animation blending #95
This commit is contained in:
@@ -523,6 +523,10 @@ Describes an orientation in 3D space.
|
||||
- SetLooped(bool value)
|
||||
- IsLooped() : bool result
|
||||
- IsPlaying() : bool result
|
||||
- SetTimer(float value)
|
||||
- GetTimer() : float result
|
||||
- SetAmount(float value)
|
||||
- GetAmount() : float result
|
||||
|
||||
#### MaterialComponent
|
||||
- SetBaseColor(Vector value)
|
||||
|
||||
@@ -56,6 +56,7 @@ AnimationWindow::AnimationWindow(EditorComponent* editor) : GUI(&editor->GetGUI(
|
||||
else
|
||||
{
|
||||
animation->Play();
|
||||
animation->amount = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -87,6 +88,20 @@ AnimationWindow::AnimationWindow(EditorComponent* editor) : GUI(&editor->GetGUI(
|
||||
timerSlider->SetTooltip("Set the animation timer by hand.");
|
||||
animWindow->AddWidget(timerSlider);
|
||||
|
||||
amountSlider = new wiSlider(0, 1, 0, 100000, "Amount: ");
|
||||
amountSlider->SetSize(XMFLOAT2(250, 30));
|
||||
amountSlider->SetPos(XMFLOAT2(x, y += step));
|
||||
amountSlider->OnSlide([&](wiEventArgs args) {
|
||||
AnimationComponent* animation = wiScene::GetScene().animations.GetComponent(entity);
|
||||
if (animation != nullptr)
|
||||
{
|
||||
animation->amount = args.fValue;
|
||||
}
|
||||
});
|
||||
amountSlider->SetEnabled(false);
|
||||
amountSlider->SetTooltip("Set the animation blending amount by hand.");
|
||||
animWindow->AddWidget(amountSlider);
|
||||
|
||||
|
||||
|
||||
animWindow->Translate(XMFLOAT3(100, 50, 0));
|
||||
@@ -153,6 +168,7 @@ void AnimationWindow::Update()
|
||||
if (animation.IsPlaying())
|
||||
{
|
||||
playButton->SetText("Pause");
|
||||
animation.amount = wiMath::Lerp(animation.amount, 1, 0.1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,5 +179,6 @@ void AnimationWindow::Update()
|
||||
|
||||
timerSlider->SetRange(0, animation.GetLength());
|
||||
timerSlider->SetValue(animation.timer);
|
||||
amountSlider->SetValue(animation.amount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
wiButton* playButton;
|
||||
wiButton* stopButton;
|
||||
wiSlider* timerSlider;
|
||||
wiSlider* amountSlider;
|
||||
|
||||
void Update();
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
This file contains changelog of wiArchive versions
|
||||
|
||||
44: Serialized AnimationComponent::amount
|
||||
43: Serialized MeshComponent::vertex_windweights
|
||||
42: Serialized hair particle sprite sheet properties
|
||||
41: Serialized terrain blend materials in MeshComponent
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
using namespace std;
|
||||
|
||||
// this should always be only INCREMENTED and only if a new serialization is implemeted somewhere!
|
||||
uint64_t __archiveVersion = 43;
|
||||
uint64_t __archiveVersion = 44;
|
||||
// this is the version number of which below the archive is not compatible with the current version
|
||||
uint64_t __archiveVersionBarrier = 22;
|
||||
|
||||
|
||||
@@ -1672,7 +1672,8 @@ namespace wiScene
|
||||
|
||||
float left = sampler.keyframe_times[keyLeft];
|
||||
|
||||
TransformComponent& transform = *transforms.GetComponent(channel.target);
|
||||
TransformComponent& target_transform = *transforms.GetComponent(channel.target);
|
||||
TransformComponent transform = target_transform;
|
||||
|
||||
if (sampler.mode == AnimationComponent::AnimationSampler::Mode::STEP || keyLeft == keyRight)
|
||||
{
|
||||
@@ -1741,7 +1742,25 @@ namespace wiScene
|
||||
}
|
||||
}
|
||||
|
||||
transform.SetDirty();
|
||||
target_transform.SetDirty();
|
||||
|
||||
const float t = animation.amount;
|
||||
|
||||
const XMVECTOR aS = XMLoadFloat3(&target_transform.scale_local);
|
||||
const XMVECTOR aR = XMLoadFloat4(&target_transform.rotation_local);
|
||||
const XMVECTOR aT = XMLoadFloat3(&target_transform.translation_local);
|
||||
|
||||
const XMVECTOR bS = XMLoadFloat3(&transform.scale_local);
|
||||
const XMVECTOR bR = XMLoadFloat4(&transform.rotation_local);
|
||||
const XMVECTOR bT = XMLoadFloat3(&transform.translation_local);
|
||||
|
||||
const XMVECTOR S = XMVectorLerp(aS, bS, t);
|
||||
const XMVECTOR R = XMQuaternionSlerp(aR, bR, t);
|
||||
const XMVECTOR T = XMVectorLerp(aT, bT, t);
|
||||
|
||||
XMStoreFloat3(&target_transform.scale_local, S);
|
||||
XMStoreFloat4(&target_transform.rotation_local, R);
|
||||
XMStoreFloat3(&target_transform.translation_local, T);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -873,7 +873,8 @@ namespace wiScene
|
||||
uint32_t _flags = LOOPED;
|
||||
float start = 0;
|
||||
float end = 0;
|
||||
float timer = 0.0f;
|
||||
float timer = 0;
|
||||
float amount = 1;
|
||||
|
||||
struct AnimationChannel
|
||||
{
|
||||
|
||||
@@ -1535,6 +1535,10 @@ Luna<AnimationComponent_BindLua>::FunctionType AnimationComponent_BindLua::metho
|
||||
lunamethod(AnimationComponent_BindLua, IsLooped),
|
||||
lunamethod(AnimationComponent_BindLua, IsPlaying),
|
||||
lunamethod(AnimationComponent_BindLua, IsEnded),
|
||||
lunamethod(AnimationComponent_BindLua, SetTimer),
|
||||
lunamethod(AnimationComponent_BindLua, GetTimer),
|
||||
lunamethod(AnimationComponent_BindLua, SetAmount),
|
||||
lunamethod(AnimationComponent_BindLua, GetAmount),
|
||||
{ NULL, NULL }
|
||||
};
|
||||
Luna<AnimationComponent_BindLua>::PropertyType AnimationComponent_BindLua::properties[] = {
|
||||
@@ -1598,6 +1602,44 @@ int AnimationComponent_BindLua::IsEnded(lua_State* L)
|
||||
wiLua::SSetBool(L, component->IsEnded());
|
||||
return 1;
|
||||
}
|
||||
int AnimationComponent_BindLua::SetTimer(lua_State* L)
|
||||
{
|
||||
int argc = wiLua::SGetArgCount(L);
|
||||
if (argc > 0)
|
||||
{
|
||||
float value = wiLua::SGetFloat(L, 1);
|
||||
component->timer = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
wiLua::SError(L, "SetTimer(float value) not enough arguments!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int AnimationComponent_BindLua::GetTimer(lua_State* L)
|
||||
{
|
||||
wiLua::SSetFloat(L, component->timer);
|
||||
return 1;
|
||||
}
|
||||
int AnimationComponent_BindLua::SetAmount(lua_State* L)
|
||||
{
|
||||
int argc = wiLua::SGetArgCount(L);
|
||||
if (argc > 0)
|
||||
{
|
||||
float value = wiLua::SGetFloat(L, 1);
|
||||
component->amount = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
wiLua::SError(L, "SetAmount(float value) not enough arguments!");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int AnimationComponent_BindLua::GetAmount(lua_State* L)
|
||||
{
|
||||
wiLua::SSetFloat(L, component->amount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -193,6 +193,10 @@ namespace wiScene_BindLua
|
||||
int IsLooped(lua_State* L);
|
||||
int IsPlaying(lua_State* L);
|
||||
int IsEnded(lua_State* L);
|
||||
int SetTimer(lua_State* L);
|
||||
int GetTimer(lua_State* L);
|
||||
int SetAmount(lua_State* L);
|
||||
int GetAmount(lua_State* L);
|
||||
};
|
||||
|
||||
class MaterialComponent_BindLua
|
||||
|
||||
@@ -636,6 +636,11 @@ namespace wiScene
|
||||
archive >> end;
|
||||
archive >> timer;
|
||||
|
||||
if (archive.GetVersion() >= 44)
|
||||
{
|
||||
archive >> amount;
|
||||
}
|
||||
|
||||
size_t channelCount;
|
||||
archive >> channelCount;
|
||||
channels.resize(channelCount);
|
||||
@@ -666,6 +671,11 @@ namespace wiScene
|
||||
archive << end;
|
||||
archive << timer;
|
||||
|
||||
if (archive.GetVersion() >= 44)
|
||||
{
|
||||
archive << amount;
|
||||
}
|
||||
|
||||
archive << channels.size();
|
||||
for (size_t i = 0; i < channels.size(); ++i)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace wiVersion
|
||||
// minor features, major updates
|
||||
const int minor = 39;
|
||||
// minor bug fixes, alterations, refactors, updates
|
||||
const int revision = 67;
|
||||
const int revision = 68;
|
||||
|
||||
|
||||
long GetVersion()
|
||||
|
||||
@@ -40,6 +40,7 @@ Character = {
|
||||
JUMP = 2,
|
||||
},
|
||||
state = STAND,
|
||||
state_prev = STAND,
|
||||
|
||||
Create = function(self,entity)
|
||||
self.model = entity
|
||||
@@ -93,33 +94,30 @@ Character = {
|
||||
|
||||
Input = function(self)
|
||||
|
||||
if(self.state==self.states.STAND) then
|
||||
local lookDir = Vector()
|
||||
if(input.Down(KEYBOARD_BUTTON_LEFT) or input.Down(string.byte('A'))) then
|
||||
lookDir = lookDir:Add( Vector(-1) )
|
||||
end
|
||||
if(input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(string.byte('D'))) then
|
||||
lookDir = lookDir:Add( Vector(1) )
|
||||
end
|
||||
local lookDir = Vector()
|
||||
if(input.Down(KEYBOARD_BUTTON_LEFT) or input.Down(string.byte('A'))) then
|
||||
lookDir = lookDir:Add( Vector(-1) )
|
||||
end
|
||||
if(input.Down(KEYBOARD_BUTTON_RIGHT) or input.Down(string.byte('D'))) then
|
||||
lookDir = lookDir:Add( Vector(1) )
|
||||
end
|
||||
|
||||
if(input.Down(KEYBOARD_BUTTON_UP) or input.Down(string.byte('W'))) then
|
||||
lookDir = lookDir:Add( Vector(0,0,1) )
|
||||
end
|
||||
if(input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(string.byte('S'))) then
|
||||
lookDir = lookDir:Add( Vector(0,0,-1) )
|
||||
end
|
||||
if(input.Down(KEYBOARD_BUTTON_UP) or input.Down(string.byte('W'))) then
|
||||
lookDir = lookDir:Add( Vector(0,0,1) )
|
||||
end
|
||||
if(input.Down(KEYBOARD_BUTTON_DOWN) or input.Down(string.byte('S'))) then
|
||||
lookDir = lookDir:Add( Vector(0,0,-1) )
|
||||
end
|
||||
|
||||
local analog = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_L)
|
||||
lookDir = vector.Add(lookDir, Vector(analog.GetX(), 0, analog.GetY()))
|
||||
local analog = input.GetAnalog(GAMEPAD_ANALOG_THUMBSTICK_L)
|
||||
lookDir = vector.Add(lookDir, Vector(analog.GetX(), 0, analog.GetY()))
|
||||
|
||||
if(lookDir:Length()>0) then
|
||||
if(input.Down(KEYBOARD_BUTTON_LSHIFT) or input.Down(GAMEPAD_BUTTON_6)) then
|
||||
self:MoveDirection(lookDir,self.moveSpeed*2)
|
||||
else
|
||||
self:MoveDirection(lookDir,self.moveSpeed)
|
||||
end
|
||||
if(lookDir:Length()>0) then
|
||||
if(input.Down(KEYBOARD_BUTTON_LSHIFT) or input.Down(GAMEPAD_BUTTON_6)) then
|
||||
self:MoveDirection(lookDir,self.moveSpeed*2)
|
||||
else
|
||||
self:MoveDirection(lookDir,self.moveSpeed)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if( input.Press(string.byte('J')) or input.Press(KEYBOARD_BUTTON_SPACE) or input.Press(GAMEPAD_BUTTON_2) ) then
|
||||
@@ -157,7 +155,7 @@ Character = {
|
||||
local target_transform = scene.Component_GetTransform(self.target)
|
||||
|
||||
-- gravity:
|
||||
self.force = vector.Add(self.force, Vector(0,-9.8 * 10,0))
|
||||
self.force = vector.Add(self.force, Vector(0,-9.8 * 20,0))
|
||||
|
||||
-- apply force:
|
||||
self.velocity = vector.Add(self.velocity, vector.Multiply(self.force, getDeltaTime()))
|
||||
@@ -165,18 +163,31 @@ Character = {
|
||||
|
||||
-- state and animation update
|
||||
if(self.state == self.states.STAND) then
|
||||
scene.Component_GetAnimation(self.idle_anim).Play()
|
||||
scene.Component_GetAnimation(self.walk_anim).Stop()
|
||||
self.state = self.states.STAND
|
||||
local anim = scene.Component_GetAnimation(self.idle_anim)
|
||||
anim.Play()
|
||||
anim.SetAmount(math.lerp(anim.GetAmount(), 1, 0.1))
|
||||
if(self.state ~= self.state_prev) then
|
||||
anim.SetAmount(0)
|
||||
end
|
||||
elseif(self.state == self.states.WALK) then
|
||||
scene.Component_GetAnimation(self.idle_anim).Stop()
|
||||
scene.Component_GetAnimation(self.walk_anim).Play()
|
||||
self.state = self.states.STAND
|
||||
local anim = scene.Component_GetAnimation(self.walk_anim)
|
||||
anim.Play()
|
||||
anim.SetAmount(math.lerp(anim.GetAmount(), 1, 0.1))
|
||||
if(self.state ~= self.state_prev) then
|
||||
anim.SetAmount(0)
|
||||
end
|
||||
elseif(self.state == self.states.JUMP) then
|
||||
scene.Component_GetAnimation(self.idle_anim).Play()
|
||||
scene.Component_GetAnimation(self.walk_anim).Stop()
|
||||
self.state = self.states.STAND
|
||||
local anim = scene.Component_GetAnimation(self.idle_anim)
|
||||
anim.Play()
|
||||
anim.SetAmount(math.lerp(anim.GetAmount(), 1, 0.1))
|
||||
if(self.state ~= self.state_prev) then
|
||||
anim.SetAmount(0)
|
||||
end
|
||||
end
|
||||
self.state_prev = self.state
|
||||
|
||||
-- front block shoots multiple rays in front to try to find obstruction
|
||||
local rotations = {0, 3.1415*0.3, -3.1415*0.3}
|
||||
@@ -228,7 +239,7 @@ Character = {
|
||||
self.velocity.SetY(0) -- don't fall below ground
|
||||
self.velocity = vector.Multiply(self.velocity, 0.8) -- slow down on ground
|
||||
else
|
||||
self.velocity = vector.Multiply(self.velocity, 0.96) -- slow down in air
|
||||
self.velocity = vector.Multiply(self.velocity, 0.94) -- slow down in air
|
||||
end
|
||||
|
||||
end
|
||||
@@ -368,9 +379,11 @@ runProcess(function()
|
||||
|
||||
while true do
|
||||
|
||||
player:Input()
|
||||
|
||||
player:Update()
|
||||
|
||||
fixedupdate()
|
||||
|
||||
player:Input()
|
||||
|
||||
camera:Update()
|
||||
|
||||
|
||||
@@ -1181,7 +1181,9 @@ local function Character(face, skin_color, shirt_color, hair_color, shoe_color)
|
||||
end,
|
||||
-- Starts a new state:
|
||||
StartState = function(self, dst_state)
|
||||
scene.Component_GetAnimation(self.states[dst_state].anim).Play()
|
||||
local anim = scene.Component_GetAnimation(self.states[dst_state].anim)
|
||||
anim.Play()
|
||||
anim.SetAmount(0)
|
||||
self.frame = 0
|
||||
self.state = dst_state
|
||||
self.hitconfirms = {}
|
||||
@@ -1210,6 +1212,11 @@ local function Character(face, skin_color, shirt_color, hair_color, shoe_color)
|
||||
end
|
||||
end
|
||||
|
||||
-- Animation blending:
|
||||
local anim = scene.Component_GetAnimation(self.states[self.state].anim)
|
||||
local anim_amount = anim.GetAmount()
|
||||
anim.SetAmount(math.lerp(anim_amount, 1, 0.2))
|
||||
|
||||
-- Execute the currently active state:
|
||||
local current_state = self.states[self.state]
|
||||
if(current_state ~= nil) then
|
||||
|
||||
Reference in New Issue
Block a user