From 593e358cc1a630ef91fb46af513954e416278c05 Mon Sep 17 00:00:00 2001 From: Mikulas Florek Date: Sun, 10 Nov 2024 16:31:56 +0100 Subject: [PATCH] demo - ik to push a button --- data/maps/demo/button.lua | 73 +++++++++++++--- data/maps/demo/demo.unv | Bin 9564 -> 9527 bytes data/models/ybot/ybot.act | Bin 2439 -> 2629 bytes data/scripts/math.lua | 134 ++++++++++++++++------------- src/animation/animation_module.cpp | 1 + src/editor/asset_browser.cpp | 2 + 6 files changed, 141 insertions(+), 69 deletions(-) diff --git a/data/maps/demo/button.lua b/data/maps/demo/button.lua index 014d7492f9..795c3a9104 100644 --- a/data/maps/demo/button.lua +++ b/data/maps/demo/button.lua @@ -1,9 +1,12 @@ -local math = require "scripts/math" +local lumix_math = require "scripts/math" local interactive = false label = {} player = {} sound = -1 +local ik_target_input = -1 +local ik_alpha_input = -1 +local ik_co = nil Editor.setPropertyType(this, "label", Editor.ENTITY_PROPERTY) Editor.setPropertyType(this, "player", Editor.ENTITY_PROPERTY) @@ -16,23 +19,73 @@ end function update(time_delta) -- check if player is close - local dist_squared = math.distXZSquared(this.position, player.position) + local dist_squared = lumix_math.distXZSquared(this.position, player.position) interactive = dist_squared < 2 -- animate the label if player is close label.property_animator.enabled = interactive + + if ik_co then + local status, res = coroutine.resume(ik_co, time_delta) + if not status then + LumixAPI.logError("coroutine error: " .. res) + ik_co = nil + end + if not res then + ik_co = nil + end + end +end + +function easeOutBack(x: number): number + local c1 = 1.70158; + local c3 = c1 + 1; + + return 1 + c3 * math.pow(x - 1, 3) + c1 * math.pow(x - 1, 2); +end + +function calcIKTarget() + local button_pos = this.position + local player_pos = player.position + button_pos = lumix_math.subVec3(button_pos, player_pos) -- relative to player_pos + local player_rot = player.rotation + player_rot[4] = -player_rot[4] --invert rotation + button_pos = lumix_math.transformVec3(player_rot, button_pos) --transform to player space + return button_pos end function onInputEvent(event : InputEvent) - -- check if player pressed "F" and is close + -- check if player pressed "F" and is close if interactive and event.type == "button" and event.device.type == "keyboard" then if event.key_id == string.byte("F") then - if event.down then - -- play the sound - playSound(sound) - -- press (move) the button - this.property_animator.enabled = false - this.property_animator.enabled = true - end + if event.down then + -- start by moving the hand to button + ik_target_input = player.animator:getInputIndex("left_hand_ik_target") + ik_alpha_input = player.animator:getInputIndex("left_hand_ik_alpha") + local ik_time = 0 + + ik_co = coroutine.create(function() + local td = 0 + while ik_time < 1 do + player.animator:setVec3Input(ik_target_input, calcIKTarget()) + if ik_time < 0.2 then + if ik_time + td >= 0.2 then + -- play the sound + playSound(sound) + -- press (move) the button + this.property_animator.enabled = false + this.property_animator.enabled = true + end + player.animator:setFloatInput(ik_alpha_input, easeOutBack(ik_time / 0.2)) + else + player.animator:setFloatInput(ik_alpha_input, 1 - easeOutBack((ik_time - 0.2) / 0.8)) + end + td = coroutine.yield(true) + ik_time = ik_time + td + end + return false + end) + + end end end end diff --git a/data/maps/demo/demo.unv b/data/maps/demo/demo.unv index f385fd1bb6347b81abbc3c6abe54ef0a4c8e80f0..2e7803afb784c57dbbc89e1fd02d3c43c5dca139 100644 GIT binary patch delta 367 zcmccPwcTrj0hh+6t2<3zq_{flaM+W^v+cqD2fG8BeArzaJJ z{gl+nDpDfsP_rl7OGz>^OpcVgAanjbqs?BeY&(<1*KLlKGw$bk&9UEM^A0=71w#8b RyGk=MG6N0SoG0^+0|4FsT|58) delta 403 zcmdn)b;oOi0hfkQ_SbgSbFL02@Bfo{^!CyI`bYUEkLtQOOgg)F&$lgg`&<5++V-ey zvfUiPb%kAhLDmz6orm^UY`Di4TkzGMVZPe-H`C7B0~Ol<725+9?*%H}yE$0Mo{gQs z#f72apY!CI5{i=}B?Tv&OY%*gAjvlQ9FWf@DL;9agu-MyNhP`D(xg$>!##q~;Xs zr=(6+krH8F01{$bFxg&8k}-91q|^nOZSNUvc4=kXsVu&3bF`e%p8GY2z5V7L`@|Or v*>850W@OZ01Zn|cy~MmsE2wdmN%OvQ3ufkapw;sstHy z?b@~fY(SbH$OEwj!E8n_8{{sKI*>R!kOpC(o(2&Y1_uAl;T+nG;Sx|Kmz^0He1I4N pxPTNh5OV-A$UtwP3>#b)WGzSrWV{DZw8aU?00WSop#1z21^|1*ILH71 delta 132 zcmX>q(k^V^?C2BE%D}+D0mQlaDXBTd`jtufC164?EvbTm2`B*q#RaLUDe)B(4P_?! zC~n-kk=>FRC<@ZX#=yvM^WKXG>|iznn9T-cgLHz#S%5T14#Yq0%+S!i`7nnzBWqB8 HehC8r%+Vp{ diff --git a/data/scripts/math.lua b/data/scripts/math.lua index 1f6e835e1e..9d9d94d350 100644 --- a/data/scripts/math.lua +++ b/data/scripts/math.lua @@ -1,61 +1,77 @@ -return { - dot = function(a, b) - return a[1] * b[1] + a[2] * b[2] + a[3] * b[3] - end, - - mulQuat = function(a, b) - return { - a[4] * b[1] + b[4] * a[1] + a[2] * b[3] - b[2] * a[3], - a[4] * b[2] + b[4] * a[2] + a[3] * b[1] - b[3] * a[1], - a[4] * b[3] + b[4] * a[3] + a[1] * b[2] - b[1] * a[2], - a[4] * b[4] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3] - } - end, - - makeQuatFromYaw = function(yaw) - local syaw = math.sin(yaw * 0.5) - local cyaw = math.cos(yaw * 0.5) - return {0, syaw, 0, cyaw } - end, - - makeQuatFromPitch = function(pitch) - local spitch = math.sin(pitch * 0.5) - local cpitch = math.cos(pitch * 0.5) - return {-spitch, 0, 0, cpitch} - end, - - yawToDir = function(yaw) - return {math.sin(yaw), 0, math.cos(yaw)} - end, - - mulVec3Num = function(v, f) - return {v[1] * f, v[2] * f, v[3] * f} - end, - - addVec3 = function(a, b) - return {a[1] + b[1], a[2] + b[2], a[3] + b[3]} - end, +local m = {} + +m.dot = function(a, b) + return a[1] * b[1] + a[2] * b[2] + a[3] * b[3] +end + +m.mulQuat = function(a, b) + return { + a[4] * b[1] + b[4] * a[1] + a[2] * b[3] - b[2] * a[3], + a[4] * b[2] + b[4] * a[2] + a[3] * b[1] - b[3] * a[1], + a[4] * b[3] + b[4] * a[3] + a[1] * b[2] - b[1] * a[2], + a[4] * b[4] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3] + } +end + +m.makeQuatFromYaw = function(yaw) + local syaw = math.sin(yaw * 0.5) + local cyaw = math.cos(yaw * 0.5) + return {0, syaw, 0, cyaw } +end + +m.makeQuatFromPitch = function(pitch) + local spitch = math.sin(pitch * 0.5) + local cpitch = math.cos(pitch * 0.5) + return {-spitch, 0, 0, cpitch} +end + +m.yawToDir = function(yaw) + return {math.sin(yaw), 0, math.cos(yaw)} +end + +m.mulVec3Num = function(v, f) + return {v[1] * f, v[2] * f, v[3] * f} +end + +m.addVec3 = function(a, b) + return {a[1] + b[1], a[2] + b[2], a[3] + b[3]} +end + +m.subVec3 = function(a, b) + return {a[1] - b[1], a[2] - b[2], a[3] - b[3]} +end + +m.mulVec3 = function(a, f) + return {a[1] * f, a[2] * f, a[3] * f} +end + +m.distSquared = function(a, b) + local xd = a[1] - b[1] + local yd = a[2] - b[2] + local zd = a[3] - b[3] - subVec3 = function(a, b) - return {a[1] - b[1], a[2] - b[2], a[3] - b[3]} - end, + return xd * xd + yd * yd + zd * zd +end + +m.distXZSquared = function(a, b) + local xd = a[1] - b[1] + local zd = a[3] - b[3] - mulVec3 = function(a, f) - return {a[1] * f, a[2] * f, a[3] * f} - end, - - distSquared = function(a, b) - local xd = a[1] - b[1] - local yd = a[2] - b[2] - local zd = a[3] - b[3] - - return xd * xd + yd * yd + zd * zd - end, - - distXZSquared = function(a, b) - local xd = a[1] - b[1] - local zd = a[3] - b[3] - - return xd * xd + zd * zd - end, -} + return xd * xd + zd * zd +end + +m.cross = function(a, b) + return {a[2] * b[3] - a[3] * b[2], a[3] * b[1] - a[1] * b[3], a[1] * b[2] - a[2] * b[1]} +end + +m.transformVec3 = function(rot_quat, pos) + local qvec = {rot_quat[1], rot_quat[2], rot_quat[3] } + local uv = m.cross(qvec, pos) + local uuv = m.cross(qvec, uv) + uv = m.mulVec3(uv, 2.0 * rot_quat[4]) + uuv = m.mulVec3Num(uuv, 2.0) + + return m.addVec3(pos, m.addVec3(uv, uuv)); +end + +return m \ No newline at end of file diff --git a/src/animation/animation_module.cpp b/src/animation/animation_module.cpp index a0bdaa4247..01015ed152 100644 --- a/src/animation/animation_module.cpp +++ b/src/animation/animation_module.cpp @@ -851,6 +851,7 @@ void AnimationModule::reflect(Engine& engine) { .LUMIX_CMP(Animator, "animator", "Animation / Animator") .function<(void (AnimationModule::*)(EntityRef, u32, float))&AnimationModule::setAnimatorInput>("setFloatInput", "AnimationModule::setAnimatorInput") .function<(void (AnimationModule::*)(EntityRef, u32, bool))&AnimationModule::setAnimatorInput>("setBoolInput", "AnimationModule::setAnimatorInput") + .function<(void (AnimationModule::*)(EntityRef, u32, Vec3))&AnimationModule::setAnimatorInput>("setVec3Input", "AnimationModule::setAnimatorInput") .LUMIX_FUNC_EX(AnimationModule::getAnimatorInputIndex, "getInputIndex") .LUMIX_PROP(AnimatorSource, "Source").resourceAttribute(anim::Controller::TYPE) .LUMIX_PROP(AnimatorDefaultSet, "Default set") diff --git a/src/editor/asset_browser.cpp b/src/editor/asset_browser.cpp index 5985c4f72e..8a71f3e9b5 100644 --- a/src/editor/asset_browser.cpp +++ b/src/editor/asset_browser.cpp @@ -659,8 +659,10 @@ struct AssetBrowserImpl : AssetBrowser { { FileInfo& tile = m_file_infos[j]; bool b = m_selected_resources.find([&](const Path& p){ return p == tile.filepath; }) >= 0; + ImGui::PushID(&tile); ImGui::Selectable(tile.clamped_filename, b); callbacks(tile, j, b); + ImGui::PopID(); } } }