differentiate between setPosition/queuePositionUpdate (+rotate), use EntityId in collision callback, fix collisions + add skiing effect
This commit is contained in:
@@ -39,8 +39,10 @@ namespace polyvox
|
||||
void transformToUnitCube(EntityId e);
|
||||
inline void updateTransform(EntityId e);
|
||||
void setScale(EntityId e, float scale);
|
||||
void setPosition(EntityId e, float x, float y, float z, bool relative);
|
||||
void setRotation(EntityId e, float rads, float x, float y, float z, float w, bool relative);
|
||||
void setPosition(EntityId e, float x, float y, float z);
|
||||
void setRotation(EntityId e, float rads, float x, float y, float z, float w);
|
||||
void queuePositionUpdate(EntityId e, float x, float y, float z, bool relative);
|
||||
void queueRotationUpdate(EntityId e, float rads, float x, float y, float z, float w, bool relative);
|
||||
const utils::Entity *getCameraEntities(EntityId e);
|
||||
size_t getCameraEntityCount(EntityId e);
|
||||
const utils::Entity *getLightEntities(EntityId e) const noexcept;
|
||||
@@ -101,7 +103,7 @@ namespace polyvox
|
||||
const char *entityName);
|
||||
int getEntityCount(EntityId entity, bool renderableOnly);
|
||||
const char* getEntityNameAt(EntityId entity, int index, bool renderableOnly);
|
||||
void addCollisionComponent(EntityId entity);
|
||||
void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(EntityId entityId));
|
||||
|
||||
private:
|
||||
AssetLoader *_assetLoader = nullptr;
|
||||
|
||||
@@ -146,8 +146,10 @@ extern "C"
|
||||
FLUTTER_PLUGIN_EXPORT void clear_assets(const void *const viewer);
|
||||
FLUTTER_PLUGIN_EXPORT bool set_material_color(void *assetManager, EntityId asset, const char *meshName, int materialIndex, const float r, const float g, const float b, const float a);
|
||||
FLUTTER_PLUGIN_EXPORT void transform_to_unit_cube(void *assetManager, EntityId asset);
|
||||
FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z, bool relative);
|
||||
FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative);
|
||||
FLUTTER_PLUGIN_EXPORT void queue_position_update(void *assetManager, EntityId asset, float x, float y, float z, bool relative);
|
||||
FLUTTER_PLUGIN_EXPORT void queue_rotation_update(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative);
|
||||
FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z);
|
||||
FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w);
|
||||
FLUTTER_PLUGIN_EXPORT void set_scale(void *assetManager, EntityId asset, float scale);
|
||||
|
||||
// Camera methods
|
||||
@@ -176,14 +178,14 @@ extern "C"
|
||||
FLUTTER_PLUGIN_EXPORT void set_post_processing(void *const viewer, bool enabled);
|
||||
FLUTTER_PLUGIN_EXPORT void pick(void *const viewer, int x, int y, EntityId *entityId);
|
||||
FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const assetManager, const EntityId entityId);
|
||||
FLUTTER_PLUGIN_EXPORT const EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name);
|
||||
FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name);
|
||||
FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const assetManager, const EntityId target, bool renderableOnly);
|
||||
FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const assetManager, const EntityId target, int index, bool renderableOnly);
|
||||
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording);
|
||||
FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory);
|
||||
FLUTTER_PLUGIN_EXPORT void ios_dummy();
|
||||
FLUTTER_PLUGIN_EXPORT void flutter_filament_free(void *ptr);
|
||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId);
|
||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId, void (*callback)(const EntityId entityId));
|
||||
FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -7,54 +7,71 @@
|
||||
#include "filament/TransformManager.h"
|
||||
#include "gltfio/FilamentAsset.h"
|
||||
#include "gltfio/FilamentInstance.h"
|
||||
#include "Log.hpp"
|
||||
|
||||
namespace polyvox
|
||||
{
|
||||
|
||||
class FloatComponentManager : public utils::SingleInstanceComponentManager<float, float, float, float> {
|
||||
|
||||
static constexpr size_t DIRECTION = 0;
|
||||
static constexpr size_t POSITION = 1;
|
||||
static constexpr size_t MAX = 2;
|
||||
static constexpr size_t SPEED = 2;
|
||||
|
||||
// void update() {
|
||||
// const auto* entities = getEntities();
|
||||
// for(int i = 0; i < getComponentCount(); i++) {
|
||||
// // const auto instance = getInstance();
|
||||
// // elementAt<POSITION>
|
||||
// // const auto component = get
|
||||
// // const auto entity = entities[i];
|
||||
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
class CollisionComponentManager : public utils::SingleInstanceComponentManager<filament::gltfio::FilamentInstance*> {
|
||||
|
||||
static constexpr size_t INSTANCE = 0;
|
||||
typedef void(*CollisionCallback)(int32_t entityId) ;
|
||||
class CollisionComponentManager : public utils::SingleInstanceComponentManager<filament::Aabb, CollisionCallback> {
|
||||
|
||||
const filament::TransformManager& _transformManager;
|
||||
public:
|
||||
CollisionComponentManager(const filament::TransformManager& transformManager) : _transformManager(transformManager) {}
|
||||
|
||||
bool collides(filament::Aabb sourceBox) {
|
||||
std::vector<filament::math::float3> collides(filament::Aabb sourceBox, filament::math::float3 direction) {
|
||||
auto sourceCorners = sourceBox.getCorners();
|
||||
const auto& entities = getEntities();
|
||||
std::vector<filament::math::float3> collision_axes;
|
||||
for(auto it = begin(); it < end(); it++) {
|
||||
auto entity = entities[it];
|
||||
|
||||
auto targetInstance = elementAt<INSTANCE>(it);
|
||||
auto entity = getEntity(it);
|
||||
auto targetXformInstance = _transformManager.getInstance(entity);
|
||||
auto targetXform = _transformManager.getWorldTransform(targetXformInstance);
|
||||
auto targetBox = targetInstance->getBoundingBox().transform(targetXform);
|
||||
auto targetBox = elementAt<0>(it).transform(targetXform);
|
||||
|
||||
// iterate over every vertex in the source AABB
|
||||
for(int i = 0; i < 8; i++) {
|
||||
// if the vertex has insersected with the target AABB
|
||||
if(targetBox.contains(sourceCorners.vertices[i]) < 0) {
|
||||
return true;
|
||||
|
||||
auto intersecting = sourceCorners.vertices[i];
|
||||
auto min = targetBox.min;
|
||||
auto max = targetBox.max;
|
||||
|
||||
float xmin = min.x - intersecting.x;
|
||||
float ymin = min.y - intersecting.y;
|
||||
float zmin = min.z - intersecting.z;
|
||||
float xmax = intersecting.x - max.x;
|
||||
float ymax = intersecting.y - max.y;
|
||||
float zmax = intersecting.z - max.z;
|
||||
|
||||
auto maxD = std::max(xmin,std::max(ymin,std::max(zmin,std::max(xmax,std::max(ymax,zmax)))));
|
||||
filament::math::float3 axis;
|
||||
if(maxD == xmin) {
|
||||
axis = {-1.0f,0.0f, 0.0f};
|
||||
} else if(maxD == ymin) {
|
||||
axis = {0.0f,-1.0f, 0.0f};
|
||||
} else if(maxD == zmin) {
|
||||
axis = {0.0f,0.0f, -1.0f};
|
||||
} else if(maxD == xmax) {
|
||||
axis = {1.0f,0.0f, 0.0f};
|
||||
} else if(maxD == ymax) {
|
||||
axis = {0.0f,1.0f, 0.0f};
|
||||
} else {
|
||||
axis = { 0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
collision_axes.push_back(axis);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(collision_axes.size() > 0) {
|
||||
auto callback = elementAt<1>(it);
|
||||
if(callback) {
|
||||
callback(utils::Entity::smuggle(entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return collision_axes;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -172,9 +172,7 @@ namespace polyvox
|
||||
sceneAsset.initialJointTransforms.push_back(jointTransform);
|
||||
}
|
||||
|
||||
utils::Entity e = EntityManager::get().create();
|
||||
|
||||
EntityId eid = Entity::smuggle(e);
|
||||
EntityId eid = Entity::smuggle(asset->getRoot());
|
||||
|
||||
_entityIdLookup.emplace(eid, _assets.size());
|
||||
_assets.push_back(sceneAsset);
|
||||
@@ -254,8 +252,7 @@ namespace polyvox
|
||||
sceneAsset.initialJointTransforms.push_back(jointTransform);
|
||||
}
|
||||
|
||||
utils::Entity e = EntityManager::get().create();
|
||||
EntityId eid = Entity::smuggle(e);
|
||||
EntityId eid = Entity::smuggle(asset->getRoot());
|
||||
|
||||
_entityIdLookup.emplace(eid, _assets.size());
|
||||
_assets.push_back(sceneAsset);
|
||||
@@ -351,7 +348,6 @@ namespace polyvox
|
||||
asset.fadeGltfAnimationIndex = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
asset.asset->getInstance()->getAnimator()->applyAnimation(animationStatus.index, elapsedInSecs);
|
||||
|
||||
if (asset.fadeGltfAnimationIndex != -1 && elapsedInSecs < asset.fadeDuration)
|
||||
@@ -361,9 +357,11 @@ namespace polyvox
|
||||
auto alpha = elapsedInSecs / asset.fadeDuration;
|
||||
asset.asset->getInstance()->getAnimator()->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha);
|
||||
}
|
||||
asset.asset->getInstance()->getAnimator()->updateBoneMatrices();
|
||||
}
|
||||
|
||||
asset.asset->getInstance()->getAnimator()->updateBoneMatrices();
|
||||
|
||||
|
||||
for (int i = (int)asset.morphAnimations.size() - 1; i >= 0; i--) {
|
||||
|
||||
auto animationStatus = asset.morphAnimations[i];
|
||||
@@ -1165,17 +1163,20 @@ namespace polyvox
|
||||
tm.setTransform(tm.getInstance(inst->getRoot()), transform);
|
||||
}
|
||||
|
||||
void AssetManager::addCollisionComponent(EntityId entityId) {
|
||||
void AssetManager::addCollisionComponent(EntityId entityId, void(*onCollisionCallback)(EntityId entityId)) {
|
||||
std::lock_guard lock(_mutex);
|
||||
const auto &pos = _entityIdLookup.find(entityId);
|
||||
if (pos == _entityIdLookup.end())
|
||||
{
|
||||
Log("ERROR: asset not found for entity.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto &asset = _assets[pos->second];
|
||||
asset.asset->getAssetInstances();
|
||||
auto collisionInstance = _collisionComponentManager->addComponent(asset.asset->getRoot());
|
||||
_collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance();
|
||||
_collisionComponentManager->elementAt<0>(collisionInstance) = asset.asset->getInstance()->getBoundingBox();
|
||||
_collisionComponentManager->elementAt<1>(collisionInstance) = onCollisionCallback;
|
||||
|
||||
}
|
||||
|
||||
void AssetManager::updateTransforms() {
|
||||
@@ -1211,20 +1212,37 @@ namespace polyvox
|
||||
rotation = newRotation;
|
||||
}
|
||||
|
||||
math::float3 relativeTranslation;
|
||||
|
||||
if(newTranslationRelative) {
|
||||
math::mat3f rotationMatrix(rotation);
|
||||
math::float3 relativeTranslation = rotationMatrix * newTranslation;
|
||||
relativeTranslation = rotationMatrix * newTranslation;
|
||||
translation += relativeTranslation;
|
||||
} else {
|
||||
relativeTranslation = newTranslation - translation;
|
||||
translation = newTranslation;
|
||||
}
|
||||
|
||||
transform = composeMatrix(translation, rotation, scale);
|
||||
auto bb = asset.asset->getBoundingBox();
|
||||
auto transformedBB = bb.transform(transform);
|
||||
if(!_collisionComponentManager->collides(transformedBB)) {
|
||||
tm.setTransform(transformInstance, transform);
|
||||
|
||||
auto collisions = _collisionComponentManager->collides(transformedBB, relativeTranslation);
|
||||
|
||||
Log("%d collisions", collisions.size());
|
||||
if(collisions.size() == 1) {
|
||||
auto globalAxis = collisions[0];
|
||||
globalAxis *= norm(relativeTranslation);
|
||||
auto newRelativeTranslation = relativeTranslation + globalAxis;
|
||||
// Log("Collision axis global : %f %f %f relativeTranslation %f %f %f relativeTranslation (after subtracting global collision vector) %f %f %f", globalAxis.x, globalAxis.y, globalAxis.z, relativeTranslation.x, relativeTranslation.y, relativeTranslation.z, newRelativeTranslation.x, newRelativeTranslation.y, newRelativeTranslation.z);
|
||||
translation -= relativeTranslation;
|
||||
translation += newRelativeTranslation;
|
||||
transform = composeMatrix(translation, rotation, scale);
|
||||
} else if(collisions.size() > 1) {
|
||||
translation -= relativeTranslation;
|
||||
transform = composeMatrix(translation, rotation, scale);
|
||||
}
|
||||
tm.setTransform(transformInstance, transform);
|
||||
}
|
||||
_transformUpdates.clear();
|
||||
}
|
||||
@@ -1243,9 +1261,59 @@ namespace polyvox
|
||||
_transformUpdates[entity] = curr;
|
||||
}
|
||||
|
||||
void AssetManager::setPosition(EntityId entity, float x, float y, float z, bool relative)
|
||||
void AssetManager::setPosition(EntityId entityId, float x, float y, float z)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto entity = Entity::import(entityId);
|
||||
if(entity.isNull()) {
|
||||
Log("Failed to find entity under ID %d", entityId);
|
||||
return;
|
||||
}
|
||||
auto &tm = _engine->getTransformManager();
|
||||
|
||||
auto transformInstance = tm.getInstance(entity);
|
||||
auto transform = tm.getTransform(transformInstance);
|
||||
math::float3 translation;
|
||||
math::quatf rotation;
|
||||
math::float3 scale;
|
||||
|
||||
decomposeMatrix(transform, &translation, &rotation, &scale);
|
||||
translation = math::float3(x,y,z);
|
||||
auto newTransform = composeMatrix(translation, rotation, scale);
|
||||
tm.setTransform(transformInstance, newTransform);
|
||||
}
|
||||
|
||||
void AssetManager::setRotation(EntityId entityId, float rads, float x, float y, float z, float w)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
auto entity = Entity::import(entityId);
|
||||
if(entity.isNull()) {
|
||||
Log("Failed to find entity under ID %d", entityId);
|
||||
return;
|
||||
}
|
||||
auto &tm = _engine->getTransformManager();
|
||||
|
||||
auto transformInstance = tm.getInstance(entity);
|
||||
auto transform = tm.getTransform(transformInstance);
|
||||
math::float3 translation;
|
||||
math::quatf rotation;
|
||||
math::float3 scale;
|
||||
|
||||
decomposeMatrix(transform, &translation, &rotation, &scale);
|
||||
rotation = math::quatf(w,x,y,z);
|
||||
auto newTransform = composeMatrix(translation, rotation, scale);
|
||||
tm.setTransform(transformInstance, newTransform);
|
||||
}
|
||||
|
||||
void AssetManager::queuePositionUpdate(EntityId entity, float x, float y, float z, bool relative)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
|
||||
if(!relative) {
|
||||
|
||||
}
|
||||
const auto &pos = _transformUpdates.find(entity);
|
||||
if (pos == _transformUpdates.end())
|
||||
{
|
||||
@@ -1262,7 +1330,7 @@ namespace polyvox
|
||||
_transformUpdates[entity] = curr;
|
||||
}
|
||||
|
||||
void AssetManager::setRotation(EntityId entity, float rads, float x, float y, float z, float w, bool relative)
|
||||
void AssetManager::queueRotationUpdate(EntityId entity, float rads, float x, float y, float z, float w, bool relative)
|
||||
{
|
||||
std::lock_guard lock(_mutex);
|
||||
const auto &pos = _transformUpdates.find(entity);
|
||||
|
||||
@@ -470,14 +470,14 @@ extern "C"
|
||||
((AssetManager *)assetManager)->transformToUnitCube(asset);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z, bool relative)
|
||||
FLUTTER_PLUGIN_EXPORT void set_position(void *assetManager, EntityId asset, float x, float y, float z)
|
||||
{
|
||||
((AssetManager *)assetManager)->setPosition(asset, x, y, z, relative);
|
||||
((AssetManager *)assetManager)->setPosition(asset, x, y, z);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative)
|
||||
FLUTTER_PLUGIN_EXPORT void set_rotation(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w)
|
||||
{
|
||||
((AssetManager *)assetManager)->setRotation(asset, rads, x, y, z, w, relative);
|
||||
((AssetManager *)assetManager)->setRotation(asset, rads, x, y, z, w);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void set_scale(void *assetManager, EntityId asset, float scale)
|
||||
@@ -485,6 +485,16 @@ extern "C"
|
||||
((AssetManager *)assetManager)->setScale(asset, scale);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void queue_position_update(void *assetManager, EntityId asset, float x, float y, float z, bool relative)
|
||||
{
|
||||
((AssetManager *)assetManager)->queuePositionUpdate(asset, x, y, z, relative);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void queue_rotation_update(void *assetManager, EntityId asset, float rads, float x, float y, float z, float w, bool relative)
|
||||
{
|
||||
((AssetManager *)assetManager)->queueRotationUpdate(asset, rads, x, y, z, w, relative);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void stop_animation(void *assetManager, EntityId asset, int index)
|
||||
{
|
||||
((AssetManager *)assetManager)->stopAnimation(asset, index);
|
||||
@@ -537,13 +547,17 @@ extern "C"
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId) {
|
||||
((AssetManager*)assetManager)->addCollisionComponent(entityId);
|
||||
FLUTTER_PLUGIN_EXPORT void add_collision_component(void *const assetManager, EntityId entityId, void (*onCollisionCallback)(const EntityId entityId)) {
|
||||
((AssetManager*)assetManager)->addCollisionComponent(entityId, onCollisionCallback);
|
||||
}
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) {
|
||||
return ((FilamentViewer*)viewer)->createGeometry(vertices, (size_t)numVertices, indices, numIndices, materialPath);
|
||||
}
|
||||
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const assetManager, const EntityId parent, const char* name) {
|
||||
auto entity = ((AssetManager*)assetManager)->findChildEntityByName(parent, name);
|
||||
return Entity::smuggle(entity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
|
||||
@@ -79,7 +80,7 @@ class EntityTransformController {
|
||||
|
||||
double rads = 0.0;
|
||||
if (_rotY != 0) {
|
||||
rads = _rotY! * pi / 1000;
|
||||
rads = _rotY * pi / 1000;
|
||||
var rotY = v.Quaternion.axisAngle(v.Vector3(0, 1, 0), rads).normalized();
|
||||
_rotation = rotY;
|
||||
updateRotation = true;
|
||||
@@ -87,12 +88,13 @@ class EntityTransformController {
|
||||
}
|
||||
|
||||
if (updateTranslation) {
|
||||
await controller.setPosition(
|
||||
await controller.queuePositionUpdate(
|
||||
_entity, _position.x, _position.y, _position.z,
|
||||
relative: true);
|
||||
}
|
||||
if (updateRotation) {
|
||||
await controller.setRotationQuat(_entity, _rotation, relative: true);
|
||||
await controller.queueRotationUpdateQuat(_entity, _rotation,
|
||||
relative: true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,43 +107,45 @@ class EntityTransformController {
|
||||
}
|
||||
|
||||
bool _playingForwardAnimation = false;
|
||||
bool _playingBackwardAnimation = false;
|
||||
|
||||
void forwardPressed() async {
|
||||
_forward = true;
|
||||
if (forwardAnimationIndex != null) {
|
||||
if (!_playingForwardAnimation) {
|
||||
await controller.playAnimation(_entity, forwardAnimationIndex!,
|
||||
loop: true);
|
||||
_playingForwardAnimation = true;
|
||||
}
|
||||
if (forwardAnimationIndex != null && !_playingForwardAnimation) {
|
||||
await controller.playAnimation(_entity, forwardAnimationIndex!,
|
||||
loop: true, replaceActive: false);
|
||||
_playingForwardAnimation = true;
|
||||
}
|
||||
}
|
||||
|
||||
Timer? _forwardTimer;
|
||||
Timer? _backwardsTimer;
|
||||
Timer? _strafeLeftTimer;
|
||||
Timer? _strafeRightTimer;
|
||||
|
||||
void forwardReleased() async {
|
||||
_forwardTimer?.cancel();
|
||||
_forwardTimer = Timer(Duration(milliseconds: 50), () async {
|
||||
_forward = false;
|
||||
_forward = false;
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
if (!_forward) {
|
||||
_playingForwardAnimation = false;
|
||||
if (forwardAnimationIndex != null) {
|
||||
await controller.stopAnimation(_entity, forwardAnimationIndex!);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void backPressed() {
|
||||
void backPressed() async {
|
||||
_back = true;
|
||||
if (forwardAnimationIndex != null) {
|
||||
if (!_playingBackwardAnimation) {
|
||||
await controller.playAnimation(_entity, forwardAnimationIndex!,
|
||||
loop: true, replaceActive: false, reverse: true);
|
||||
_playingBackwardAnimation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void backReleased() async {
|
||||
_backwardsTimer?.cancel();
|
||||
_backwardsTimer = Timer(Duration(milliseconds: 50), () {
|
||||
_back = false;
|
||||
});
|
||||
_back = false;
|
||||
if (forwardAnimationIndex != null) {
|
||||
await controller.stopAnimation(_entity, forwardAnimationIndex!);
|
||||
}
|
||||
_playingBackwardAnimation = false;
|
||||
}
|
||||
|
||||
void strafeLeftPressed() {
|
||||
@@ -149,10 +153,7 @@ class EntityTransformController {
|
||||
}
|
||||
|
||||
void strafeLeftReleased() async {
|
||||
_strafeLeftTimer?.cancel();
|
||||
_strafeLeftTimer = Timer(Duration(milliseconds: 50), () {
|
||||
_strafeLeft = false;
|
||||
});
|
||||
_strafeLeft = false;
|
||||
}
|
||||
|
||||
void strafeRightPressed() {
|
||||
@@ -160,9 +161,21 @@ class EntityTransformController {
|
||||
}
|
||||
|
||||
void strafeRightReleased() async {
|
||||
_strafeRightTimer?.cancel();
|
||||
_strafeRightTimer = Timer(Duration(milliseconds: 50), () {
|
||||
_strafeRight = false;
|
||||
});
|
||||
_strafeRight = false;
|
||||
}
|
||||
|
||||
void Function()? _mouse1DownCallback;
|
||||
void onMouse1Down(void Function() callback) {
|
||||
_mouse1DownCallback = callback;
|
||||
}
|
||||
|
||||
void mouse1Down() async {
|
||||
_mouse1DownCallback?.call();
|
||||
}
|
||||
|
||||
void mouse1Up() async {}
|
||||
|
||||
void mouse2Up() async {}
|
||||
|
||||
void mouse2Down() async {}
|
||||
}
|
||||
|
||||
@@ -449,9 +449,41 @@ abstract class FilamentController {
|
||||
Future transformToUnitCube(FilamentEntity entity);
|
||||
|
||||
///
|
||||
/// Sets the world space position for [entity] to the given coordinates.
|
||||
/// Directly sets the world space position for [entity] to the given coordinates, skipping all collision detection.
|
||||
///
|
||||
Future setPosition(FilamentEntity entity, double x, double y, double z,
|
||||
Future setPosition(FilamentEntity entity, double x, double y, double z);
|
||||
|
||||
///
|
||||
/// Directly sets the scale for [entity], skipping all collision detection.
|
||||
///
|
||||
Future setScale(FilamentEntity entity, double scale);
|
||||
|
||||
///
|
||||
/// Directly sets the rotation for [entity] to [rads] around the axis {x,y,z}, skipping all collision detection.
|
||||
///
|
||||
Future setRotation(
|
||||
FilamentEntity entity, double rads, double x, double y, double z);
|
||||
|
||||
///
|
||||
/// Queues an update to the worldspace position for [entity] to {x,y,z}.
|
||||
/// The actual update will occur on the next frame, and will be subject to collision detection.
|
||||
///
|
||||
Future queuePositionUpdate(
|
||||
FilamentEntity entity, double x, double y, double z,
|
||||
{bool relative = false});
|
||||
|
||||
///
|
||||
/// Queues an update to the worldspace rotation for [entity].
|
||||
/// The actual update will occur on the next frame, and will be subject to collision detection.
|
||||
///
|
||||
Future queueRotationUpdate(
|
||||
FilamentEntity entity, double rads, double x, double y, double z,
|
||||
{bool relative = false});
|
||||
|
||||
///
|
||||
/// Same as [queueRotationUpdate].
|
||||
///
|
||||
Future queueRotationUpdateQuat(FilamentEntity entity, Quaternion quat,
|
||||
{bool relative = false});
|
||||
|
||||
///
|
||||
@@ -459,23 +491,10 @@ abstract class FilamentController {
|
||||
///
|
||||
Future setPostProcessing(bool enabled);
|
||||
|
||||
///
|
||||
/// Sets the scale for the given entity.
|
||||
///
|
||||
Future setScale(FilamentEntity entity, double scale);
|
||||
|
||||
///
|
||||
/// Sets the rotation for [entity] to [rads] around the axis {x,y,z}.
|
||||
///
|
||||
Future setRotation(
|
||||
FilamentEntity entity, double rads, double x, double y, double z,
|
||||
{bool relative = false});
|
||||
|
||||
///
|
||||
/// Sets the rotation for [entity] to the specified quaternion.
|
||||
///
|
||||
Future setRotationQuat(FilamentEntity entity, Quaternion rotation,
|
||||
{bool relative = false});
|
||||
Future setRotationQuat(FilamentEntity entity, Quaternion rotation);
|
||||
|
||||
///
|
||||
/// Reveal the node [meshName] under [entity]. Only applicable if [hide] had previously been called; this is a no-op otherwise.
|
||||
@@ -544,7 +563,8 @@ abstract class FilamentController {
|
||||
/// At the moment, this is only relevant when controlling a different entity's transform.
|
||||
/// If there is a collision between the controlled entity and [collidableEntity], the transform will not be updated.
|
||||
///
|
||||
Future addCollisionComponent(FilamentEntity collidableEntity);
|
||||
Future addCollisionComponent(FilamentEntity collidableEntity,
|
||||
{void Function(int entityId)? callback});
|
||||
|
||||
///
|
||||
/// Creates a (renderable) entity with the specified geometry and adds to the scene.
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/animations/animation_data.dart';
|
||||
import 'package:flutter_filament/generated_bindings.dart';
|
||||
import 'package:flutter_filament/hardware/hardware_keyboard_listener.dart';
|
||||
import 'package:flutter_filament/hardware/hardware_keyboard_poll.dart';
|
||||
import 'package:flutter_filament/rendering_surface.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
@@ -1051,13 +1052,33 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
|
||||
@override
|
||||
Future setPosition(FilamentEntity entity, double x, double y, double z,
|
||||
{bool relative = false}) async {
|
||||
Future setPosition(
|
||||
FilamentEntity entity, double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
|
||||
set_position(_assetManager!, entity, x, y, z, relative);
|
||||
set_position(_assetManager!, entity, x, y, z);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRotation(
|
||||
FilamentEntity entity, double rads, double x, double y, double z) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
var quat = Quaternion.axisAngle(Vector3(x, y, z), rads);
|
||||
await setRotationQuat(entity, quat);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRotationQuat(FilamentEntity entity, Quaternion rotation,
|
||||
{bool relative = false}) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
set_rotation(_assetManager!, entity, rotation.radians, rotation.x,
|
||||
rotation.y, rotation.z, rotation.w);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1069,23 +1090,33 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRotation(
|
||||
Future queuePositionUpdate(
|
||||
FilamentEntity entity, double x, double y, double z,
|
||||
{bool relative = false}) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
|
||||
queue_position_update(_assetManager!, entity, x, y, z, relative);
|
||||
}
|
||||
|
||||
@override
|
||||
Future queueRotationUpdate(
|
||||
FilamentEntity entity, double rads, double x, double y, double z,
|
||||
{bool relative = false}) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
var quat = Quaternion.axisAngle(Vector3(x, y, z), rads);
|
||||
await setRotationQuat(entity, quat, relative: relative);
|
||||
await queueRotationUpdateQuat(entity, quat, relative: relative);
|
||||
}
|
||||
|
||||
@override
|
||||
Future setRotationQuat(FilamentEntity entity, Quaternion rotation,
|
||||
Future queueRotationUpdateQuat(FilamentEntity entity, Quaternion rotation,
|
||||
{bool relative = false}) async {
|
||||
if (_viewer == null) {
|
||||
throw Exception("No viewer available, ignoring");
|
||||
}
|
||||
set_rotation(_assetManager!, entity, rotation.radians, rotation.x,
|
||||
queue_rotation_update(_assetManager!, entity, rotation.radians, rotation.x,
|
||||
rotation.y, rotation.z, rotation.w, relative);
|
||||
}
|
||||
|
||||
@@ -1359,12 +1390,20 @@ class FilamentControllerFFI extends FilamentController {
|
||||
}
|
||||
|
||||
@override
|
||||
Future addCollisionComponent(FilamentEntity entity) async {
|
||||
Future addCollisionComponent(FilamentEntity entity,
|
||||
{void Function(int entityId)? callback}) async {
|
||||
if (_assetManager == null) {
|
||||
throw Exception("AssetManager must be non-null");
|
||||
}
|
||||
// ignore: sdk_version_since
|
||||
|
||||
add_collision_component(_assetManager!, entity);
|
||||
if (callback != null) {
|
||||
var ptr =
|
||||
NativeCallable<Void Function(Int32 entityId)>.listener(callback);
|
||||
add_collision_component(_assetManager!, entity, ptr.nativeFunction);
|
||||
} else {
|
||||
add_collision_component(_assetManager!, entity, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user