Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue-6553 Possibility to stop all animations of a gui node at the same time #6592

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions engine/gui/src/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3540,6 +3540,20 @@ Result DeleteDynamicTexture(HScene scene, const dmhash_t texture_hash)
dmArray<Animation>* animations = &scene->m_Animations;
uint32_t n_animations = animations->Size();

if (property_hash == 0)
{
// if property hash is 0 then cancels all ongoing animation of properties for node
for (uint32_t i = 0; i < n_animations; ++i)
{
Animation* anim = &(*animations)[i];
if (anim->m_Node == node)
{
anim->m_Cancelled = 1;
}
}
return;
}

PropDesc* pd = GetPropertyDesc(property_hash);
if (pd) {
for (uint32_t i = 0; i < n_animations; ++i)
Expand Down
31 changes: 23 additions & 8 deletions engine/gui/src/gui_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1148,13 +1148,13 @@ namespace dmGui
return 0;
}

/*# cancels an ongoing animation
/*# cancels an ongoing animation(s)
*
* If an animation of the specified node is currently running (started by <code>gui.animate</code>), it will immediately be canceled.
*
* @name gui.cancel_animation
* @param node [type:node] node that should have its animation canceled
* @param property [type:string|constant] property for which the animation should be canceled
* @param [property] [type:string|constant] optional property for which the animation should be canceled
*
* - `"position"`
* - `"rotation"`
Expand All @@ -1181,6 +1181,18 @@ namespace dmGui
* -- cancel animation of the x component.
* gui.cancel_animation(node, "position.x")
* ```
*
* Cancels all property animations on a node in a single call:
*
* ```lua
* local node = gui.get_node("my_node")
* -- animate to new position and scale
* gui.animate(node, "position", vmath.vector3(100, 100, 0), go.EASING_LINEAR, 5)
* gui.animate(node, "scale", vmath.vector3(0.5), go.EASING_LINEAR, 5)
* ...
* -- cancel positioning and scaling at once
* gui.cancel_animation(node)
* ```
*/
int LuaCancelAnimation(lua_State* L)
{
Expand All @@ -1193,14 +1205,17 @@ namespace dmGui
InternalNode* node = LuaCheckNodeInternal(L, 1, &hnode);
(void) node;

dmhash_t property_hash;
if (dmScript::IsHash(L, 2)) {
property_hash = dmScript::CheckHash(L, 2);
} else {
property_hash = dmHashString64(luaL_checkstring(L, 2));
dmhash_t property_hash = 0;
if (top >= 2 && !lua_isnil(L, 2))
{
if (dmScript::IsHash(L, 2)) {
property_hash = dmScript::CheckHash(L, 2);
} else {
property_hash = dmHashString64(luaL_checkstring(L, 2));
}
}

if (!dmGui::HasPropertyHash(scene, hnode, property_hash)) {
if (property_hash != 0 && !dmGui::HasPropertyHash(scene, hnode, property_hash)) {
luaL_error(L, "property '%s' not found", dmHashReverseSafe64(property_hash));
}

Expand Down
65 changes: 65 additions & 0 deletions engine/gui/src/test/test_gui_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,71 @@ TEST_F(dmGuiScriptTest, TestCancelAnimationComponent)
dmGui::DeleteScript(script);
}

TEST_F(dmGuiScriptTest, TestCancelAnimationAll)
{
dmGui::HScript script = NewScript(m_Context);

dmGui::NewSceneParams params;
params.m_MaxNodes = 64;
params.m_MaxAnimations = 32;
params.m_UserData = this;
dmGui::HScene scene = dmGui::NewScene(m_Context, &params);
dmGui::SetSceneResolution(scene, 1, 1);
dmGui::SetSceneScript(scene, script);

// Animate position and scale
const char* src =
"local n1\n"
"local elapsed = 0\n"
"local animating = true\n"
"function init(self)\n"
" n1 = gui.new_box_node(vmath.vector3(0), vmath.vector3(1))\n"
" gui.set_pivot(n1, gui.PIVOT_SW)\n"
" gui.animate(n1, gui.PROP_POSITION, vmath.vector3(100, 100, 0), gui.EASING_LINEAR, 1)\n"
" gui.animate(n1, gui.PROP_SCALE, vmath.vector3(2), gui.EASING_LINEAR, 1)\n"
"end\n"
"function update(self, dt)\n"
" elapsed = elapsed + dt\n"
" if 0.5 <= elapsed and animating then\n"
" gui.cancel_animation(n1)\n"
" animating = false\n"
" end\n"
"end\n";

dmGui::Result result = SetScript(script, LuaSourceFromStr(src));
ASSERT_EQ(dmGui::RESULT_OK, result);

result = dmGui::InitScene(scene);
ASSERT_EQ(dmGui::RESULT_OK, result);

int ticks = 0;
dmVMath::Matrix4 t1;
while (ticks < 4) {
dmGui::RenderScene(scene, RenderNodesStoreTransform, &t1);
dmGui::UpdateScene(scene, 0.125f);
++ticks;
}
dmVMath::Vector3 translation = t1.getTranslation();
dmVMath::Vector3 postScaleDiagonal = Vector3(t1[0][0], t1[1][1], t1[2][2]);

const float tinyDifference = 10e-10f;
while (ticks < 8) {
dmGui::RenderScene(scene, RenderNodesStoreTransform, &t1);
dmGui::UpdateScene(scene, 0.125f);

dmVMath::Vector3 currentTranslation = t1.getTranslation();
dmVMath::Vector3 currentDiagonal = Vector3(t1[0][0], t1[1][1], t1[2][2]);

ASSERT_LE(Vectormath::Aos::lengthSqr(currentTranslation - translation), tinyDifference);
ASSERT_LE(Vectormath::Aos::lengthSqr(currentDiagonal - postScaleDiagonal), tinyDifference);

++ticks;
}

dmGui::DeleteScene(scene);
dmGui::DeleteScript(script);
}

TEST_F(dmGuiScriptTest, TestInstanceContext)
{
lua_State* L = dmGui::GetLuaState(m_Context);
Expand Down