forked from Mirrors/openclonk
PlayAnimation: Delete previous animations in same slot if no weight is given.
This will simplify fixing several animation leaks.objectmenu
parent
80b8879805
commit
1f81b87c33
|
@ -28,7 +28,8 @@
|
|||
<param>
|
||||
<type>array</type>
|
||||
<name>weight</name>
|
||||
<desc>Specifies how to compute the weight of the animation in case the animation is combined with another animation in the given slot. The value needs to be created with one of the "Anim_" animation functions.</desc>
|
||||
<desc>Specifies how to compute the weight of the animation in case the animation is combined with another animation in the given slot. The value needs to be created with one of the "Anim_" animation functions.<br />If nil, the animation is created with constant weight 1000 and other animations in the same slot are removed.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
|
@ -45,6 +46,7 @@
|
|||
</params>
|
||||
</syntax>
|
||||
<desc>Starts playing a new animation. The return value of this function is the animation number of the animation node inserted which can be used to manipulate or remove the animation later. If there are already animations in the given slot then additionally a combination node is created. This combination node is assigned the returned number plus 1.</desc>
|
||||
<remark>If a weight is specified, other animations remain in the slot and are automatically combined. Scripters are responsible for removing animations either by replacing them (pass nil as weight), calling <funclink>StopAnimation</funclink> or using the ANIM_Remove flag in the <funclink>Anim_Linear</funclink> function.</remark>
|
||||
<remark>See the <emlink href="definition/animations.html">animation documentation</emlink> for further explanations of the animation system.</remark>
|
||||
<examples>
|
||||
<example>
|
||||
|
|
|
@ -1177,26 +1177,26 @@ void StdMeshInstance::SetCompletion(float completion)
|
|||
#endif
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight)
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight, bool stop_previous_animation)
|
||||
{
|
||||
const StdMeshAnimation* animation = Mesh->GetSkeleton().GetAnimationByName(animation_name);
|
||||
if (!animation) { delete position; delete weight; return NULL; }
|
||||
|
||||
return PlayAnimation(*animation, slot, sibling, position, weight);
|
||||
return PlayAnimation(*animation, slot, sibling, position, weight, stop_previous_animation);
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight)
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight, bool stop_previous_animation)
|
||||
{
|
||||
position->Value = Clamp(position->Value, Fix0, ftofix(animation.Length));
|
||||
AnimationNode* child = new AnimationNode(&animation, position);
|
||||
InsertAnimationNode(child, slot, sibling, weight);
|
||||
InsertAnimationNode(child, slot, sibling, weight, stop_previous_animation);
|
||||
return child;
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdMeshBone* bone, const StdMeshTransformation& trans, int slot, AnimationNode* sibling, ValueProvider* weight)
|
||||
StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdMeshBone* bone, const StdMeshTransformation& trans, int slot, AnimationNode* sibling, ValueProvider* weight, bool stop_previous_animation)
|
||||
{
|
||||
AnimationNode* child = new AnimationNode(bone, trans);
|
||||
InsertAnimationNode(child, slot, sibling, weight);
|
||||
InsertAnimationNode(child, slot, sibling, weight, stop_previous_animation);
|
||||
return child;
|
||||
}
|
||||
|
||||
|
@ -1750,11 +1750,19 @@ StdMeshInstance::AnimationNodeList::iterator StdMeshInstance::GetStackIterForSlo
|
|||
return AnimationStack.insert(AnimationStack.end(), NULL);
|
||||
}
|
||||
|
||||
void StdMeshInstance::InsertAnimationNode(AnimationNode* node, int slot, AnimationNode* sibling, ValueProvider* weight)
|
||||
void StdMeshInstance::InsertAnimationNode(AnimationNode* node, int slot, AnimationNode* sibling, ValueProvider* weight, bool stop_previous_animation)
|
||||
{
|
||||
assert(!sibling || !stop_previous_animation);
|
||||
// Default
|
||||
if (!sibling) sibling = GetRootAnimationForSlot(slot);
|
||||
assert(!sibling || sibling->Slot == slot);
|
||||
|
||||
// Stop any animation already running in this slot?
|
||||
if (sibling && stop_previous_animation)
|
||||
{
|
||||
StopAnimation(sibling);
|
||||
sibling = NULL;
|
||||
}
|
||||
|
||||
// Find two subsequent numbers in case we need to create two nodes, so
|
||||
// script can deduce the second node.
|
||||
|
|
|
@ -541,9 +541,9 @@ public:
|
|||
void SetCompletion(float completion);
|
||||
float GetCompletion() const { return Completion; }
|
||||
|
||||
AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
||||
AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight);
|
||||
AnimationNode* PlayAnimation(const StdMeshBone* bone, const StdMeshTransformation& trans, int slot, AnimationNode* sibling, ValueProvider* weight);
|
||||
AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight, bool stop_previous_animation);
|
||||
AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight, bool stop_previous_animation);
|
||||
AnimationNode* PlayAnimation(const StdMeshBone* bone, const StdMeshTransformation& trans, int slot, AnimationNode* sibling, ValueProvider* weight, bool stop_previous_animation);
|
||||
void StopAnimation(AnimationNode* node);
|
||||
|
||||
AnimationNode* GetAnimationNodeByNumber(unsigned int number);
|
||||
|
@ -627,7 +627,7 @@ protected:
|
|||
typedef std::vector<AnimationNode*> AnimationNodeList;
|
||||
|
||||
AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create);
|
||||
void InsertAnimationNode(AnimationNode* node, int slot, AnimationNode* sibling, ValueProvider* weight);
|
||||
void InsertAnimationNode(AnimationNode* node, int slot, AnimationNode* sibling, ValueProvider* weight, bool stop_previous_animation);
|
||||
bool ExecuteAnimationNode(AnimationNode* node);
|
||||
void ApplyBoneTransformToVertices(const std::vector<StdSubMesh::Vertex>& mesh_vertices, std::vector<StdMeshVertex>& instance_vertices);
|
||||
void SetBoneTransformsDirty(bool value);
|
||||
|
|
|
@ -767,7 +767,7 @@ void C4GraphicsOverlay::UpdateFacet()
|
|||
const StdMeshAnimation* Animation = pSourceGfx->Mesh->GetSkeleton().GetAnimationByName(AnimationName->GetData());
|
||||
if (!Animation) return;
|
||||
|
||||
pMeshInstance->PlayAnimation(*Animation, 0, NULL, new C4ValueProviderRef<int32_t>(iPhase, ftofix(Animation->Length / action->GetPropertyInt(P_Length))), new C4ValueProviderConst(itofix(1)));
|
||||
pMeshInstance->PlayAnimation(*Animation, 0, NULL, new C4ValueProviderRef<int32_t>(iPhase, ftofix(Animation->Length / action->GetPropertyInt(P_Length))), new C4ValueProviderConst(itofix(1)), true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -2863,7 +2863,7 @@ bool C4Object::SetAction(C4PropList * Act, C4Object *pTarget, C4Object *pTarget2
|
|||
if (Animation)
|
||||
{
|
||||
// note that weight is ignored
|
||||
Action.Animation = pMeshInstance->PlayAnimation(Animation->GetData(), 0, NULL, new C4ValueProviderAction(this), new C4ValueProviderConst(itofix(1)));
|
||||
Action.Animation = pMeshInstance->PlayAnimation(Animation->GetData(), 0, NULL, new C4ValueProviderAction(this), new C4ValueProviderConst(itofix(1)), true);
|
||||
}
|
||||
}
|
||||
// Stop previous act sound
|
||||
|
|
|
@ -1806,13 +1806,16 @@ static long FnGetUnusedOverlayID(C4Object *Obj, long iBaseIndex)
|
|||
return iBaseIndex;
|
||||
}
|
||||
|
||||
static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int iSlot, C4ValueArray* PositionProvider, C4ValueArray* WeightProvider, Nillable<int> iSibling, Nillable<int> iAttachNumber)
|
||||
static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int iSlot, C4ValueArray* PositionProvider, Nillable<C4ValueArray*> WeightProvider, Nillable<int> iSibling, Nillable<int> iAttachNumber)
|
||||
{
|
||||
if (!Obj) return C4Void();
|
||||
if (!Obj->pMeshInstance) return C4Void();
|
||||
if (iSlot == 0) return C4Void(); // Reserved for ActMap animations
|
||||
if (!PositionProvider) return C4Void();
|
||||
if (!WeightProvider) return C4Void();
|
||||
// If no weight provider is passed, this animation should be played exclusively.
|
||||
bool stop_previous_animations = WeightProvider.IsNil();
|
||||
// Exclusive mode cannot work with a sibling
|
||||
if (!iSibling.IsNil() && stop_previous_animations) return C4Void();
|
||||
|
||||
StdMeshInstance* Instance = Obj->pMeshInstance;
|
||||
if (!iAttachNumber.IsNil())
|
||||
|
@ -1834,7 +1837,15 @@ static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int i
|
|||
if (!animation) return C4Void();
|
||||
|
||||
StdMeshInstance::ValueProvider* p_provider = CreateValueProviderFromArray(Obj, *PositionProvider, animation);
|
||||
StdMeshInstance::ValueProvider* w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
|
||||
StdMeshInstance::ValueProvider* w_provider;
|
||||
if (stop_previous_animations)
|
||||
{
|
||||
w_provider = new C4ValueProviderConst(Fix1);
|
||||
}
|
||||
else
|
||||
{
|
||||
w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
|
||||
}
|
||||
if (!p_provider || !w_provider)
|
||||
{
|
||||
delete p_provider;
|
||||
|
@ -1842,7 +1853,7 @@ static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int i
|
|||
return C4Void();
|
||||
}
|
||||
|
||||
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(*animation, iSlot, s_node, p_provider, w_provider);
|
||||
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(*animation, iSlot, s_node, p_provider, w_provider, stop_previous_animations);
|
||||
if (!n_node) return C4Void();
|
||||
|
||||
return n_node->GetNumber();
|
||||
|
@ -1892,7 +1903,7 @@ static Nillable<int> FnTransformBone(C4Object *Obj, C4String *szBoneName, C4Valu
|
|||
// a check here and return nil if the matrix cannot be decomposed.
|
||||
StdMeshTransformation trans = matrix.Decompose();
|
||||
|
||||
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(bone, trans, iSlot, s_node, w_provider);
|
||||
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(bone, trans, iSlot, s_node, w_provider, false);
|
||||
if (!n_node) return C4Void();
|
||||
|
||||
return n_node->GetNumber();
|
||||
|
|
Loading…
Reference in New Issue