Skip to content

Commit

Permalink
Implement skeleton retarget and overhaul some animation features
Browse files Browse the repository at this point in the history
  • Loading branch information
TokageItLab committed Mar 7, 2022
1 parent 1fbd498 commit 984509f
Show file tree
Hide file tree
Showing 41 changed files with 5,932 additions and 502 deletions.
1 change: 1 addition & 0 deletions core/variant/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ class Variant {
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void sub(const Variant &a, const Variant &b, Variant &r_dst);

/* Built-In Methods */

Expand Down
104 changes: 104 additions & 0 deletions core/variant/variant_setget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1868,6 +1868,110 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
}
}

void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) {
if (a.type != b.type) {
return;
}

switch (a.type) {
case NIL: {
r_dst = Variant();
}
return;
case INT: {
int64_t va = a._data._int;
int64_t vb = b._data._int;
r_dst = int(va - vb);
}
return;
case FLOAT: {
double ra = a._data._float;
double rb = b._data._float;
r_dst = ra - rb;
}
return;
case VECTOR2: {
r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem);
}
return;
case VECTOR2I: {
int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby));
}
return;
case RECT2: {
const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
r_dst = Rect2(ra->position - rb->position, ra->size - rb->size);
}
return;
case RECT2I: {
const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);

int32_t vax = ra->position.x;
int32_t vay = ra->position.y;
int32_t vbx = ra->size.x;
int32_t vby = ra->size.y;
int32_t vcx = rb->position.x;
int32_t vcy = rb->position.y;
int32_t vdx = rb->size.x;
int32_t vdy = rb->size.y;

r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy));
}
return;
case VECTOR3: {
r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem);
}
return;
case VECTOR3I: {
int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz));
}
return;
case AABB: {
const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size);
}
return;
case QUATERNION: {
Quaternion empty_rot;
const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
r_dst = (*qb).inverse() * *qa;
}
return;
case COLOR: {
const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
float new_r = ca->r - cb->r;
float new_g = ca->g - cb->g;
float new_b = ca->b - cb->b;
float new_a = ca->a - cb->a;
new_r = new_r > 1.0 ? 1.0 : new_r;
new_g = new_g > 1.0 ? 1.0 : new_g;
new_b = new_b > 1.0 ? 1.0 : new_b;
new_a = new_a > 1.0 ? 1.0 : new_a;
r_dst = Color(new_r, new_g, new_b, new_a);
}
return;
default: {
r_dst = a;
}
return;
}
}

