allow multiple simultaneous gltf animatiosn
This commit is contained in:
@@ -372,13 +372,13 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
|
|||||||
// apply_weights(assetManager, asset, entityName, UnsafeMutablePointer(&weights), Int32(count))
|
// apply_weights(assetManager, asset, entityName, UnsafeMutablePointer(&weights), Int32(count))
|
||||||
result(true)
|
result(true)
|
||||||
case "setMorphTargetWeights":
|
case "setMorphTargetWeights":
|
||||||
guard let args = call.arguments as? [Any], args.count == 7,
|
guard let args = call.arguments as? [Any], args.count == 5,
|
||||||
let assetManager = args[0] as? Int64,
|
let assetManager = args[0] as? Int64,
|
||||||
let asset = args[1] as? EntityId,
|
let asset = args[1] as? EntityId,
|
||||||
let entityName = args[2] as? String,
|
let entityName = args[2] as? String,
|
||||||
let morphData = args[3] as? FlutterStandardTypedData,
|
let morphData = args[3] as? FlutterStandardTypedData,
|
||||||
let numMorphWeights = args[4] as? Int else {
|
let numMorphWeights = args[4] as? Int else {
|
||||||
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for set_morph_animation", details: nil))
|
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for setMorphTargetWeights", details: nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let success = morphData.data.withUnsafeBytes { buffer in
|
let success = morphData.data.withUnsafeBytes { buffer in
|
||||||
@@ -434,18 +434,18 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
|
|||||||
result(true)
|
result(true)
|
||||||
|
|
||||||
case "playAnimation":
|
case "playAnimation":
|
||||||
guard let args = call.arguments as? [Any], args.count == 6,
|
guard let args = call.arguments as? [Any], args.count == 7,
|
||||||
let assetManager = args[0] as? Int64,
|
let assetManager = args[0] as? Int64,
|
||||||
let asset = args[1] as? EntityId,
|
let asset = args[1] as? EntityId,
|
||||||
let index = args[2] as? Int,
|
let index = args[2] as? Int,
|
||||||
let loop = args[3] as? Bool,
|
let loop = args[3] as? Bool,
|
||||||
let reverse = args[4] as? Bool,
|
let reverse = args[4] as? Bool,
|
||||||
let crossfade = args[5] as? Float else {
|
let replaceActive = args[5] as? Bool,
|
||||||
|
let crossfade = args[6] as? Double else {
|
||||||
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for play_animation", details: nil))
|
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for play_animation", details: nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
play_animation(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, Int32(index), loop, reverse, replaceActive, Float(crossfade))
|
||||||
play_animation(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, Int32(index), loop, reverse, crossfade)
|
|
||||||
result(true)
|
result(true)
|
||||||
case "getAnimationDuration":
|
case "getAnimationDuration":
|
||||||
guard let args = call.arguments as? [Any], args.count == 3,
|
guard let args = call.arguments as? [Any], args.count == 3,
|
||||||
@@ -546,10 +546,12 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
|
|||||||
}
|
}
|
||||||
let count = get_morph_target_name_count(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, meshName)
|
let count = get_morph_target_name_count(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, meshName)
|
||||||
var names:[String] = []
|
var names:[String] = []
|
||||||
for i in 0...count - 1 {
|
if count > 0 {
|
||||||
var buffer = [CChar](repeating: 0, count: 256) // Assuming max name length of 256 for simplicity
|
for i in 0...count - 1 {
|
||||||
get_morph_target_name(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, meshName, &buffer, Int32(i))
|
var buffer = [CChar](repeating: 0, count: 256) // Assuming max name length of 256 for simplicity
|
||||||
names.append(String(cString:buffer))
|
get_morph_target_name(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, meshName, &buffer, Int32(i))
|
||||||
|
names.append(String(cString:buffer))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result(names)
|
result(names)
|
||||||
case "getMorphTargetNameCount":
|
case "getMorphTargetNameCount":
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace polyvox {
|
|||||||
const char** const meshName,
|
const char** const meshName,
|
||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs);
|
float frameLengthInMs);
|
||||||
void playAnimation(EntityId e, int index, bool loop, bool reverse, float crossfade = 0.3f);
|
void playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade = 0.3f);
|
||||||
void stopAnimation(EntityId e, int index);
|
void stopAnimation(EntityId e, int index);
|
||||||
void setMorphTargetWeights(const char* const entityName, float *weights, int count);
|
void setMorphTargetWeights(const char* const entityName, float *weights, int count);
|
||||||
void loadTexture(EntityId entity, const char* resourcePath, int renderableIndex);
|
void loadTexture(EntityId entity, const char* resourcePath, int renderableIndex);
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void set_bone_animation(
|
|||||||
int numMeshTargets,
|
int numMeshTargets,
|
||||||
float frameLengthInMs);
|
float frameLengthInMs);
|
||||||
|
|
||||||
void play_animation(void* assetManager, EntityId asset, int index, bool loop, bool reverse, float crossfade);
|
void play_animation(void* assetManager, EntityId asset, int index, bool loop, bool reverse, bool replaceActive, float crossfade);
|
||||||
void set_animation_frame(void* assetManager, EntityId asset, int animationIndex, int animationFrame);
|
void set_animation_frame(void* assetManager, EntityId asset, int animationIndex, int animationFrame);
|
||||||
void stop_animation(void* assetManager, EntityId asset, int index);
|
void stop_animation(void* assetManager, EntityId asset, int index);
|
||||||
int get_animation_count(void* assetManager, EntityId asset);
|
int get_animation_count(void* assetManager, EntityId asset);
|
||||||
|
|||||||
@@ -31,12 +31,17 @@ namespace polyvox {
|
|||||||
|
|
||||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
|
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_point_t;
|
||||||
|
|
||||||
|
enum AnimationType {
|
||||||
|
MORPH, BONE, GLTF
|
||||||
|
};
|
||||||
|
|
||||||
struct AnimationStatus {
|
struct AnimationStatus {
|
||||||
time_point_t mStart = time_point_t::max();
|
time_point_t mStart = time_point_t::max();
|
||||||
bool mLoop = false;
|
bool mLoop = false;
|
||||||
bool mReverse = false;
|
bool mReverse = false;
|
||||||
float mDuration = 0;
|
float mDuration = 0;
|
||||||
bool mActive = false;
|
AnimationType type;
|
||||||
|
int gltfIndex = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -73,11 +78,9 @@ namespace polyvox {
|
|||||||
FilamentAsset* mAsset = nullptr;
|
FilamentAsset* mAsset = nullptr;
|
||||||
Animator* mAnimator = nullptr;
|
Animator* mAnimator = nullptr;
|
||||||
|
|
||||||
// fixed-sized array containing pointers to the active morph, bone and GLTF animations.
|
// vector containing AnimationStatus structs for the morph, bone and/or glTF animations.
|
||||||
AnimationStatus mAnimations[3];
|
vector<AnimationStatus> mAnimations;
|
||||||
// the index of the active glTF animation in the Filament Asset animations array
|
|
||||||
// if no glTF animation is active, this is -1
|
|
||||||
int gltfAnimationIndex = -1;
|
|
||||||
// the index of the last active glTF animation,
|
// the index of the last active glTF animation,
|
||||||
// used to cross-fade
|
// used to cross-fade
|
||||||
int fadeGltfAnimationIndex = -1;
|
int fadeGltfAnimationIndex = -1;
|
||||||
|
|||||||
@@ -243,104 +243,67 @@ void AssetManager::updateAnimations() {
|
|||||||
|
|
||||||
for (auto& asset : _assets) {
|
for (auto& asset : _assets) {
|
||||||
|
|
||||||
if(!asset.mAnimating) {
|
vector<AnimationStatus> completed;
|
||||||
continue;
|
for(auto& anim : asset.mAnimations) {
|
||||||
}
|
|
||||||
asset.mAnimating = false;
|
|
||||||
|
|
||||||
// GLTF animations
|
|
||||||
AnimationStatus& anim = asset.mAnimations[2];
|
|
||||||
|
|
||||||
if(anim.mActive) {
|
|
||||||
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - anim.mStart).count()) / 1000.0f;
|
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - anim.mStart).count()) / 1000.0f;
|
||||||
|
|
||||||
if(anim.mLoop || elapsed < anim.mDuration) {
|
if(anim.mLoop || elapsed < anim.mDuration) {
|
||||||
asset.mAnimator->applyAnimation(asset.gltfAnimationIndex, elapsed);
|
|
||||||
asset.mAnimating = true;
|
switch(anim.type) {
|
||||||
if(asset.fadeGltfAnimationIndex != -1 && elapsed < asset.fadeDuration) {
|
case AnimationType::GLTF: {
|
||||||
// cross-fade
|
asset.mAnimator->applyAnimation(anim.gltfIndex, elapsed);
|
||||||
auto fadeFromTime = asset.fadeOutAnimationStart + elapsed;
|
if(asset.fadeGltfAnimationIndex != -1 && elapsed < asset.fadeDuration) {
|
||||||
auto alpha = elapsed / asset.fadeDuration;
|
// cross-fade
|
||||||
asset.mAnimator->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha);
|
auto fadeFromTime = asset.fadeOutAnimationStart + elapsed;
|
||||||
|
auto alpha = elapsed / asset.fadeDuration;
|
||||||
|
asset.mAnimator->applyCrossFade(asset.fadeGltfAnimationIndex, fadeFromTime, alpha);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AnimationType::MORPH: {
|
||||||
|
int lengthInFrames = static_cast<int>(
|
||||||
|
anim.mDuration * 1000.0f /
|
||||||
|
asset.mMorphAnimationBuffer.mFrameLengthInMs
|
||||||
|
);
|
||||||
|
int frameNumber = static_cast<int>(elapsed * 1000.0f / asset.mMorphAnimationBuffer.mFrameLengthInMs) % lengthInFrames;
|
||||||
|
// offset from the end if reverse
|
||||||
|
if(anim.mReverse) {
|
||||||
|
frameNumber = lengthInFrames - frameNumber;
|
||||||
|
}
|
||||||
|
// set the weights appropriately
|
||||||
|
rm.setMorphWeights(
|
||||||
|
rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget),
|
||||||
|
asset.mMorphAnimationBuffer.mFrameData.data() + (frameNumber * asset.mMorphAnimationBuffer.mNumMorphWeights),
|
||||||
|
asset.mMorphAnimationBuffer.mNumMorphWeights
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AnimationType::BONE: {
|
||||||
|
int lengthInFrames = static_cast<int>(
|
||||||
|
anim.mDuration * 1000.0f /
|
||||||
|
asset.mBoneAnimationBuffer.mFrameLengthInMs
|
||||||
|
);
|
||||||
|
int frameNumber = static_cast<int>(elapsed * 1000.0f / asset.mBoneAnimationBuffer.mFrameLengthInMs) % lengthInFrames;
|
||||||
|
|
||||||
|
// offset from the end if reverse
|
||||||
|
if(anim.mReverse) {
|
||||||
|
frameNumber = lengthInFrames - frameNumber;
|
||||||
|
}
|
||||||
|
setBoneTransform(
|
||||||
|
asset,
|
||||||
|
frameNumber
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// animation has completed
|
||||||
} else {
|
} else {
|
||||||
// stop
|
completed.push_back(anim);
|
||||||
anim.mStart = time_point_t::max();
|
|
||||||
anim.mActive = false;
|
|
||||||
asset.gltfAnimationIndex = -1;
|
|
||||||
asset.fadeGltfAnimationIndex = -1;
|
asset.fadeGltfAnimationIndex = -1;
|
||||||
}
|
}
|
||||||
asset.mAnimator->updateBoneMatrices();
|
asset.mAnimator->updateBoneMatrices();
|
||||||
}
|
}
|
||||||
|
|
||||||
// dynamic morph animation
|
|
||||||
AnimationStatus& morphAnimation = asset.mAnimations[0];
|
|
||||||
|
|
||||||
if(morphAnimation.mActive) {
|
|
||||||
|
|
||||||
auto elapsed = float(
|
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
now - morphAnimation.mStart
|
|
||||||
).count()) / 1000.0f;
|
|
||||||
int lengthInFrames = static_cast<int>(
|
|
||||||
morphAnimation.mDuration * 1000.0f /
|
|
||||||
asset.mMorphAnimationBuffer.mFrameLengthInMs
|
|
||||||
);
|
|
||||||
|
|
||||||
// if more time has elapsed than the animation duration && we aren't looping, then mark the animation as complete
|
|
||||||
if(elapsed >= morphAnimation.mDuration && !morphAnimation.mLoop) {
|
|
||||||
morphAnimation.mStart = time_point_t::max();
|
|
||||||
morphAnimation.mActive = false;
|
|
||||||
} else {
|
|
||||||
asset.mAnimating = true;
|
|
||||||
int frameNumber = static_cast<int>(elapsed * 1000.0f / asset.mMorphAnimationBuffer.mFrameLengthInMs) % lengthInFrames;
|
|
||||||
// offset from the end if reverse
|
|
||||||
if(morphAnimation.mReverse) {
|
|
||||||
frameNumber = lengthInFrames - frameNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the weights appropriately
|
|
||||||
rm.setMorphWeights(
|
|
||||||
rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget),
|
|
||||||
asset.mMorphAnimationBuffer.mFrameData.data() + (frameNumber * asset.mMorphAnimationBuffer.mNumMorphWeights),
|
|
||||||
asset.mMorphAnimationBuffer.mNumMorphWeights
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// dynamic bone animations
|
|
||||||
AnimationStatus boneAnimation = asset.mAnimations[1];
|
|
||||||
if(boneAnimation.mActive) {
|
|
||||||
auto elapsed = float(
|
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
now - boneAnimation.mStart
|
|
||||||
).count()) / 1000.0f;
|
|
||||||
int lengthInFrames = static_cast<int>(
|
|
||||||
boneAnimation.mDuration * 1000.0f /
|
|
||||||
asset.mBoneAnimationBuffer.mFrameLengthInMs
|
|
||||||
);
|
|
||||||
|
|
||||||
// if more time has elapsed than the animation duration and we are not looping, mark the animation as complete
|
|
||||||
if(elapsed >= boneAnimation.mDuration && !boneAnimation.mLoop) {
|
|
||||||
boneAnimation.mStart = time_point_t::max();
|
|
||||||
boneAnimation.mActive = false;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
asset.mAnimating = true;
|
|
||||||
int frameNumber = static_cast<int>(elapsed * 1000.0f / asset.mBoneAnimationBuffer.mFrameLengthInMs) % lengthInFrames;
|
|
||||||
|
|
||||||
// offset from the end if reverse
|
|
||||||
if(boneAnimation.mReverse) {
|
|
||||||
frameNumber = lengthInFrames - frameNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBoneTransform(
|
|
||||||
asset,
|
|
||||||
frameNumber
|
|
||||||
);
|
|
||||||
}
|
|
||||||
asset.mAnimator->updateBoneMatrices();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +366,7 @@ void AssetManager::remove(EntityId entityId) {
|
|||||||
}
|
}
|
||||||
EntityManager& em = EntityManager::get();
|
EntityManager& em = EntityManager::get();
|
||||||
em.destroy(Entity::import(entityId));
|
em.destroy(Entity::import(entityId));
|
||||||
sceneAsset.mAsset = nullptr; // still need to remove this somewhere...
|
sceneAsset.mAsset = nullptr; // still need to remove sceneAsset somewhere...
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::setMorphTargetWeights(EntityId entityId, const char* const entityName, const float* const weights, const int count) {
|
void AssetManager::setMorphTargetWeights(EntityId entityId, const char* const entityName, const float* const weights, const int count) {
|
||||||
@@ -427,8 +390,6 @@ void AssetManager::setMorphTargetWeights(EntityId entityId, const char* const en
|
|||||||
weights,
|
weights,
|
||||||
count
|
count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::Entity AssetManager::findEntityByName(SceneAsset asset, const char* entityName) {
|
utils::Entity AssetManager::findEntityByName(SceneAsset asset, const char* entityName) {
|
||||||
@@ -444,7 +405,6 @@ utils::Entity AssetManager::findEntityByName(SceneAsset asset, const char* entit
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool AssetManager::setMorphAnimationBuffer(
|
bool AssetManager::setMorphAnimationBuffer(
|
||||||
EntityId entityId,
|
EntityId entityId,
|
||||||
const char* entityName,
|
const char* entityName,
|
||||||
@@ -476,11 +436,11 @@ bool AssetManager::setMorphAnimationBuffer(
|
|||||||
asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs;
|
asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs;
|
||||||
asset.mMorphAnimationBuffer.mNumMorphWeights = numMorphWeights;
|
asset.mMorphAnimationBuffer.mNumMorphWeights = numMorphWeights;
|
||||||
|
|
||||||
AnimationStatus& animation = asset.mAnimations[0];
|
AnimationStatus animation;
|
||||||
animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f;
|
animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f;
|
||||||
animation.mStart = high_resolution_clock::now();
|
animation.mStart = high_resolution_clock::now();
|
||||||
animation.mActive = true;
|
animation.type = AnimationType::MORPH;
|
||||||
asset.mAnimating = true;
|
asset.mAnimations.push_back(animation);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,7 +489,6 @@ bool AssetManager::setBoneAnimationBuffer(
|
|||||||
animationBuffer.mBaseTransforms.resize(numBones);
|
animationBuffer.mBaseTransforms.resize(numBones);
|
||||||
|
|
||||||
for(int i = 0; i < numBones; i++) {
|
for(int i = 0; i < numBones; i++) {
|
||||||
Log("Bone %s", boneNames[i]);
|
|
||||||
for(int j = 0; j < numJoints; j++) {
|
for(int j = 0; j < numJoints; j++) {
|
||||||
const char* jointName = _ncm->getName(_ncm->getInstance(joints[j]));
|
const char* jointName = _ncm->getName(_ncm->getInstance(joints[j]));
|
||||||
if(strcmp(jointName, boneNames[i]) == 0) {
|
if(strcmp(jointName, boneNames[i]) == 0) {
|
||||||
@@ -571,18 +530,18 @@ bool AssetManager::setBoneAnimationBuffer(
|
|||||||
animationBuffer.mMeshTargets.push_back(entity);
|
animationBuffer.mMeshTargets.push_back(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& animation = asset.mAnimations[1];
|
AnimationStatus animation;
|
||||||
animation.mStart = std::chrono::high_resolution_clock::now();
|
animation.mStart = std::chrono::high_resolution_clock::now();
|
||||||
animation.mActive = true;
|
|
||||||
animation.mReverse = false;
|
animation.mReverse = false;
|
||||||
animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f;
|
animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f;
|
||||||
asset.mAnimating = true;
|
animation.type = AnimationType::BONE;
|
||||||
|
asset.mAnimations.push_back(animation);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse, float crossfade) {
|
void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse, bool replaceActive, float crossfade) {
|
||||||
const auto& pos = _entityIdLookup.find(e);
|
const auto& pos = _entityIdLookup.find(e);
|
||||||
if(pos == _entityIdLookup.end()) {
|
if(pos == _entityIdLookup.end()) {
|
||||||
Log("ERROR: asset not found for entity.");
|
Log("ERROR: asset not found for entity.");
|
||||||
@@ -590,24 +549,44 @@ void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse,
|
|||||||
}
|
}
|
||||||
auto& asset = _assets[pos->second];
|
auto& asset = _assets[pos->second];
|
||||||
|
|
||||||
if(asset.gltfAnimationIndex != -1) {
|
if(replaceActive) {
|
||||||
asset.fadeGltfAnimationIndex = asset.gltfAnimationIndex;
|
vector<int> active;
|
||||||
asset.fadeDuration = crossfade;
|
for(int i = 0; i < asset.mAnimations.size(); i++) {
|
||||||
auto now = high_resolution_clock::now();
|
if(asset.mAnimations[i].type == AnimationType::GLTF) {
|
||||||
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - asset.mAnimations[2].mStart).count()) / 1000.0f;
|
active.push_back(i);
|
||||||
asset.fadeOutAnimationStart = elapsed;
|
}
|
||||||
|
}
|
||||||
|
if(active.size() > 0) {
|
||||||
|
auto& last = asset.mAnimations[active.back()];
|
||||||
|
asset.fadeGltfAnimationIndex = last.gltfIndex;
|
||||||
|
asset.fadeDuration = crossfade;
|
||||||
|
auto now = high_resolution_clock::now();
|
||||||
|
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - last.mStart).count()) / 1000.0f;
|
||||||
|
asset.fadeOutAnimationStart = elapsed;
|
||||||
|
for(int j = active.size() - 1; j >= 0; j--) {
|
||||||
|
asset.mAnimations.erase(asset.mAnimations.begin() + active[j]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
asset.fadeGltfAnimationIndex = -1;
|
||||||
|
asset.fadeDuration = 0.0f;
|
||||||
|
}
|
||||||
|
} else if(crossfade > 0) {
|
||||||
|
Log("ERROR: crossfade only supported when replaceActive is true.");
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
asset.fadeGltfAnimationIndex = -1;
|
asset.fadeGltfAnimationIndex = -1;
|
||||||
asset.fadeDuration = 0.0f;
|
asset.fadeDuration = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
asset.gltfAnimationIndex = index;
|
AnimationStatus animation;
|
||||||
asset.mAnimations[2].mStart = std::chrono::high_resolution_clock::now();
|
animation.gltfIndex = index;
|
||||||
asset.mAnimations[2].mLoop = loop;
|
animation.mStart = std::chrono::high_resolution_clock::now();
|
||||||
asset.mAnimations[2].mReverse = reverse;
|
animation.mLoop = loop;
|
||||||
asset.mAnimations[2].mActive = true;
|
animation.mReverse = reverse;
|
||||||
asset.mAnimations[2].mDuration = asset.mAnimator->getAnimationDuration(index);
|
animation.type = AnimationType::GLTF;
|
||||||
asset.mAnimating = true;
|
animation.mDuration = asset.mAnimator->getAnimationDuration(index);
|
||||||
|
|
||||||
|
asset.mAnimations.push_back(animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::stopAnimation(EntityId entityId, int index) {
|
void AssetManager::stopAnimation(EntityId entityId, int index) {
|
||||||
@@ -617,12 +596,12 @@ void AssetManager::stopAnimation(EntityId entityId, int index) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& asset = _assets[pos->second];
|
auto& asset = _assets[pos->second];
|
||||||
if(asset.gltfAnimationIndex != index) {
|
|
||||||
// ignore?
|
asset.mAnimations.erase(std::remove_if(asset.mAnimations.begin(),
|
||||||
} else {
|
asset.mAnimations.end(),
|
||||||
asset.mAnimations[2].mStart = time_point_t::max();
|
[=](AnimationStatus& anim) { return anim.gltfIndex == index; }),
|
||||||
asset.mAnimations[2].mActive = false;
|
asset.mAnimations.end());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetManager::loadTexture(EntityId entity, const char* resourcePath, int renderableIndex) {
|
void AssetManager::loadTexture(EntityId entity, const char* resourcePath, int renderableIndex) {
|
||||||
|
|||||||
@@ -268,8 +268,9 @@ extern "C" {
|
|||||||
int index,
|
int index,
|
||||||
bool loop,
|
bool loop,
|
||||||
bool reverse,
|
bool reverse,
|
||||||
|
bool replaceActive,
|
||||||
float crossfade) {
|
float crossfade) {
|
||||||
((AssetManager*)assetManager)->playAnimation(asset, index, loop, reverse, crossfade);
|
((AssetManager*)assetManager)->playAnimation(asset, index, loop, reverse, replaceActive, crossfade);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLUTTER_PLUGIN_EXPORT void set_animation_frame(
|
FLUTTER_PLUGIN_EXPORT void set_animation_frame(
|
||||||
|
|||||||
@@ -332,13 +332,17 @@ class FilamentController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void playAnimation(FilamentEntity asset, int index,
|
void playAnimation(FilamentEntity asset, int index,
|
||||||
{bool loop = false, bool reverse = false, double crossfade = 0.0}) async {
|
{bool loop = false,
|
||||||
|
bool reverse = false,
|
||||||
|
bool replaceActive = true,
|
||||||
|
double crossfade = 0.0}) async {
|
||||||
await _channel.invokeMethod("playAnimation", [
|
await _channel.invokeMethod("playAnimation", [
|
||||||
_assetManager,
|
_assetManager,
|
||||||
asset,
|
asset,
|
||||||
index,
|
index,
|
||||||
loop ? 1 : 0,
|
loop ? 1 : 0,
|
||||||
reverse ? 1 : 0,
|
reverse ? 1 : 0,
|
||||||
|
replaceActive,
|
||||||
crossfade
|
crossfade
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user