void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
if (a.type != b.type) {
if (a.is_num() && b.is_num()) {
Expand Down
69 changes: 69 additions & 0 deletions doc/classes/Animation.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@
Sets the key identified by [code]key_idx[/code] to value [code]animation[/code]. The [code]track_idx[/code] must be the index of an Animation Track.
</description>
</method>
<method name="audio_track_get_auto_volume" qualifiers="const">
<return type="bool" />
<argument index="0" name="track_idx" type="int" />
<description>
Returns [code]true[/code] if the track at [code]idx[/code] override the volume in [AudioStreamPlayer].
</description>
</method>
<method name="audio_track_get_key_end_offset" qualifiers="const">
<return type="float" />
<argument index="0" name="track_idx" type="int" />
Expand Down Expand Up @@ -103,6 +110,14 @@
[code]stream[/code] is the [AudioStream] resource to play. [code]start_offset[/code] is the number of seconds cut off at the beginning of the audio stream, while [code]end_offset[/code] is at the ending.
</description>
</method>
<method name="audio_track_set_auto_volume">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="enable" type="bool" />
<description>
If [code]true[/code], the track at [code]idx[/code] override the volume in [AudioStreamPlayer].
</description>
</method>
<method name="audio_track_set_key_end_offset">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
Expand Down Expand Up @@ -291,6 +306,13 @@
Returns the arguments values to be called on a method track for a given key in a given track.
</description>
</method>
<method name="position_track_get_retarget_mode" qualifiers="const">
<return type="int" enum="Animation.RetargetMode" />
<argument index="0" name="track_idx" type="int" />
<description>
Returns the retarget mode of a given track.
</description>
</method>
<method name="position_track_insert_key">
<return type="int" />
<argument index="0" name="track_idx" type="int" />
Expand All @@ -299,13 +321,28 @@
<description>
</description>
</method>
<method name="position_track_set_retarget_mode">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="retarget_mode" type="int" enum="Animation.RetargetMode" />
<description>
Sets the retarget mode of a given track.
</description>
</method>
<method name="remove_track">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
<description>
Removes a track by specifying the track index.
</description>
</method>
<method name="rotation_track_get_retarget_mode" qualifiers="const">
<return type="int" enum="Animation.RetargetMode" />
<argument index="0" name="track_idx" type="int" />
<description>
Returns the retarget mode of a given track.
</description>
</method>
<method name="rotation_track_insert_key">
<return type="int" />
<argument index="0" name="track_idx" type="int" />
Expand All @@ -314,6 +351,21 @@
<description>
</description>
</method>
<method name="rotation_track_set_retarget_mode">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="retarget_mode" type="int" enum="Animation.RetargetMode" />
<description>
Sets the retarget mode of a given track.
</description>
</method>
<method name="scale_track_get_retarget_mode" qualifiers="const">
<return type="int" enum="Animation.RetargetMode" />
<argument index="0" name="track_idx" type="int" />
<description>
Returns the retarget mode of a given track.
</description>
</method>
<method name="scale_track_insert_key">
<return type="int" />
<argument index="0" name="track_idx" type="int" />
Expand All @@ -322,6 +374,14 @@
<description>
</description>
</method>
<method name="scale_track_set_retarget_mode">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
<argument index="1" name="retarget_mode" type="int" enum="Animation.RetargetMode" />
<description>
Sets the retarget mode of a given track.
</description>
</method>
<method name="track_find_key" qualifiers="const">
<return type="int" />
<argument index="0" name="track_idx" type="int" />
Expand Down Expand Up @@ -646,5 +706,14 @@
<constant name="HANDLE_MODE_BALANCED" value="1" enum="HandleMode">
Assigning the balanced handle mode to a Bezier Track's keyframe makes it so the two handles of the keyframe always stay aligned when changing either the keyframe's left or right handle.
</constant>
<constant name="RETARGET_MODE_GLOBAL" value="0" enum="RetargetMode">
Retarget the global transform in the model space relative to the bone rest.
</constant>
<constant name="RETARGET_MODE_LOCAL" value="1" enum="RetargetMode">
Retarget the local transform relative to the bone rest.
</constant>
<constant name="RETARGET_MODE_ABSOLUTE" value="2" enum="RetargetMode">
Retarget the local transform relative to the initial value of transform which is [code]Transform()[/code].
</constant>
</constants>
</class>
13 changes: 13 additions & 0 deletions doc/classes/AnimationPlayer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
</method>
<method name="clear_caches">
<return type="void" />
<argument index="0" name="p_emit_signal" type="bool" default="false" />
<description>
[AnimationPlayer] caches animated nodes. It may not notice if a node disappears; [method clear_caches] forces it to update the cache again.
</description>
Expand Down Expand Up @@ -215,6 +216,18 @@
This is used by the editor. If set to [code]true[/code], the scene will be saved with the effects of the reset animation applied (as if it had been seeked to time 0), then reverted after saving.
In other words, the saved scene file will contain the "default pose", as defined by the reset animation, if any, with the editor keeping the values that the nodes had before saving.
</member>
<member name="retarget_map" type="RetargetBoneMap" setter="set_retarget_map" getter="get_retarget_map">
The map used when extracting and applying retarget tracks.
</member>
<member name="retarget_option" type="RetargetBoneOption" setter="set_retarget_option" getter="get_retarget_option">
The option used when extracting retarget tracks.
</member>
<member name="retarget_profile" type="RetargetProfile" setter="set_retarget_profile" getter="get_retarget_profile">
The profile used when editing [RetargetBoneMap] and [RetargetBoneOption].
</member>
<member name="retarget_skeleton" type="NodePath" setter="set_retarget_skeleton" getter="get_retarget_skeleton" default="NodePath(&quot;&quot;)">
The [Skeleton3D] to extract or apply retarget tracks.
</member>
<member name="root_node" type="NodePath" setter="set_root" getter="get_root" default="NodePath(&quot;..&quot;)">
The node from which node path references will travel.
</member>
Expand Down
67 changes: 67 additions & 0 deletions doc/classes/RetargetBoneMap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RetargetBoneMap" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A map of skeleton bone names with intermediate bone names as key.
</brief_description>
<description>
To register a key in the editor, a [RetargetProfile] is required.
In the inspector, maps are organized by [RetargetProfile], but if there is no [RetargetProfile], they are listed in the unprofiled bones section.
</description>
<tutorials>
</tutorials>
<methods>
<method name="add_key">
<return type="void" />
<argument index="0" name="intermediate_bone_name" type="StringName" />
<description>
</description>
</method>
<method name="find_key" qualifiers="const">
<return type="StringName" />
<argument index="0" name="bone_name" type="StringName" />
<description>
</description>
</method>
<method name="get_bone_name" qualifiers="const">
<return type="StringName" />
<argument index="0" name="intermediate_bone_name" type="StringName" />
<description>
</description>
</method>
<method name="get_keys" qualifiers="const">
<return type="PackedStringArray" />
<description>
</description>
</method>
<method name="has_key">
<return type="bool" />
<argument index="0" name="intermediate_bone_name" type="StringName" />
<description>
</description>
</method>
<method name="remove_key">
<return type="void" />
<argument index="0" name="intermediate_bone_name" type="StringName" />
<description>
</description>
</method>
<method name="set_bone_name">
<return type="void" />
<argument index="0" name="intermediate_bone_name" type="StringName" />
<argument index="1" name="bone_name" type="StringName" />
<description>
</description>
</method>
</methods>
<signals>
<signal name="redraw_needed">
<description>
Emitted when the drawing on the inspector needs to be updated, it is enable only when [code]tools[/code] is enabled.
</description>
</signal>
<signal name="retarget_map_updated">
<description>
</description>
</signal>
</signals>
</class>
Loading

0 comments on commit 984509f

Please sign in to comment.