mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-11 13:21:10 +01:00
Cleaned up and added the skeleton modification stack implementations to the build. Also smaller fixes.
This commit is contained in:
parent
a09d72ea7d
commit
6be9bf5dfe
@ -810,7 +810,7 @@ Basis::operator String() const {
|
||||
|
||||
Quaternion Basis::get_quaternion() const {
|
||||
#ifdef MATH_CHECKS
|
||||
ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternionernion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
|
||||
ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors.");
|
||||
#endif
|
||||
/* Allow getting a quaternion from an unnormalized transform */
|
||||
Basis m = *this;
|
||||
|
@ -52,7 +52,7 @@ class ThreadWorkPool {
|
||||
C *instance;
|
||||
M method;
|
||||
U userdata;
|
||||
virtual void work() override {
|
||||
virtual void work() {
|
||||
while (true) {
|
||||
uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed);
|
||||
if (work_index >= max_elements) {
|
||||
|
@ -260,7 +260,7 @@
|
||||
<return type="int" />
|
||||
<argument index="0" name="track_idx" type="int" />
|
||||
<argument index="1" name="time" type="float" />
|
||||
<argument index="2" name="rotation" type="Quaternionernion" />
|
||||
<argument index="2" name="rotation" type="Quaternion" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<description>
|
||||
Override this method to commit a handle being edited (handles must have been previously added by [method EditorSpatialGizmo.add_handles] during [method _redraw]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo".
|
||||
If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the committed handle is secondary (see [method EditorNode3DGizmo.add_handles] for more information).
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the committed handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
@ -99,7 +99,7 @@
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to provide gizmo's handle names. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorNode3DGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
Override this method to provide gizmo's handle names. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_value" qualifiers="virtual">
|
||||
@ -109,7 +109,7 @@
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle].
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorNode3DGizmo.add_handles] for more information).
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
@ -142,7 +142,7 @@
|
||||
<argument index="1" name="id" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Override this method to return the current transform of a subgizmo. As with all subgizmo methods, the transform should be in local space respect to the gizmo's Node3D. This transform will be requested at the start of an edit and used in the [code]restore[/code] argument in [method _commit_subgizmos]. Called for this plugin's active gizmos.
|
||||
Override this method to return the current transform of a subgizmo. As with all subgizmo methods, the transform should be in local space respect to the gizmo's Spatial. This transform will be requested at the start of an edit and used in the [code]restore[/code] argument in [method _commit_subgizmos]. Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_gizmo" qualifiers="virtual">
|
||||
@ -158,7 +158,7 @@
|
||||
<argument index="1" name="id" type="int" />
|
||||
<argument index="2" name="secondary" type="bool" />
|
||||
<description>
|
||||
Override this method to return [code]true[/code] whenever to given handle should be highlighted in the editor. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorNode3DGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
Override this method to return [code]true[/code] whenever to given handle should be highlighted in the editor. The [code]secondary[/code] argument is [code]true[/code] when the requested handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information). Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_selectable_when_hidden" qualifiers="virtual">
|
||||
@ -182,8 +182,8 @@
|
||||
<argument index="3" name="camera" type="Camera" />
|
||||
<argument index="4" name="point" type="Vector2" />
|
||||
<description>
|
||||
Override this method to update the node's properties when the user drags a gizmo handle (previously added with [method EditorNode3DGizmo.add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the edited handle is secondary (see [method EditorNode3DGizmo.add_handles] for more information).
|
||||
Override this method to update the node's properties when the user drags a gizmo handle (previously added with [method EditorSpatialGizmo.add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts.
|
||||
The [code]secondary[/code] argument is [code]true[/code] when the edited handle is secondary (see [method EditorSpatialGizmo.add_handles] for more information).
|
||||
Called for this plugin's active gizmos.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="Quaternion" version="3.5">
|
||||
<brief_description>
|
||||
Quaternionernion.
|
||||
Quaternion.
|
||||
</brief_description>
|
||||
<description>
|
||||
A unit quaternion used for representing 3D rotations. Quaternionernions need to be normalized to be used for rotation.
|
||||
A unit quaternion used for representing 3D rotations. Quaternions need to be normalized to be used for rotation.
|
||||
It is similar to Basis, which implements matrix representation of rotations, and can be parametrized using both an axis-angle pair or Euler angles. Basis stores rotation, scale, and shearing, while Quaternion only stores rotation.
|
||||
Due to its compactness and the way it is stored in memory, certain operations (obtaining axis-angle and performing SLERP, in particular) are more efficient and robust against floating-point errors.
|
||||
</description>
|
||||
@ -71,7 +71,7 @@
|
||||
</description>
|
||||
</method>
|
||||
<method name="exp" qualifiers="const">
|
||||
<return type="Quaternionernion" />
|
||||
<return type="Quaternion" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -113,7 +113,7 @@
|
||||
</description>
|
||||
</method>
|
||||
<method name="log" qualifiers="const">
|
||||
<return type="Quaternionernion" />
|
||||
<return type="Quaternion" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -164,19 +164,19 @@
|
||||
<members>
|
||||
<member name="w" type="float" setter="" getter="" default="1.0">
|
||||
W component of the quaternion (real part).
|
||||
Quaternionernion components should usually not be manipulated directly.
|
||||
Quaternion components should usually not be manipulated directly.
|
||||
</member>
|
||||
<member name="x" type="float" setter="" getter="" default="0.0">
|
||||
X component of the quaternion (imaginary [code]i[/code] axis part).
|
||||
Quaternionernion components should usually not be manipulated directly.
|
||||
Quaternion components should usually not be manipulated directly.
|
||||
</member>
|
||||
<member name="y" type="float" setter="" getter="" default="0.0">
|
||||
Y component of the quaternion (imaginary [code]j[/code] axis part).
|
||||
Quaternionernion components should usually not be manipulated directly.
|
||||
Quaternion components should usually not be manipulated directly.
|
||||
</member>
|
||||
<member name="z" type="float" setter="" getter="" default="0.0">
|
||||
Z component of the quaternion (imaginary [code]k[/code] axis part).
|
||||
Quaternionernion components should usually not be manipulated directly.
|
||||
Quaternion components should usually not be manipulated directly.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
|
@ -160,7 +160,7 @@
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_bone_pose_rotation" qualifiers="const">
|
||||
<return type="Quaternionernion" />
|
||||
<return type="Quaternion" />
|
||||
<argument index="0" name="bone_idx" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
@ -193,18 +193,18 @@
|
||||
<method name="global_pose_to_local_pose">
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="bone_idx" type="int" />
|
||||
<argument index="1" name="global_pose" type="Transform3D" />
|
||||
<argument index="1" name="global_pose" type="Transform" />
|
||||
<description>
|
||||
Takes the passed-in global pose and converts it to local pose transform.
|
||||
This can be used to easily convert a global pose from [method get_bone_global_pose] to a global transform in [method set_bone_local_pose_override].
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_pose_to_world_transform">
|
||||
<return type="Transform3D" />
|
||||
<argument index="0" name="global_pose" type="Transform3D" />
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="global_pose" type="Transform" />
|
||||
<description>
|
||||
Takes the passed-in global pose and converts it to a world transform.
|
||||
This can be used to easily convert a global pose from [method get_bone_global_pose] to a global transform usable with a node's transform, like [member Node3D.global_transform] for example.
|
||||
This can be used to easily convert a global pose from [method get_bone_global_pose] to a global transform usable with a node's transform, like [member Spatial.global_transform] for example.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_pose_z_forward_to_bone_forward">
|
||||
@ -224,9 +224,9 @@
|
||||
</description>
|
||||
</method>
|
||||
<method name="local_pose_to_global_pose">
|
||||
<return type="Transform3D" />
|
||||
<return type="Transform" />
|
||||
<argument index="0" name="bone_idx" type="int" />
|
||||
<argument index="1" name="local_pose" type="Transform3D" />
|
||||
<argument index="1" name="local_pose" type="Transform" />
|
||||
<description>
|
||||
Converts the passed-in local pose to a global pose relative to the inputted bone, [code]bone_idx[/code].
|
||||
This could be used to convert [method get_bone_pose] for use with the [method set_bone_global_pose_override] function.
|
||||
@ -315,13 +315,13 @@
|
||||
<description>
|
||||
Sets the global pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code].
|
||||
[code]amount[/code] is the interpolation strengh that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain.
|
||||
[b]Note:[/b] The pose transform needs to be a global pose! Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Node3D], to a global pose.
|
||||
[b]Note:[/b] The pose transform needs to be a global pose! Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Spatial], to a global pose.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_bone_local_pose_override">
|
||||
<return type="void" />
|
||||
<argument index="0" name="bone_idx" type="int" />
|
||||
<argument index="1" name="pose" type="Transform3D" />
|
||||
<argument index="1" name="pose" type="Transform" />
|
||||
<argument index="2" name="amount" type="float" />
|
||||
<argument index="3" name="persistent" type="bool" default="false" />
|
||||
<description>
|
||||
@ -352,7 +352,7 @@
|
||||
<argument index="1" name="pose" type="Transform" />
|
||||
<description>
|
||||
Sets the pose transform for bone [code]bone_idx[/code]. Prefer set_bone_pose_position, set_bone_pose_rotation, or set_bone_pose_scale instead.
|
||||
[b]Note:[/b] The pose transform needs to be in bone space. Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Node3D], to bone space.
|
||||
[b]Note:[/b] The pose transform needs to be in bone space. Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Spatial], to bone space.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_bone_pose_position">
|
||||
@ -365,7 +365,7 @@
|
||||
<method name="set_bone_pose_rotation">
|
||||
<return type="void" />
|
||||
<argument index="0" name="bone_idx" type="int" />
|
||||
<argument index="1" name="rotation" type="Quaternionernion" />
|
||||
<argument index="1" name="rotation" type="Quaternion" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
@ -375,7 +375,7 @@
|
||||
<argument index="1" name="scale" type="Vector3" />
|
||||
<description>
|
||||
Sets the pose transform for bone [code]bone_idx[/code].
|
||||
[b]Note:[/b] The pose transform needs to be in bone space. Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Node3D], to bone space.
|
||||
[b]Note:[/b] The pose transform needs to be in bone space. Use [method world_transform_to_global_pose] to convert a world transform, like one you can get from a [Spatial], to bone space.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_bone_rest">
|
||||
@ -407,7 +407,7 @@
|
||||
</argument>
|
||||
<description>
|
||||
Takes the passed-in global transform and converts it to a global pose.
|
||||
This can be used to easily convert a global transform from [member Node3D.global_transform] to a global pose usable with [method set_bone_global_pose_override], for example.
|
||||
This can be used to easily convert a global transform from [member Spatial.global_transform] to a global pose usable with [method set_bone_global_pose_override], for example.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
@ -59,7 +59,7 @@
|
||||
<return type="NodePath" />
|
||||
<argument index="0" name="joint_idx" type="int" />
|
||||
<description>
|
||||
Returns the [Node3D]-based node placed at the tip of the FABRIK joint at [code]joint_idx[/code], if one has been set.
|
||||
Returns the [Spatial]-based node placed at the tip of the FABRIK joint at [code]joint_idx[/code], if one has been set.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_fabrik_joint_use_target_basis" qualifiers="const">
|
||||
@ -74,7 +74,7 @@
|
||||
<return type="bool" />
|
||||
<argument index="0" name="joint_idx" type="int" />
|
||||
<description>
|
||||
Sets the [Node3D]-based node that will be used as the tip of the FABRIK joint at [code]joint_idx[/code].
|
||||
Sets the [Spatial]-based node that will be used as the tip of the FABRIK joint at [code]joint_idx[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_fabrik_joint_auto_calculate_length">
|
||||
|
@ -6,7 +6,7 @@
|
||||
<description>
|
||||
This [SkeletonModification3D] uses an algorithm typically called TwoBoneIK. This algorithm works by leveraging the law of cosigns and the lengths of the bones to figure out what rotation the bones currently have, and what rotation they need to make a complete triangle, where the first bone, the second bone, and the target form the three vertices of the triangle. Because the algorithm works by making a triangle, it can only operate on two bones.
|
||||
TwoBoneIK is great for arms, legs, and really any joints that can be represented by just two bones that bend to reach a target. This solver is more lightweight than [SkeletonModification3DFABRIK], but gives similar, natural looking results.
|
||||
A [Node3D]-based node can be used to define the pole, or bend direction, allowing control over which direction the joint takes when bending to reach the target when the target is within reach.
|
||||
A [Spatial]-based node can be used to define the pole, or bend direction, allowing control over which direction the joint takes when bending to reach the target when the target is within reach.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -47788,12 +47788,12 @@ msgid "Size on the X and Y axes."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid "Quaternionernion."
|
||||
msgid "Quaternion."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"A unit quaternion used for representing 3D rotations. Quaternionernions need to be "
|
||||
"A unit quaternion used for representing 3D rotations. Quaternions need to be "
|
||||
"normalized to be used for rotation.\n"
|
||||
"It is similar to Basis, which implements matrix representation of rotations, "
|
||||
"and can be parametrized using both an axis-angle pair or Euler angles. Basis "
|
||||
@ -47914,25 +47914,25 @@ msgstr ""
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"W component of the quaternion (real part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"X component of the quaternion (imaginary [code]i[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"Y component of the quaternion (imaginary [code]j[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"Z component of the quaternion (imaginary [code]k[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
|
@ -47873,12 +47873,12 @@ msgid "Size on the X and Y axes."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid "Quaternionernion."
|
||||
msgid "Quaternion."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"A unit quaternion used for representing 3D rotations. Quaternionernions need to be "
|
||||
"A unit quaternion used for representing 3D rotations. Quaternions need to be "
|
||||
"normalized to be used for rotation.\n"
|
||||
"It is similar to Basis, which implements matrix representation of rotations, "
|
||||
"and can be parametrized using both an axis-angle pair or Euler angles. Basis "
|
||||
@ -47999,25 +47999,25 @@ msgstr ""
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"W component of the quaternion (real part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"X component of the quaternion (imaginary [code]i[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"Y component of the quaternion (imaginary [code]j[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
msgid ""
|
||||
"Z component of the quaternion (imaginary [code]k[/code] axis part).\n"
|
||||
"Quaternionernion components should usually not be manipulated directly."
|
||||
"Quaternion components should usually not be manipulated directly."
|
||||
msgstr ""
|
||||
|
||||
#: doc/classes/Quaternion.xml
|
||||
|
@ -204,7 +204,7 @@ bool test_rotation(Vector3 deg_original_euler, RotOrder rot_order) {
|
||||
OS *os = OS::get_singleton();
|
||||
os->print("Rotation order: %s\n.", get_rot_order_name(rot_order).utf8().get_data());
|
||||
os->print("Original Rotation: %s\n", String(deg_original_euler).utf8().get_data());
|
||||
os->print("Quaternionernion to rotation order: %s\n", String(rad2deg(euler_from_rotation)).utf8().get_data());
|
||||
os->print("Quaternion to rotation order: %s\n", String(rad2deg(euler_from_rotation)).utf8().get_data());
|
||||
}
|
||||
|
||||
return pass;
|
||||
|
@ -407,13 +407,13 @@ struct ServerController : public Controller {
|
||||
|
||||
void process(real_t p_delta);
|
||||
uint32_t last_known_input() const;
|
||||
virtual uint32_t get_current_input_id() const override;
|
||||
virtual uint32_t get_current_input_id() const;
|
||||
|
||||
void set_enabled(bool p_enable);
|
||||
|
||||
virtual void clear_peers() override;
|
||||
virtual void activate_peer(int p_peer) override;
|
||||
virtual void deactivate_peer(int p_peer) override;
|
||||
virtual void clear_peers();
|
||||
virtual void activate_peer(int p_peer);
|
||||
virtual void deactivate_peer(int p_peer);
|
||||
|
||||
void receive_inputs(const PoolVector<uint8_t> &p_data);
|
||||
int get_inputs_count() const;
|
||||
@ -459,7 +459,7 @@ struct PlayerController : public Controller {
|
||||
int notify_input_checked(uint32_t p_input_id);
|
||||
uint32_t last_known_input() const;
|
||||
uint32_t get_stored_input_id(int p_i) const;
|
||||
virtual uint32_t get_current_input_id() const override;
|
||||
virtual uint32_t get_current_input_id() const;
|
||||
|
||||
bool process_instant(int p_i, real_t p_delta);
|
||||
real_t get_pretended_delta(real_t p_iteration_per_second) const;
|
||||
@ -499,10 +499,10 @@ struct DollController : public Controller {
|
||||
|
||||
DollController(NetworkedController *p_node);
|
||||
|
||||
virtual void ready() override;
|
||||
virtual void ready();
|
||||
void process(real_t p_delta);
|
||||
// TODO consider make this non virtual
|
||||
virtual uint32_t get_current_input_id() const override;
|
||||
virtual uint32_t get_current_input_id() const;
|
||||
|
||||
void receive_batch(const PoolVector<uint8_t> &p_data);
|
||||
uint32_t receive_epoch(const PoolVector<uint8_t> &p_data);
|
||||
@ -520,7 +520,7 @@ struct NoNetController : public Controller {
|
||||
NoNetController(NetworkedController *p_node);
|
||||
|
||||
void process(real_t p_delta);
|
||||
virtual uint32_t get_current_input_id() const override;
|
||||
virtual uint32_t get_current_input_id() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -351,8 +351,8 @@ class NoNetSynchronizer : public Synchronizer {
|
||||
public:
|
||||
NoNetSynchronizer(SceneSynchronizer *p_node);
|
||||
|
||||
virtual void clear() override;
|
||||
virtual void process() override;
|
||||
virtual void clear();
|
||||
virtual void process();
|
||||
|
||||
void set_enabled(bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
@ -375,11 +375,11 @@ class ServerSynchronizer : public Synchronizer {
|
||||
public:
|
||||
ServerSynchronizer(SceneSynchronizer *p_node);
|
||||
|
||||
virtual void clear() override;
|
||||
virtual void process() override;
|
||||
virtual void on_node_added(NetUtility::NodeData *p_node_data) override;
|
||||
virtual void on_variable_added(NetUtility::NodeData *p_node_data, const StringName &p_var_name) override;
|
||||
virtual void on_variable_changed(NetUtility::NodeData *p_node_data, NetVarId p_var_id, const Variant &p_old_value, int p_flag) override;
|
||||
virtual void clear();
|
||||
virtual void process();
|
||||
virtual void on_node_added(NetUtility::NodeData *p_node_data);
|
||||
virtual void on_variable_added(NetUtility::NodeData *p_node_data, const StringName &p_var_name);
|
||||
virtual void on_variable_changed(NetUtility::NodeData *p_node_data, NetVarId p_var_id, const Variant &p_old_value, int p_flag);
|
||||
|
||||
void process_snapshot_notificator(real_t p_delta);
|
||||
Vector<Variant> global_nodes_generate_snapshot(bool p_force_full_snapshot) const;
|
||||
@ -421,13 +421,13 @@ class ClientSynchronizer : public Synchronizer {
|
||||
public:
|
||||
ClientSynchronizer(SceneSynchronizer *p_node);
|
||||
|
||||
virtual void clear() override;
|
||||
virtual void clear();
|
||||
|
||||
virtual void process() override;
|
||||
virtual void on_node_added(NetUtility::NodeData *p_node_data) override;
|
||||
virtual void on_node_removed(NetUtility::NodeData *p_node_data) override;
|
||||
virtual void on_variable_changed(NetUtility::NodeData *p_node_data, NetVarId p_var_id, const Variant &p_old_value, int p_flag) override;
|
||||
virtual void on_controller_reset(NetUtility::NodeData *p_node_data) override;
|
||||
virtual void process();
|
||||
virtual void on_node_added(NetUtility::NodeData *p_node_data);
|
||||
virtual void on_node_removed(NetUtility::NodeData *p_node_data);
|
||||
virtual void on_variable_changed(NetUtility::NodeData *p_node_data, NetVarId p_var_id, const Variant &p_old_value, int p_flag);
|
||||
virtual void on_controller_reset(NetUtility::NodeData *p_node_data);
|
||||
|
||||
void receive_snapshot(Variant p_snapshot);
|
||||
bool parse_sync_data(
|
||||
|
@ -60,31 +60,31 @@ class DirAccessJAndroid : public DirAccessUnix {
|
||||
static jmethodID _current_is_hidden;
|
||||
|
||||
public:
|
||||
virtual Error list_dir_begin() override; ///< This starts dir listing
|
||||
virtual String get_next() override;
|
||||
virtual bool current_is_dir() const override;
|
||||
virtual bool current_is_hidden() const override;
|
||||
virtual void list_dir_end() override; ///<
|
||||
virtual Error list_dir_begin(); ///< This starts dir listing
|
||||
virtual String get_next();
|
||||
virtual bool current_is_dir() const;
|
||||
virtual bool current_is_hidden() const;
|
||||
virtual void list_dir_end(); ///<
|
||||
|
||||
virtual int get_drive_count() override;
|
||||
virtual String get_drive(int p_drive) override;
|
||||
virtual int get_drive_count();
|
||||
virtual String get_drive(int p_drive);
|
||||
|
||||
virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
|
||||
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
|
||||
|
||||
virtual bool file_exists(String p_file) override;
|
||||
virtual bool dir_exists(String p_dir) override;
|
||||
virtual bool file_exists(String p_file);
|
||||
virtual bool dir_exists(String p_dir);
|
||||
|
||||
virtual Error make_dir(String p_dir) override;
|
||||
virtual Error make_dir_recursive(String p_dir) override;
|
||||
virtual Error make_dir(String p_dir);
|
||||
virtual Error make_dir_recursive(String p_dir);
|
||||
|
||||
virtual Error rename(String p_from, String p_to) override;
|
||||
virtual Error remove(String p_name) override;
|
||||
virtual Error rename(String p_from, String p_to);
|
||||
virtual Error remove(String p_name);
|
||||
|
||||
virtual bool is_link(String p_file) override { return false; }
|
||||
virtual String read_link(String p_file) override { return p_file; }
|
||||
virtual Error create_link(String p_source, String p_target) override { return FAILED; }
|
||||
virtual bool is_link(String p_file) { return false; }
|
||||
virtual String read_link(String p_file) { return p_file; }
|
||||
virtual Error create_link(String p_source, String p_target) { return FAILED; }
|
||||
|
||||
virtual uint64_t get_space_left() override;
|
||||
virtual uint64_t get_space_left();
|
||||
|
||||
static void setup(jobject p_dir_access_handler);
|
||||
|
||||
|
@ -56,39 +56,39 @@ class FileAccessFilesystemJAndroid : public FileAccess {
|
||||
String path_src;
|
||||
|
||||
public:
|
||||
virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file
|
||||
virtual void close() override; ///< close a file
|
||||
virtual bool is_open() const override; ///< true when file is open
|
||||
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
|
||||
virtual void close(); ///< close a file
|
||||
virtual bool is_open() const; ///< true when file is open
|
||||
|
||||
/// returns the path for the current open file
|
||||
virtual String get_path() const override;
|
||||
virtual String get_path() const;
|
||||
/// returns the absolute path for the current open file
|
||||
virtual String get_path_absolute() const override;
|
||||
virtual String get_path_absolute() const;
|
||||
|
||||
virtual void seek(uint64_t p_position) override; ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
|
||||
virtual uint64_t get_position() const override; ///< get position in the file
|
||||
virtual uint64_t get_len() const override; ///< get size of the file
|
||||
virtual void seek(uint64_t p_position); ///< seek to a given position
|
||||
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
|
||||
virtual uint64_t get_position() const; ///< get position in the file
|
||||
virtual uint64_t get_len() const; ///< get size of the file
|
||||
|
||||
virtual bool eof_reached() const override; ///< reading passed EOF
|
||||
virtual bool eof_reached() const; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const override; ///< get a byte
|
||||
virtual String get_line() const override; ///< get a line
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
virtual String get_line() const; ///< get a line
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const;
|
||||
|
||||
virtual Error get_error() const override; ///< get last error
|
||||
virtual Error get_error() const; ///< get last error
|
||||
|
||||
virtual void flush() override;
|
||||
virtual void store_8(uint8_t p_dest) override; ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
|
||||
virtual void flush();
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length);
|
||||
|
||||
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
|
||||
virtual bool file_exists(const String &p_path); ///< return true if a file exists
|
||||
|
||||
static void setup(jobject p_file_access_handler);
|
||||
|
||||
virtual uint64_t _get_modified_time(const String &p_file) override;
|
||||
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
|
||||
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
|
||||
virtual uint64_t _get_modified_time(const String &p_file);
|
||||
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
|
||||
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
|
||||
|
||||
FileAccessFilesystemJAndroid();
|
||||
~FileAccessFilesystemJAndroid();
|
||||
|
@ -76,12 +76,12 @@ public:
|
||||
virtual void start() final;
|
||||
virtual void finish() final;
|
||||
|
||||
virtual float get_latency() override;
|
||||
virtual int get_mix_rate() const override;
|
||||
virtual SpeakerMode get_speaker_mode() const override;
|
||||
virtual float get_latency();
|
||||
virtual int get_mix_rate() const;
|
||||
virtual SpeakerMode get_speaker_mode() const;
|
||||
|
||||
virtual Error capture_start() override;
|
||||
virtual Error capture_stop() override;
|
||||
virtual Error capture_start();
|
||||
virtual Error capture_stop();
|
||||
|
||||
static void resume();
|
||||
|
||||
@ -96,14 +96,14 @@ private:
|
||||
static AudioDriverScriptProcessor *singleton;
|
||||
|
||||
protected:
|
||||
Error create(int &p_buffer_samples, int p_channels) override;
|
||||
void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override;
|
||||
Error create(int &p_buffer_samples, int p_channels);
|
||||
void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size);
|
||||
|
||||
public:
|
||||
virtual const char *get_name() const override { return "ScriptProcessor"; }
|
||||
virtual const char *get_name() const { return "ScriptProcessor"; }
|
||||
|
||||
virtual void lock() override {}
|
||||
virtual void unlock() override {}
|
||||
virtual void lock() {}
|
||||
virtual void unlock() {}
|
||||
|
||||
AudioDriverScriptProcessor() { singleton = this; }
|
||||
};
|
||||
@ -116,14 +116,14 @@ private:
|
||||
static AudioDriverWorklet *singleton;
|
||||
|
||||
protected:
|
||||
virtual Error create(int &p_buffer_size, int p_output_channels) override;
|
||||
virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override;
|
||||
virtual Error create(int &p_buffer_size, int p_output_channels);
|
||||
virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size);
|
||||
|
||||
public:
|
||||
virtual const char *get_name() const override { return "AudioWorklet"; }
|
||||
virtual const char *get_name() const { return "AudioWorklet"; }
|
||||
|
||||
virtual void lock() override {}
|
||||
virtual void unlock() override {}
|
||||
virtual void lock() {}
|
||||
virtual void unlock() {}
|
||||
|
||||
AudioDriverWorklet() { singleton = this; }
|
||||
};
|
||||
@ -145,15 +145,15 @@ private:
|
||||
static void _audio_thread_func(void *p_data);
|
||||
|
||||
protected:
|
||||
virtual Error create(int &p_buffer_size, int p_output_channels) override;
|
||||
virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override;
|
||||
virtual void finish_driver() override;
|
||||
virtual Error create(int &p_buffer_size, int p_output_channels);
|
||||
virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size);
|
||||
virtual void finish_driver();
|
||||
|
||||
public:
|
||||
virtual const char *get_name() const override { return "AudioWorklet"; }
|
||||
virtual const char *get_name() const { return "AudioWorklet"; }
|
||||
|
||||
void lock() override;
|
||||
void unlock() override;
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -73,14 +73,14 @@ private:
|
||||
static void _callback(void *p_ref, int p_arg_id, int p_argc);
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value) override;
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const override;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const override;
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const override;
|
||||
void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = nullptr) override;
|
||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argc, Variant::CallError &r_error) override;
|
||||
Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const;
|
||||
void setvar(const Variant &p_key, const Variant &p_value, bool *r_valid = nullptr);
|
||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argc, Variant::CallError &r_error);
|
||||
JavaScriptObjectImpl() {}
|
||||
JavaScriptObjectImpl(int p_id) { _js_id = p_id; }
|
||||
~JavaScriptObjectImpl() {
|
||||
|
@ -162,13 +162,13 @@ public:
|
||||
|
||||
Vector<String> parse_requirements() const;
|
||||
|
||||
virtual PoolByteArray get_hash_sha1() const override;
|
||||
virtual PoolByteArray get_hash_sha256() const override;
|
||||
virtual PoolByteArray get_hash_sha1() const;
|
||||
virtual PoolByteArray get_hash_sha256() const;
|
||||
|
||||
virtual int get_size() const override;
|
||||
virtual int get_size() const;
|
||||
|
||||
virtual uint32_t get_index_type() const override { return 0x00000002; };
|
||||
virtual void write_to_file(FileAccess *p_file) const override;
|
||||
virtual uint32_t get_index_type() const { return 0x00000002; };
|
||||
virtual void write_to_file(FileAccess *p_file) const;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@ -184,13 +184,13 @@ public:
|
||||
CodeSignEntitlementsText();
|
||||
CodeSignEntitlementsText(const String &p_string);
|
||||
|
||||
virtual PoolByteArray get_hash_sha1() const override;
|
||||
virtual PoolByteArray get_hash_sha256() const override;
|
||||
virtual PoolByteArray get_hash_sha1() const;
|
||||
virtual PoolByteArray get_hash_sha256() const;
|
||||
|
||||
virtual int get_size() const override;
|
||||
virtual int get_size() const;
|
||||
|
||||
virtual uint32_t get_index_type() const override { return 0x00000005; };
|
||||
virtual void write_to_file(FileAccess *p_file) const override;
|
||||
virtual uint32_t get_index_type() const { return 0x00000005; };
|
||||
virtual void write_to_file(FileAccess *p_file) const;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@ -206,13 +206,13 @@ public:
|
||||
CodeSignEntitlementsBinary();
|
||||
CodeSignEntitlementsBinary(const String &p_string);
|
||||
|
||||
virtual PoolByteArray get_hash_sha1() const override;
|
||||
virtual PoolByteArray get_hash_sha256() const override;
|
||||
virtual PoolByteArray get_hash_sha1() const;
|
||||
virtual PoolByteArray get_hash_sha256() const;
|
||||
|
||||
virtual int get_size() const override;
|
||||
virtual int get_size() const;
|
||||
|
||||
virtual uint32_t get_index_type() const override { return 0x00000007; };
|
||||
virtual void write_to_file(FileAccess *p_file) const override;
|
||||
virtual uint32_t get_index_type() const { return 0x00000007; };
|
||||
virtual void write_to_file(FileAccess *p_file) const;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@ -308,13 +308,13 @@ public:
|
||||
|
||||
bool set_hash_in_slot(const PoolByteArray &p_hash, int p_slot);
|
||||
|
||||
virtual PoolByteArray get_hash_sha1() const override;
|
||||
virtual PoolByteArray get_hash_sha256() const override;
|
||||
virtual PoolByteArray get_hash_sha1() const;
|
||||
virtual PoolByteArray get_hash_sha256() const;
|
||||
|
||||
virtual int get_size() const override;
|
||||
virtual uint32_t get_index_type() const override { return 0x00000000; };
|
||||
virtual int get_size() const;
|
||||
virtual uint32_t get_index_type() const { return 0x00000000; };
|
||||
|
||||
virtual void write_to_file(FileAccess *p_file) const override;
|
||||
virtual void write_to_file(FileAccess *p_file) const;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@ -327,13 +327,13 @@ class CodeSignSignature : public CodeSignBlob {
|
||||
public:
|
||||
CodeSignSignature();
|
||||
|
||||
virtual PoolByteArray get_hash_sha1() const override;
|
||||
virtual PoolByteArray get_hash_sha256() const override;
|
||||
virtual PoolByteArray get_hash_sha1() const;
|
||||
virtual PoolByteArray get_hash_sha256() const;
|
||||
|
||||
virtual int get_size() const override;
|
||||
virtual uint32_t get_index_type() const override { return 0x00010000; };
|
||||
virtual int get_size() const;
|
||||
virtual uint32_t get_index_type() const { return 0x00010000; };
|
||||
|
||||
virtual void write_to_file(FileAccess *p_file) const override;
|
||||
virtual void write_to_file(FileAccess *p_file) const;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -177,12 +177,12 @@
|
||||
#include "scene/scene_string_names.h"
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_ccdik.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_fabrik.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_jiggle.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_lookat.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_stackholder.h"
|
||||
//#include "scene/resources/skeleton_modification_3d_twoboneik.h"
|
||||
#include "scene/resources/skeleton_modification_3d_ccdik.h"
|
||||
#include "scene/resources/skeleton_modification_3d_fabrik.h"
|
||||
#include "scene/resources/skeleton_modification_3d_jiggle.h"
|
||||
#include "scene/resources/skeleton_modification_3d_lookat.h"
|
||||
#include "scene/resources/skeleton_modification_3d_stackholder.h"
|
||||
#include "scene/resources/skeleton_modification_3d_twoboneik.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
@ -617,12 +617,12 @@ void register_scene_types() {
|
||||
|
||||
ClassDB::register_class<SkeletonModificationStack3D>();
|
||||
ClassDB::register_class<SkeletonModification3D>();
|
||||
//ClassDB::register_class<SkeletonModification3DLookAt>();
|
||||
//ClassDB::register_class<SkeletonModification3DCCDIK>();
|
||||
//ClassDB::register_class<SkeletonModification3DFABRIK>();
|
||||
//ClassDB::register_class<SkeletonModification3DJiggle>();
|
||||
//ClassDB::register_class<SkeletonModification3DTwoBoneIK>();
|
||||
//ClassDB::register_class<SkeletonModification3DStackHolder>();
|
||||
ClassDB::register_class<SkeletonModification3DLookAt>();
|
||||
ClassDB::register_class<SkeletonModification3DCCDIK>();
|
||||
ClassDB::register_class<SkeletonModification3DFABRIK>();
|
||||
ClassDB::register_class<SkeletonModification3DJiggle>();
|
||||
ClassDB::register_class<SkeletonModification3DTwoBoneIK>();
|
||||
ClassDB::register_class<SkeletonModification3DStackHolder>();
|
||||
|
||||
OS::get_singleton()->yield(); //may take time to init
|
||||
|
||||
|
@ -87,7 +87,7 @@ private:
|
||||
Key() { transition = 1; }
|
||||
};
|
||||
|
||||
// transform key holds either Vector3 or Quaternionernion
|
||||
// transform key holds either Vector3 or Quaternion
|
||||
template <class T>
|
||||
struct TKey : public Key {
|
||||
T value;
|
||||
|
@ -161,4 +161,9 @@ void SkeletonModification3D::_bind_methods() {
|
||||
SkeletonModification3D::SkeletonModification3D() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
|
||||
execution_mode = 0; // 0 = process
|
||||
|
||||
enabled = true;
|
||||
execution_error_found = false;
|
||||
}
|
||||
|
@ -44,12 +44,12 @@ class SkeletonModification3D : public Resource {
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
SkeletonModificationStack3D *stack = nullptr;
|
||||
int execution_mode = 0; // 0 = process
|
||||
SkeletonModificationStack3D *stack;
|
||||
int execution_mode; // 0 = process
|
||||
|
||||
bool enabled = true;
|
||||
bool is_setup = false;
|
||||
bool execution_error_found = false;
|
||||
bool enabled;
|
||||
bool is_setup;
|
||||
bool execution_error_found;
|
||||
|
||||
bool _print_execution_error(bool p_condition, String p_message);
|
||||
|
||||
|
@ -29,8 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_ccdik.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
bool SkeletonModification3DCCDIK::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
@ -102,26 +102,26 @@ void SkeletonModification3DCCDIK::_get_property_list(List<PropertyInfo> *p_list)
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "enable_joint_constraint", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (ccdik_data_chain[i].enable_constraint) {
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "joint_constraint_angle_min", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "joint_constraint_angle_max", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "joint_constraint_angle_min", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "joint_constraint_angle_max", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "joint_constraint_angles_invert", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModification3DCCDIK::_execute(real_t p_delta) {
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
|
||||
"Modification is not setup and therefore cannot execute!");
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr, "Modification is not setup and therefore cannot execute!");
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_node_cache.is_null()) {
|
||||
if (target_node_cache== 0) {
|
||||
_print_execution_error(true, "Target cache is out of date. Attempting to update");
|
||||
update_target_cache();
|
||||
return;
|
||||
}
|
||||
if (tip_node_cache.is_null()) {
|
||||
if (tip_node_cache == 0) {
|
||||
_print_execution_error(true, "Tip cache is out of date. Attempting to update");
|
||||
update_tip_cache();
|
||||
return;
|
||||
@ -134,8 +134,8 @@ void SkeletonModification3DCCDIK::_execute(real_t p_delta) {
|
||||
0.0, false);
|
||||
}
|
||||
|
||||
Node3D *node_target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
|
||||
Node3D *node_tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
|
||||
Spatial *node_target = Object::cast_to<Spatial>(ObjectDB::get_instance(target_node_cache));
|
||||
Spatial *node_tip = Object::cast_to<Spatial>(ObjectDB::get_instance(tip_node_cache));
|
||||
|
||||
if (_print_execution_error(!node_target || !node_target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
@ -159,7 +159,7 @@ void SkeletonModification3DCCDIK::_execute(real_t p_delta) {
|
||||
execution_error_found = false;
|
||||
}
|
||||
|
||||
void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node3D *p_target, Node3D *p_tip) {
|
||||
void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Spatial *p_target, Spatial *p_tip) {
|
||||
CCDIK_Joint_Data ccdik_data = ccdik_data_chain[p_joint_idx];
|
||||
|
||||
if (_print_execution_error(ccdik_data.bone_idx < 0 || ccdik_data.bone_idx > stack->skeleton->get_bone_count(),
|
||||
@ -167,9 +167,9 @@ void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node3D *
|
||||
return;
|
||||
}
|
||||
|
||||
Transform3D bone_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->get_bone_global_pose(ccdik_data.bone_idx));
|
||||
Transform3D tip_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_tip->get_global_transform()));
|
||||
Transform3D target_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_target->get_global_transform()));
|
||||
Transform bone_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->get_bone_global_pose(ccdik_data.bone_idx));
|
||||
Transform tip_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_tip->get_global_transform()));
|
||||
Transform target_trans = stack->skeleton->global_pose_to_local_pose(ccdik_data.bone_idx, stack->skeleton->world_transform_to_global_pose(p_target->get_global_transform()));
|
||||
|
||||
if (tip_trans.origin.distance_to(target_trans.origin) <= 0.01) {
|
||||
return;
|
||||
@ -232,8 +232,9 @@ void SkeletonModification3DCCDIK::_execute_ccdik_joint(int p_joint_idx, Node3D *
|
||||
stack->skeleton->force_update_bone_children_transforms(ccdik_data.bone_idx);
|
||||
}
|
||||
|
||||
void SkeletonModification3DCCDIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DCCDIK::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
|
||||
if (stack != nullptr) {
|
||||
is_setup = true;
|
||||
execution_error_found = false;
|
||||
@ -332,7 +333,7 @@ void SkeletonModification3DCCDIK::set_ccdik_joint_bone_name(int p_joint_idx, Str
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DCCDIK::get_ccdik_joint_bone_index(int p_joint_idx) const {
|
||||
@ -353,7 +354,7 @@ void SkeletonModification3DCCDIK::set_ccdik_joint_bone_index(int p_joint_idx, in
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DCCDIK::get_ccdik_joint_ccdik_axis(int p_joint_idx) const {
|
||||
@ -367,7 +368,7 @@ void SkeletonModification3DCCDIK::set_ccdik_joint_ccdik_axis(int p_joint_idx, in
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
ERR_FAIL_COND_MSG(p_axis < 0, "CCDIK axis is out of range: The axis mode is too low!");
|
||||
ccdik_data_chain[p_joint_idx].ccdik_axis = p_axis;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DCCDIK::get_ccdik_joint_enable_constraint(int p_joint_idx) const {
|
||||
@ -380,7 +381,7 @@ void SkeletonModification3DCCDIK::set_ccdik_joint_enable_constraint(int p_joint_
|
||||
const int bone_chain_size = ccdik_data_chain.size();
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
ccdik_data_chain[p_joint_idx].enable_constraint = p_enable;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
real_t SkeletonModification3DCCDIK::get_ccdik_joint_constraint_angle_min(int p_joint_idx) const {
|
||||
@ -426,7 +427,7 @@ void SkeletonModification3DCCDIK::set_ccdik_data_chain_length(int p_length) {
|
||||
ERR_FAIL_COND(p_length < 0);
|
||||
ccdik_data_chain.resize(p_length);
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
void SkeletonModification3DCCDIK::_bind_methods() {
|
||||
@ -458,8 +459,8 @@ void SkeletonModification3DCCDIK::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_ccdik_data_chain_length", "length"), &SkeletonModification3DCCDIK::set_ccdik_data_chain_length);
|
||||
ClassDB::bind_method(D_METHOD("get_ccdik_data_chain_length"), &SkeletonModification3DCCDIK::get_ccdik_data_chain_length);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "tip_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_tip_node", "get_tip_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "tip_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_tip_node", "get_tip_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "high_quality_solve", PROPERTY_HINT_NONE, ""), "set_use_high_quality_solve", "get_use_high_quality_solve");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "ccdik_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_ccdik_data_chain_length", "get_ccdik_data_chain_length");
|
||||
}
|
||||
@ -468,6 +469,10 @@ SkeletonModification3DCCDIK::SkeletonModification3DCCDIK() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
enabled = true;
|
||||
|
||||
target_node_cache = 0;
|
||||
tip_node_cache = 0;
|
||||
use_high_quality_solve = true;
|
||||
}
|
||||
|
||||
SkeletonModification3DCCDIK::~SkeletonModification3DCCDIK() {
|
@ -1,3 +1,7 @@
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_CCDIK_H
|
||||
#define SKELETON_MODIFICATION_3D_CCDIK_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_ccdik.h */
|
||||
/*************************************************************************/
|
||||
@ -28,13 +32,10 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "core/containers/local_vector.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_CCDIK_H
|
||||
#define SKELETON_MODIFICATION_3D_CCDIK_H
|
||||
|
||||
class SkeletonModification3DCCDIK : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DCCDIK, SkeletonModification3D);
|
||||
|
||||
@ -46,14 +47,24 @@ private:
|
||||
};
|
||||
|
||||
struct CCDIK_Joint_Data {
|
||||
String bone_name = "";
|
||||
int bone_idx = -1;
|
||||
int ccdik_axis = 0;
|
||||
String bone_name;
|
||||
int bone_idx;
|
||||
int ccdik_axis;
|
||||
|
||||
bool enable_constraint = false;
|
||||
real_t constraint_angle_min = 0;
|
||||
real_t constraint_angle_max = (2.0 * Math_PI);
|
||||
bool constraint_angles_invert = false;
|
||||
bool enable_constraint;
|
||||
real_t constraint_angle_min;
|
||||
real_t constraint_angle_max;
|
||||
bool constraint_angles_invert;
|
||||
|
||||
CCDIK_Joint_Data() {
|
||||
bone_idx = -1;
|
||||
ccdik_axis = 0;
|
||||
|
||||
enable_constraint = false;
|
||||
constraint_angle_min = 0;
|
||||
constraint_angle_max = (2.0 * Math_PI);
|
||||
constraint_angles_invert = false;
|
||||
}
|
||||
};
|
||||
|
||||
LocalVector<CCDIK_Joint_Data> ccdik_data_chain;
|
||||
@ -63,12 +74,12 @@ private:
|
||||
NodePath tip_node;
|
||||
ObjectID tip_node_cache;
|
||||
|
||||
bool use_high_quality_solve = true;
|
||||
bool use_high_quality_solve;
|
||||
|
||||
void update_target_cache();
|
||||
void update_tip_cache();
|
||||
|
||||
void _execute_ccdik_joint(int p_joint_idx, Node3D *p_target, Node3D *p_tip);
|
||||
void _execute_ccdik_joint(int p_joint_idx, Spatial *p_target, Spatial *p_tip);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
@ -77,8 +88,8 @@ protected:
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_target_node(const NodePath &p_target_node);
|
||||
NodePath get_target_node() const;
|
@ -29,8 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_fabrik.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
bool SkeletonModification3DFABRIK::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
@ -104,15 +104,15 @@ void SkeletonModification3DFABRIK::_get_property_list(List<PropertyInfo> *p_list
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING_NAME, base_string + "bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "auto_calculate_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
|
||||
if (!fabrik_data_chain[i].auto_calculate_length) {
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
} else {
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_tip_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (fabrik_data_chain[i].use_tip_node) {
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_node_cache.is_null()) {
|
||||
if (target_node_cache == 0) {
|
||||
_print_execution_error(true, "Target cache is out of date. Attempting to update...");
|
||||
update_target_cache();
|
||||
return;
|
||||
@ -144,7 +144,7 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node3D *node_target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
|
||||
Spatial *node_target = Object::cast_to<Spatial>(ObjectDB::get_instance(target_node_cache));
|
||||
if (_print_execution_error(!node_target || !node_target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
@ -172,13 +172,13 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
|
||||
// Apply magnet positions:
|
||||
if (stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx) >= 0) {
|
||||
int parent_bone_idx = stack->skeleton->get_bone_parent(fabrik_data_chain[i].bone_idx);
|
||||
Transform3D conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx));
|
||||
Transform conversion_transform = (stack->skeleton->get_bone_global_pose(parent_bone_idx));
|
||||
fabrik_transforms[i].origin += conversion_transform.basis.xform_inv(fabrik_data_chain[i].magnet_position);
|
||||
} else {
|
||||
fabrik_transforms[i].origin += fabrik_data_chain[i].magnet_position;
|
||||
}
|
||||
}
|
||||
Transform3D origin_global_pose_trans = stack->skeleton->get_bone_global_pose_no_override(fabrik_data_chain[0].bone_idx);
|
||||
Transform origin_global_pose_trans = stack->skeleton->get_bone_global_pose_no_override(fabrik_data_chain[0].bone_idx);
|
||||
|
||||
target_global_pose = stack->skeleton->world_transform_to_global_pose(node_target->get_global_transform());
|
||||
origin_global_pose = origin_global_pose_trans;
|
||||
@ -207,11 +207,11 @@ void SkeletonModification3DFABRIK::_execute(real_t p_delta) {
|
||||
|
||||
void SkeletonModification3DFABRIK::chain_backwards() {
|
||||
int final_bone_idx = fabrik_data_chain[final_joint_idx].bone_idx;
|
||||
Transform3D final_joint_trans = fabrik_transforms[final_joint_idx];
|
||||
Transform final_joint_trans = fabrik_transforms[final_joint_idx];
|
||||
|
||||
// Get the direction the final bone is facing in.
|
||||
stack->skeleton->update_bone_rest_forward_vector(final_bone_idx);
|
||||
Transform3D final_bone_direction_trans = final_joint_trans.looking_at(target_global_pose.origin, Vector3(0, 1, 0));
|
||||
Transform final_bone_direction_trans = final_joint_trans.looking_at(target_global_pose.origin, Vector3(0, 1, 0));
|
||||
final_bone_direction_trans.basis = stack->skeleton->global_pose_z_forward_to_bone_forward(final_bone_idx, final_bone_direction_trans.basis);
|
||||
Vector3 direction = final_bone_direction_trans.basis.xform(stack->skeleton->get_bone_axis_forward_vector(final_bone_idx)).normalized();
|
||||
|
||||
@ -227,12 +227,12 @@ void SkeletonModification3DFABRIK::chain_backwards() {
|
||||
// for all other joints, move them towards the target
|
||||
int i = final_joint_idx;
|
||||
while (i >= 1) {
|
||||
Transform3D next_bone_trans = fabrik_transforms[i];
|
||||
Transform next_bone_trans = fabrik_transforms[i];
|
||||
i -= 1;
|
||||
Transform3D current_trans = fabrik_transforms[i];
|
||||
Transform current_trans = fabrik_transforms[i];
|
||||
|
||||
real_t length = fabrik_data_chain[i].length / (current_trans.origin.distance_to(next_bone_trans.origin));
|
||||
current_trans.origin = next_bone_trans.origin.lerp(current_trans.origin, length);
|
||||
current_trans.origin = next_bone_trans.origin.linear_interpolate(current_trans.origin, length);
|
||||
|
||||
// Save the result
|
||||
fabrik_transforms[i] = current_trans;
|
||||
@ -241,17 +241,17 @@ void SkeletonModification3DFABRIK::chain_backwards() {
|
||||
|
||||
void SkeletonModification3DFABRIK::chain_forwards() {
|
||||
// Set root at the initial position.
|
||||
Transform3D root_transform = fabrik_transforms[0];
|
||||
Transform root_transform = fabrik_transforms[0];
|
||||
|
||||
root_transform.origin = origin_global_pose.origin;
|
||||
fabrik_transforms[0] = origin_global_pose;
|
||||
|
||||
for (uint32_t i = 0; i < fabrik_data_chain.size() - 1; i++) {
|
||||
Transform3D current_trans = fabrik_transforms[i];
|
||||
Transform3D next_bone_trans = fabrik_transforms[i + 1];
|
||||
Transform current_trans = fabrik_transforms[i];
|
||||
Transform next_bone_trans = fabrik_transforms[i + 1];
|
||||
|
||||
real_t length = fabrik_data_chain[i].length / (next_bone_trans.origin.distance_to(current_trans.origin));
|
||||
next_bone_trans.origin = current_trans.origin.lerp(next_bone_trans.origin, length);
|
||||
next_bone_trans.origin = current_trans.origin.linear_interpolate(next_bone_trans.origin, length);
|
||||
|
||||
// Save the result
|
||||
fabrik_transforms[i + 1] = next_bone_trans;
|
||||
@ -261,7 +261,7 @@ void SkeletonModification3DFABRIK::chain_forwards() {
|
||||
void SkeletonModification3DFABRIK::chain_apply() {
|
||||
for (uint32_t i = 0; i < fabrik_data_chain.size(); i++) {
|
||||
int current_bone_idx = fabrik_data_chain[i].bone_idx;
|
||||
Transform3D current_trans = fabrik_transforms[i];
|
||||
Transform current_trans = fabrik_transforms[i];
|
||||
|
||||
// If this is the last bone in the chain...
|
||||
if (i == fabrik_data_chain.size() - 1) {
|
||||
@ -276,7 +276,7 @@ void SkeletonModification3DFABRIK::chain_apply() {
|
||||
current_trans.basis = target_global_pose.basis.orthonormalized().scaled(current_trans.basis.get_scale());
|
||||
}
|
||||
} else { // every other bone in the chain...
|
||||
Transform3D next_trans = fabrik_transforms[i + 1];
|
||||
Transform next_trans = fabrik_transforms[i + 1];
|
||||
|
||||
// Get the forward direction that the basis is facing in right now.
|
||||
stack->skeleton->update_bone_rest_forward_vector(current_bone_idx);
|
||||
@ -292,8 +292,8 @@ void SkeletonModification3DFABRIK::chain_apply() {
|
||||
stack->skeleton->force_update_all_bone_transforms();
|
||||
}
|
||||
|
||||
void SkeletonModification3DFABRIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DFABRIK::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
if (stack != nullptr) {
|
||||
is_setup = true;
|
||||
execution_error_found = false;
|
||||
@ -369,7 +369,7 @@ void SkeletonModification3DFABRIK::set_fabrik_data_chain_length(int p_length) {
|
||||
fabrik_data_chain.resize(p_length);
|
||||
fabrik_transforms.resize(p_length);
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
real_t SkeletonModification3DFABRIK::get_chain_tolerance() {
|
||||
@ -407,7 +407,7 @@ void SkeletonModification3DFABRIK::set_fabrik_joint_bone_name(int p_joint_idx, S
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DFABRIK::get_fabrik_joint_bone_index(int p_joint_idx) const {
|
||||
@ -428,7 +428,7 @@ void SkeletonModification3DFABRIK::set_fabrik_joint_bone_index(int p_joint_idx,
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
real_t SkeletonModification3DFABRIK::get_fabrik_joint_length(int p_joint_idx) const {
|
||||
@ -480,7 +480,7 @@ void SkeletonModification3DFABRIK::set_fabrik_joint_auto_calculate_length(int p_
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
fabrik_data_chain[p_joint_idx].auto_calculate_length = p_auto_calculate;
|
||||
fabrik_joint_auto_calculate_length(p_joint_idx);
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
void SkeletonModification3DFABRIK::fabrik_joint_auto_calculate_length(int p_joint_idx) {
|
||||
@ -501,11 +501,11 @@ void SkeletonModification3DFABRIK::fabrik_joint_auto_calculate_length(int p_join
|
||||
|
||||
update_joint_tip_cache(p_joint_idx);
|
||||
|
||||
Node3D *tip_node = Object::cast_to<Node3D>(ObjectDB::get_instance(fabrik_data_chain[p_joint_idx].tip_node_cache));
|
||||
ERR_FAIL_COND_MSG(!tip_node, "Tip node for joint " + itos(p_joint_idx) + "is not a Node3D-based node. Cannot calculate length...");
|
||||
Spatial *tip_node = Object::cast_to<Spatial>(ObjectDB::get_instance(fabrik_data_chain[p_joint_idx].tip_node_cache));
|
||||
ERR_FAIL_COND_MSG(!tip_node, "Tip node for joint " + itos(p_joint_idx) + "is not a Spatial-based node. Cannot calculate length...");
|
||||
ERR_FAIL_COND_MSG(!tip_node->is_inside_tree(), "Tip node for joint " + itos(p_joint_idx) + "is not in the scene tree. Cannot calculate length...");
|
||||
|
||||
Transform3D node_trans = tip_node->get_global_transform();
|
||||
Transform node_trans = tip_node->get_global_transform();
|
||||
node_trans = stack->skeleton->world_transform_to_global_pose(node_trans);
|
||||
//node_trans = stack->skeleton->global_pose_to_local_pose(fabrik_data_chain[p_joint_idx].bone_idx, node_trans);
|
||||
//fabrik_data_chain[p_joint_idx].length = node_trans.origin.length();
|
||||
@ -519,18 +519,18 @@ void SkeletonModification3DFABRIK::fabrik_joint_auto_calculate_length(int p_join
|
||||
return;
|
||||
}
|
||||
|
||||
Transform3D bone_trans = stack->skeleton->get_bone_global_pose(fabrik_data_chain[p_joint_idx].bone_idx);
|
||||
Transform bone_trans = stack->skeleton->get_bone_global_pose(fabrik_data_chain[p_joint_idx].bone_idx);
|
||||
|
||||
real_t final_length = 0;
|
||||
for (int i = 0; i < bone_children.size(); i++) {
|
||||
Transform3D child_transform = stack->skeleton->get_bone_global_pose(bone_children[i]);
|
||||
Transform child_transform = stack->skeleton->get_bone_global_pose(bone_children[i]);
|
||||
final_length += bone_trans.origin.distance_to(child_transform.origin);
|
||||
//final_length += stack->skeleton->global_pose_to_local_pose(fabrik_data_chain[p_joint_idx].bone_idx, child_transform).origin.length();
|
||||
}
|
||||
fabrik_data_chain[p_joint_idx].length = final_length / bone_children.size();
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DFABRIK::get_fabrik_joint_use_tip_node(int p_joint_idx) const {
|
||||
@ -543,7 +543,7 @@ void SkeletonModification3DFABRIK::set_fabrik_joint_use_tip_node(int p_joint_idx
|
||||
const int bone_chain_size = fabrik_data_chain.size();
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
fabrik_data_chain[p_joint_idx].use_tip_node = p_use_tip_node;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
NodePath SkeletonModification3DFABRIK::get_fabrik_joint_tip_node(int p_joint_idx) const {
|
||||
@ -612,9 +612,9 @@ void SkeletonModification3DFABRIK::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_fabrik_joint_use_target_basis", "joint_idx"), &SkeletonModification3DFABRIK::get_fabrik_joint_use_target_basis);
|
||||
ClassDB::bind_method(D_METHOD("set_fabrik_joint_use_target_basis", "joint_idx", "use_target_basis"), &SkeletonModification3DFABRIK::set_fabrik_joint_use_target_basis);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "fabrik_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_fabrik_data_chain_length", "get_fabrik_data_chain_length");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "chain_tolerance", PROPERTY_HINT_RANGE, "0,100,0.001"), "set_chain_tolerance", "get_chain_tolerance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "chain_tolerance", PROPERTY_HINT_RANGE, "0,100,0.001"), "set_chain_tolerance", "get_chain_tolerance");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "chain_max_iterations", PROPERTY_HINT_RANGE, "1,50,1"), "set_chain_max_iterations", "get_chain_max_iterations");
|
||||
}
|
||||
|
||||
@ -622,6 +622,14 @@ SkeletonModification3DFABRIK::SkeletonModification3DFABRIK() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
enabled = true;
|
||||
|
||||
target_node_cache = 0;
|
||||
|
||||
chain_tolerance = 0.01;
|
||||
chain_max_iterations = 10;
|
||||
chain_iterations = 0;
|
||||
|
||||
final_joint_idx = 0;
|
||||
}
|
||||
|
||||
SkeletonModification3DFABRIK::~SkeletonModification3DFABRIK() {
|
@ -1,3 +1,6 @@
|
||||
#ifndef SKELETON_MODIFICATION_3D_FABRIK_H
|
||||
#define SKELETON_MODIFICATION_3D_FABRIK_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_fabrik.h */
|
||||
/*************************************************************************/
|
||||
@ -28,48 +31,56 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "core/containers/local_vector.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_FABRIK_H
|
||||
#define SKELETON_MODIFICATION_3D_FABRIK_H
|
||||
|
||||
class SkeletonModification3DFABRIK : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DFABRIK, SkeletonModification3D);
|
||||
|
||||
private:
|
||||
struct FABRIK_Joint_Data {
|
||||
String bone_name = "";
|
||||
int bone_idx = -1;
|
||||
real_t length = -1;
|
||||
Vector3 magnet_position = Vector3(0, 0, 0);
|
||||
String bone_name;
|
||||
int bone_idx;
|
||||
real_t length;
|
||||
Vector3 magnet_position;
|
||||
|
||||
bool auto_calculate_length = true;
|
||||
bool use_tip_node = false;
|
||||
NodePath tip_node = NodePath();
|
||||
bool auto_calculate_length;
|
||||
bool use_tip_node;
|
||||
NodePath tip_node;
|
||||
ObjectID tip_node_cache;
|
||||
|
||||
bool use_target_basis = false;
|
||||
real_t roll = 0;
|
||||
bool use_target_basis;
|
||||
real_t roll;
|
||||
|
||||
FABRIK_Joint_Data() {
|
||||
bone_idx = -1;
|
||||
length = -1;
|
||||
|
||||
auto_calculate_length = true;
|
||||
use_tip_node = false;
|
||||
tip_node_cache = 0;
|
||||
|
||||
use_target_basis = false;
|
||||
roll = 0;
|
||||
}
|
||||
};
|
||||
|
||||
LocalVector<FABRIK_Joint_Data> fabrik_data_chain;
|
||||
LocalVector<Transform3D> fabrik_transforms;
|
||||
LocalVector<Transform> fabrik_transforms;
|
||||
|
||||
NodePath target_node;
|
||||
ObjectID target_node_cache;
|
||||
|
||||
real_t chain_tolerance = 0.01;
|
||||
int chain_max_iterations = 10;
|
||||
int chain_iterations = 0;
|
||||
real_t chain_tolerance;
|
||||
int chain_max_iterations;
|
||||
int chain_iterations;
|
||||
|
||||
void update_target_cache();
|
||||
void update_joint_tip_cache(int p_joint_idx);
|
||||
|
||||
int final_joint_idx = 0;
|
||||
Transform3D target_global_pose = Transform3D();
|
||||
Transform3D origin_global_pose = Transform3D();
|
||||
int final_joint_idx;
|
||||
Transform target_global_pose;
|
||||
Transform origin_global_pose;
|
||||
|
||||
void chain_backwards();
|
||||
void chain_forwards();
|
||||
@ -82,8 +93,8 @@ protected:
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_target_node(const NodePath &p_target_node);
|
||||
NodePath get_target_node() const;
|
@ -29,8 +29,10 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_jiggle.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
#include "servers/physics_server.h"
|
||||
#include "scene/resources/world.h"
|
||||
|
||||
bool SkeletonModification3DJiggle::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
@ -123,13 +125,13 @@ void SkeletonModification3DJiggle::_get_property_list(List<PropertyInfo> *p_list
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING_NAME, base_string + "bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "roll", PROPERTY_HINT_RANGE, "-360,360,0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "override_defaults", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
|
||||
if (jiggle_data_chain[i].override_defaults) {
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "stiffness", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "mass", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "stiffness", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "mass", PROPERTY_HINT_RANGE, "0, 1000, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, base_string + "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (jiggle_data_chain[i].use_gravity) {
|
||||
p_list->push_back(PropertyInfo(Variant::VECTOR3, base_string + "gravity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
@ -144,12 +146,12 @@ void SkeletonModification3DJiggle::_execute(real_t p_delta) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
if (target_node_cache.is_null()) {
|
||||
if (target_node_cache == 0) {
|
||||
_print_execution_error(true, "Target cache is out of date. Attempting to update...");
|
||||
update_cache();
|
||||
return;
|
||||
}
|
||||
Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
|
||||
Spatial *target = Object::cast_to<Spatial>(ObjectDB::get_instance(target_node_cache));
|
||||
_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!");
|
||||
|
||||
for (uint32_t i = 0; i < jiggle_data_chain.size(); i++) {
|
||||
@ -159,7 +161,7 @@ void SkeletonModification3DJiggle::_execute(real_t p_delta) {
|
||||
execution_error_found = false;
|
||||
}
|
||||
|
||||
void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D *p_target, real_t p_delta) {
|
||||
void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Spatial *p_target, real_t p_delta) {
|
||||
// Adopted from: https://wiki.unity3d.com/index.php/JiggleBone
|
||||
// With modifications by TwistedTwigleg.
|
||||
|
||||
@ -172,12 +174,12 @@ void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D
|
||||
return;
|
||||
}
|
||||
|
||||
Transform3D bone_local_pos = stack->skeleton->get_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx);
|
||||
if (bone_local_pos == Transform3D()) {
|
||||
Transform bone_local_pos = stack->skeleton->get_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx);
|
||||
if (bone_local_pos == Transform()) {
|
||||
bone_local_pos = stack->skeleton->get_bone_pose(jiggle_data_chain[p_joint_idx].bone_idx);
|
||||
}
|
||||
|
||||
Transform3D new_bone_trans = stack->skeleton->local_pose_to_global_pose(jiggle_data_chain[p_joint_idx].bone_idx, bone_local_pos);
|
||||
Transform new_bone_trans = stack->skeleton->local_pose_to_global_pose(jiggle_data_chain[p_joint_idx].bone_idx, bone_local_pos);
|
||||
Vector3 target_position = stack->skeleton->world_transform_to_global_pose(p_target->get_global_transform()).origin;
|
||||
|
||||
jiggle_data_chain[p_joint_idx].force = (target_position - jiggle_data_chain[p_joint_idx].dynamic_position) * jiggle_data_chain[p_joint_idx].stiffness * p_delta;
|
||||
@ -197,21 +199,16 @@ void SkeletonModification3DJiggle::_execute_jiggle_joint(int p_joint_idx, Node3D
|
||||
// Collision detection/response
|
||||
if (use_colliders) {
|
||||
if (execution_mode == SkeletonModificationStack3D::EXECUTION_MODE::execution_mode_physics_process) {
|
||||
Ref<World3D> world_3d = stack->skeleton->get_world_3d();
|
||||
Ref<World> world_3d = stack->skeleton->get_world();
|
||||
ERR_FAIL_COND(world_3d.is_null());
|
||||
PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world_3d->get_space());
|
||||
PhysicsDirectSpaceState3D::RayResult ray_result;
|
||||
PhysicsDirectSpaceState *space_state = PhysicsServer::get_singleton()->space_get_direct_state(world_3d->get_space());
|
||||
PhysicsDirectSpaceState::RayResult ray_result;
|
||||
|
||||
// Convert to world transforms, which is what the physics server needs
|
||||
Transform3D new_bone_trans_world = stack->skeleton->global_pose_to_world_transform(new_bone_trans);
|
||||
Transform3D dynamic_position_world = stack->skeleton->global_pose_to_world_transform(Transform3D(Basis(), jiggle_data_chain[p_joint_idx].dynamic_position));
|
||||
Transform new_bone_trans_world = stack->skeleton->global_pose_to_world_transform(new_bone_trans);
|
||||
Transform dynamic_position_world = stack->skeleton->global_pose_to_world_transform(Transform(Basis(), jiggle_data_chain[p_joint_idx].dynamic_position));
|
||||
|
||||
PhysicsDirectSpaceState3D::RayParameters ray_params;
|
||||
ray_params.from = new_bone_trans_world.origin;
|
||||
ray_params.to = dynamic_position_world.get_origin();
|
||||
ray_params.collision_mask = collision_mask;
|
||||
|
||||
bool ray_hit = space_state->intersect_ray(ray_params, ray_result);
|
||||
bool ray_hit = space_state->intersect_ray(new_bone_trans_world.origin, dynamic_position_world.get_origin(), ray_result, Set<RID>(), collision_mask);
|
||||
|
||||
if (ray_hit) {
|
||||
jiggle_data_chain[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position;
|
||||
@ -253,8 +250,8 @@ void SkeletonModification3DJiggle::_update_jiggle_joint_data() {
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModification3DJiggle::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DJiggle::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
|
||||
if (stack) {
|
||||
is_setup = true;
|
||||
@ -356,7 +353,7 @@ Vector3 SkeletonModification3DJiggle::get_gravity() const {
|
||||
|
||||
void SkeletonModification3DJiggle::set_use_colliders(bool p_use_collider) {
|
||||
use_colliders = p_use_collider;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DJiggle::get_use_colliders() const {
|
||||
@ -380,7 +377,7 @@ void SkeletonModification3DJiggle::set_jiggle_data_chain_length(int p_length) {
|
||||
ERR_FAIL_COND(p_length < 0);
|
||||
jiggle_data_chain.resize(p_length);
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
void SkeletonModification3DJiggle::set_jiggle_joint_bone_name(int p_joint_idx, String p_name) {
|
||||
@ -392,7 +389,7 @@ void SkeletonModification3DJiggle::set_jiggle_joint_bone_name(int p_joint_idx, S
|
||||
jiggle_data_chain[p_joint_idx].bone_idx = stack->skeleton->find_bone(p_name);
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
String SkeletonModification3DJiggle::get_jiggle_joint_bone_name(int p_joint_idx) const {
|
||||
@ -419,7 +416,7 @@ void SkeletonModification3DJiggle::set_jiggle_joint_bone_index(int p_joint_idx,
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
void SkeletonModification3DJiggle::set_jiggle_joint_override(int p_joint_idx, bool p_override) {
|
||||
@ -427,7 +424,7 @@ void SkeletonModification3DJiggle::set_jiggle_joint_override(int p_joint_idx, bo
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
jiggle_data_chain[p_joint_idx].override_defaults = p_override;
|
||||
_update_jiggle_joint_data();
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DJiggle::get_jiggle_joint_override(int p_joint_idx) const {
|
||||
@ -479,7 +476,7 @@ void SkeletonModification3DJiggle::set_jiggle_joint_use_gravity(int p_joint_idx,
|
||||
const int bone_chain_size = jiggle_data_chain.size();
|
||||
ERR_FAIL_INDEX(p_joint_idx, bone_chain_size);
|
||||
jiggle_data_chain[p_joint_idx].use_gravity = p_use_gravity;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DJiggle::get_jiggle_joint_use_gravity(int p_joint_idx) const {
|
||||
@ -555,12 +552,12 @@ void SkeletonModification3DJiggle::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_jiggle_joint_roll", "joint_idx", "roll"), &SkeletonModification3DJiggle::set_jiggle_joint_roll);
|
||||
ClassDB::bind_method(D_METHOD("get_jiggle_joint_roll", "joint_idx"), &SkeletonModification3DJiggle::get_jiggle_joint_roll);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "jiggle_data_chain_length", PROPERTY_HINT_RANGE, "0,100,1"), "set_jiggle_data_chain_length", "get_jiggle_data_chain_length");
|
||||
ADD_GROUP("Default Joint Settings", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness"), "set_stiffness", "get_stiffness");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass"), "set_mass", "get_mass");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01"), "set_damping", "get_damping");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "stiffness"), "set_stiffness", "get_stiffness");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass"), "set_mass", "get_mass");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0, 1, 0.01"), "set_damping", "get_damping");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_gravity"), "set_use_gravity", "get_use_gravity");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity");
|
||||
ADD_GROUP("", "");
|
||||
@ -569,13 +566,16 @@ void SkeletonModification3DJiggle::_bind_methods() {
|
||||
SkeletonModification3DJiggle::SkeletonModification3DJiggle() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
jiggle_data_chain = Vector<Jiggle_Joint_Data>();
|
||||
target_node_cache = 0;
|
||||
stiffness = 3;
|
||||
mass = 0.75;
|
||||
damping = 0.75;
|
||||
use_gravity = false;
|
||||
gravity = Vector3(0, -6.0, 0);
|
||||
enabled = true;
|
||||
|
||||
use_colliders = false;
|
||||
collision_mask = 1;
|
||||
}
|
||||
|
||||
SkeletonModification3DJiggle::~SkeletonModification3DJiggle() {
|
@ -1,3 +1,6 @@
|
||||
#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H
|
||||
#define SKELETON_MODIFICATION_3D_JIGGLE_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_jiggle.h */
|
||||
/*************************************************************************/
|
||||
@ -28,54 +31,61 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "core/containers/local_vector.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_JIGGLE_H
|
||||
#define SKELETON_MODIFICATION_3D_JIGGLE_H
|
||||
|
||||
class SkeletonModification3DJiggle : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DJiggle, SkeletonModification3D);
|
||||
|
||||
private:
|
||||
struct Jiggle_Joint_Data {
|
||||
String bone_name = "";
|
||||
int bone_idx = -1;
|
||||
String bone_name;
|
||||
int bone_idx;
|
||||
|
||||
bool override_defaults = false;
|
||||
real_t stiffness = 3;
|
||||
real_t mass = 0.75;
|
||||
real_t damping = 0.75;
|
||||
bool use_gravity = false;
|
||||
Vector3 gravity = Vector3(0, -6.0, 0);
|
||||
real_t roll = 0;
|
||||
bool override_defaults;
|
||||
real_t stiffness;
|
||||
real_t mass;
|
||||
real_t damping;
|
||||
bool use_gravity;
|
||||
Vector3 gravity;
|
||||
real_t roll;
|
||||
|
||||
Vector3 cached_rotation = Vector3(0, 0, 0);
|
||||
Vector3 force = Vector3(0, 0, 0);
|
||||
Vector3 acceleration = Vector3(0, 0, 0);
|
||||
Vector3 velocity = Vector3(0, 0, 0);
|
||||
Vector3 last_position = Vector3(0, 0, 0);
|
||||
Vector3 dynamic_position = Vector3(0, 0, 0);
|
||||
Vector3 cached_rotation;
|
||||
Vector3 force;
|
||||
Vector3 acceleration;
|
||||
Vector3 velocity;
|
||||
Vector3 last_position;
|
||||
Vector3 dynamic_position;
|
||||
|
||||
Vector3 last_noncollision_position = Vector3(0, 0, 0);
|
||||
Vector3 last_noncollision_position;
|
||||
|
||||
Jiggle_Joint_Data() {
|
||||
bone_idx = -1;
|
||||
override_defaults = false;
|
||||
stiffness = 3;
|
||||
mass = 0.75;
|
||||
damping = 0.75;
|
||||
use_gravity = false;
|
||||
gravity = Vector3(0, -6.0, 0);
|
||||
roll = 0;
|
||||
}
|
||||
};
|
||||
|
||||
NodePath target_node;
|
||||
ObjectID target_node_cache;
|
||||
LocalVector<Jiggle_Joint_Data> jiggle_data_chain;
|
||||
|
||||
real_t stiffness = 3;
|
||||
real_t mass = 0.75;
|
||||
real_t damping = 0.75;
|
||||
bool use_gravity = false;
|
||||
Vector3 gravity = Vector3(0, -6.0, 0);
|
||||
real_t stiffness;
|
||||
real_t mass;
|
||||
real_t damping;
|
||||
bool use_gravity;
|
||||
Vector3 gravity;
|
||||
|
||||
bool use_colliders = false;
|
||||
uint32_t collision_mask = 1;
|
||||
bool use_colliders;
|
||||
uint32_t collision_mask;
|
||||
|
||||
void update_cache();
|
||||
void _execute_jiggle_joint(int p_joint_idx, Node3D *p_target, real_t p_delta);
|
||||
void _execute_jiggle_joint(int p_joint_idx, Spatial *p_target, real_t p_delta);
|
||||
void _update_jiggle_joint_data();
|
||||
|
||||
protected:
|
||||
@ -85,8 +95,8 @@ protected:
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_target_node(const NodePath &p_target_node);
|
||||
NodePath get_target_node() const;
|
@ -29,8 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_lookat.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
bool SkeletonModification3DLookAt::_set(const StringName &p_path, const Variant &p_value) {
|
||||
if (p_path == "lock_rotation_to_plane") {
|
||||
@ -79,7 +79,7 @@ void SkeletonModification3DLookAt::_execute(real_t p_delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_node_cache.is_null()) {
|
||||
if (target_node_cache == 0) {
|
||||
_print_execution_error(true, "Target cache is out of date. Attempting to update...");
|
||||
update_cache();
|
||||
return;
|
||||
@ -89,15 +89,15 @@ void SkeletonModification3DLookAt::_execute(real_t p_delta) {
|
||||
bone_idx = stack->skeleton->find_bone(bone_name);
|
||||
}
|
||||
|
||||
Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
|
||||
Spatial *target = Object::cast_to<Spatial>(ObjectDB::get_instance(target_node_cache));
|
||||
if (_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
if (_print_execution_error(bone_idx <= -1, "Bone index is invalid. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
Transform3D new_bone_trans = stack->skeleton->get_bone_local_pose_override(bone_idx);
|
||||
if (new_bone_trans == Transform3D()) {
|
||||
Transform new_bone_trans = stack->skeleton->get_bone_local_pose_override(bone_idx);
|
||||
if (new_bone_trans == Transform()) {
|
||||
new_bone_trans = stack->skeleton->get_bone_pose(bone_idx);
|
||||
}
|
||||
Vector3 target_pos = stack->skeleton->global_pose_to_local_pose(bone_idx, stack->skeleton->world_transform_to_global_pose(target->get_global_transform())).origin;
|
||||
@ -131,8 +131,8 @@ void SkeletonModification3DLookAt::_execute(real_t p_delta) {
|
||||
execution_error_found = false;
|
||||
}
|
||||
|
||||
void SkeletonModification3DLookAt::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DLookAt::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
|
||||
if (stack != nullptr) {
|
||||
is_setup = true;
|
||||
@ -149,7 +149,7 @@ void SkeletonModification3DLookAt::set_bone_name(String p_name) {
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
String SkeletonModification3DLookAt::get_bone_name() const {
|
||||
@ -170,7 +170,7 @@ void SkeletonModification3DLookAt::set_bone_index(int p_bone_idx) {
|
||||
}
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
void SkeletonModification3DLookAt::update_cache() {
|
||||
@ -219,7 +219,7 @@ bool SkeletonModification3DLookAt::get_lock_rotation_to_plane() const {
|
||||
|
||||
void SkeletonModification3DLookAt::set_lock_rotation_to_plane(bool p_lock_rotation) {
|
||||
lock_rotation_to_plane = p_lock_rotation;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DLookAt::get_lock_rotation_plane() const {
|
||||
@ -250,17 +250,19 @@ void SkeletonModification3DLookAt::_bind_methods() {
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "bone_name"), "set_bone_name", "get_bone_name");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "bone_index"), "set_bone_index", "get_bone_index");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_target_node", "get_target_node");
|
||||
}
|
||||
|
||||
SkeletonModification3DLookAt::SkeletonModification3DLookAt() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
bone_name = "";
|
||||
bone_idx = -2;
|
||||
additional_rotation = Vector3();
|
||||
|
||||
bone_idx = -1;
|
||||
target_node_cache = 0;
|
||||
additional_rotation = Vector3(1, 0, 0);
|
||||
lock_rotation_to_plane = false;
|
||||
enabled = true;
|
||||
lock_rotation_plane = ROTATION_PLANE_X;
|
||||
}
|
||||
|
||||
SkeletonModification3DLookAt::~SkeletonModification3DLookAt() {
|
@ -1,3 +1,6 @@
|
||||
#ifndef SKELETON_MODIFICATION_3D_LOOKAT_H
|
||||
#define SKELETON_MODIFICATION_3D_LOOKAT_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_lookat.h */
|
||||
/*************************************************************************/
|
||||
@ -28,24 +31,20 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_LOOKAT_H
|
||||
#define SKELETON_MODIFICATION_3D_LOOKAT_H
|
||||
|
||||
class SkeletonModification3DLookAt : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DLookAt, SkeletonModification3D);
|
||||
|
||||
private:
|
||||
String bone_name = "";
|
||||
int bone_idx = -1;
|
||||
String bone_name;
|
||||
int bone_idx;
|
||||
NodePath target_node;
|
||||
ObjectID target_node_cache;
|
||||
|
||||
Vector3 additional_rotation = Vector3(1, 0, 0);
|
||||
bool lock_rotation_to_plane = false;
|
||||
int lock_rotation_plane = ROTATION_PLANE_X;
|
||||
Vector3 additional_rotation;
|
||||
bool lock_rotation_to_plane;
|
||||
int lock_rotation_plane;
|
||||
|
||||
void update_cache();
|
||||
|
||||
@ -62,8 +61,8 @@ public:
|
||||
ROTATION_PLANE_Z
|
||||
};
|
||||
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_bone_name(String p_name);
|
||||
String get_bone_name() const;
|
@ -29,8 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_stackholder.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
bool SkeletonModification3DStackHolder::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
@ -55,16 +55,15 @@ void SkeletonModification3DStackHolder::_get_property_list(List<PropertyInfo> *p
|
||||
}
|
||||
|
||||
void SkeletonModification3DStackHolder::_execute(real_t p_delta) {
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
|
||||
"Modification is not setup and therefore cannot execute!");
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr, "Modification is not setup and therefore cannot execute!");
|
||||
|
||||
if (held_modification_stack.is_valid()) {
|
||||
held_modification_stack->execute(p_delta, execution_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModification3DStackHolder::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DStackHolder::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
|
||||
if (stack != nullptr) {
|
||||
is_setup = true;
|
@ -1,3 +1,6 @@
|
||||
#ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H
|
||||
#define SKELETON_MODIFICATION_3D_STACKHOLDER_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_stackholder.h */
|
||||
/*************************************************************************/
|
||||
@ -28,12 +31,8 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_STACKHOLDER_H
|
||||
#define SKELETON_MODIFICATION_3D_STACKHOLDER_H
|
||||
|
||||
class SkeletonModification3DStackHolder : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DStackHolder, SkeletonModification3D);
|
||||
|
||||
@ -46,8 +45,8 @@ protected:
|
||||
public:
|
||||
Ref<SkeletonModificationStack3D> held_modification_stack;
|
||||
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_held_modification_stack(Ref<SkeletonModificationStack3D> p_held_stack);
|
||||
Ref<SkeletonModificationStack3D> get_held_modification_stack() const;
|
@ -29,8 +29,8 @@
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/resources/skeleton_modification_3d_twoboneik.h"
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
#include "scene/3d/skeleton.h"
|
||||
#include "scene/resources/skeleton_modification_stack_3d.h"
|
||||
|
||||
bool SkeletonModification3DTwoBoneIK::_set(const StringName &p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
@ -103,32 +103,31 @@ bool SkeletonModification3DTwoBoneIK::_get(const StringName &p_path, Variant &r_
|
||||
void SkeletonModification3DTwoBoneIK::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, "use_tip_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (use_tip_node) {
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tip_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, "auto_calculate_joint_length", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (!auto_calculate_joint_length) {
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, "joint_one_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, "joint_two_length", PROPERTY_HINT_RANGE, "-1, 10000, 0.001", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::BOOL, "use_pole_node", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
if (use_pole_node) {
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "pole_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::NODE_PATH, "pole_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_one/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::INT, "joint_one/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_one/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, "joint_one/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
|
||||
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "joint_two/bone_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::INT, "joint_two/bone_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::FLOAT, "joint_two/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
p_list->push_back(PropertyInfo(Variant::REAL, "joint_two/roll", PROPERTY_HINT_RANGE, "-360, 360, 0.01", PROPERTY_USAGE_DEFAULT));
|
||||
}
|
||||
|
||||
void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr,
|
||||
"Modification is not setup and therefore cannot execute!");
|
||||
ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr, "Modification is not setup and therefore cannot execute!");
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
@ -139,7 +138,7 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target_node_cache.is_null()) {
|
||||
if (target_node_cache == 0) {
|
||||
_print_execution_error(true, "Target cache is out of date. Attempting to update...");
|
||||
update_cache_target();
|
||||
return;
|
||||
@ -154,36 +153,39 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
// http://theorangeduck.com/page/simple-two-joint
|
||||
// https://www.alanzucconi.com/2018/05/02/ik-2d-2/
|
||||
// With modifications by TwistedTwigleg
|
||||
Node3D *target = Object::cast_to<Node3D>(ObjectDB::get_instance(target_node_cache));
|
||||
Spatial *target = Object::cast_to<Spatial>(ObjectDB::get_instance(target_node_cache));
|
||||
if (_print_execution_error(!target || !target->is_inside_tree(), "Target node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
Transform3D target_trans = stack->skeleton->world_transform_to_global_pose(target->get_global_transform());
|
||||
|
||||
Transform3D bone_one_trans;
|
||||
Transform3D bone_two_trans;
|
||||
Transform target_trans = stack->skeleton->world_transform_to_global_pose(target->get_global_transform());
|
||||
|
||||
Transform bone_one_trans;
|
||||
Transform bone_two_trans;
|
||||
|
||||
// Make the first joint look at the pole, and the second look at the target. That way, the
|
||||
// TwoBoneIK solver has to really only handle extension/contraction, which should make it align with the pole.
|
||||
if (use_pole_node) {
|
||||
if (pole_node_cache.is_null()) {
|
||||
if (pole_node_cache == 0) {
|
||||
_print_execution_error(true, "Pole cache is out of date. Attempting to update...");
|
||||
update_cache_pole();
|
||||
return;
|
||||
}
|
||||
|
||||
Node3D *pole = Object::cast_to<Node3D>(ObjectDB::get_instance(pole_node_cache));
|
||||
Spatial *pole = Object::cast_to<Spatial>(ObjectDB::get_instance(pole_node_cache));
|
||||
if (_print_execution_error(!pole || !pole->is_inside_tree(), "Pole node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
Transform3D pole_trans = stack->skeleton->world_transform_to_global_pose(pole->get_global_transform());
|
||||
|
||||
Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
|
||||
if (bone_one_local_pos == Transform3D()) {
|
||||
Transform pole_trans = stack->skeleton->world_transform_to_global_pose(pole->get_global_transform());
|
||||
|
||||
Transform bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
|
||||
if (bone_one_local_pos == Transform()) {
|
||||
bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
|
||||
}
|
||||
Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
|
||||
if (bone_two_local_pos == Transform3D()) {
|
||||
|
||||
Transform bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
|
||||
if (bone_two_local_pos == Transform()) {
|
||||
bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
|
||||
}
|
||||
|
||||
@ -203,12 +205,12 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
stack->skeleton->set_bone_local_pose_override(joint_two_bone_idx, stack->skeleton->global_pose_to_local_pose(joint_two_bone_idx, bone_two_trans), stack->strength, true);
|
||||
stack->skeleton->force_update_bone_children_transforms(joint_two_bone_idx);
|
||||
} else {
|
||||
Transform3D bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
|
||||
if (bone_one_local_pos == Transform3D()) {
|
||||
Transform bone_one_local_pos = stack->skeleton->get_bone_local_pose_override(joint_one_bone_idx);
|
||||
if (bone_one_local_pos == Transform()) {
|
||||
bone_one_local_pos = stack->skeleton->get_bone_pose(joint_one_bone_idx);
|
||||
}
|
||||
Transform3D bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
|
||||
if (bone_two_local_pos == Transform3D()) {
|
||||
Transform bone_two_local_pos = stack->skeleton->get_bone_local_pose_override(joint_two_bone_idx);
|
||||
if (bone_two_local_pos == Transform()) {
|
||||
bone_two_local_pos = stack->skeleton->get_bone_pose(joint_two_bone_idx);
|
||||
}
|
||||
|
||||
@ -216,17 +218,19 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
bone_two_trans = stack->skeleton->local_pose_to_global_pose(joint_two_bone_idx, bone_two_local_pos);
|
||||
}
|
||||
|
||||
Transform3D bone_two_tip_trans;
|
||||
Transform bone_two_tip_trans;
|
||||
if (use_tip_node) {
|
||||
if (tip_node_cache.is_null()) {
|
||||
if (tip_node_cache == 0) {
|
||||
_print_execution_error(true, "Tip cache is out of date. Attempting to update...");
|
||||
update_cache_tip();
|
||||
return;
|
||||
}
|
||||
Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
|
||||
|
||||
Spatial *tip = Object::cast_to<Spatial>(ObjectDB::get_instance(tip_node_cache));
|
||||
if (_print_execution_error(!tip || !tip->is_inside_tree(), "Tip node is not in the scene tree. Cannot execute modification!")) {
|
||||
return;
|
||||
}
|
||||
|
||||
bone_two_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
|
||||
} else {
|
||||
stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
|
||||
@ -258,9 +262,9 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
Vector3 axis_1 = bone_one_trans.origin.direction_to(bone_two_tip_trans.origin).cross(bone_one_trans.origin.direction_to(target_trans.origin));
|
||||
|
||||
// Make a quaternion with the delta rotation needed to rotate the first joint into alignment and apply it to the transform.
|
||||
Quaternionernion bone_one_quat = bone_one_trans.basis.get_rotation_quaternion();
|
||||
Quaternionernion rot_0 = Quaternionernion(bone_one_quat.inverse().xform(axis_0).normalized(), (ac_ab_1 - ac_ab_0));
|
||||
Quaternionernion rot_2 = Quaternionernion(bone_one_quat.inverse().xform(axis_1).normalized(), ac_at_0);
|
||||
Quaternion bone_one_quat = bone_one_trans.basis.get_rotation_quaternion();
|
||||
Quaternion rot_0 = Quaternion(bone_one_quat.inverse().xform(axis_0).normalized(), (ac_ab_1 - ac_ab_0));
|
||||
Quaternion rot_2 = Quaternion(bone_one_quat.inverse().xform(axis_1).normalized(), ac_at_0);
|
||||
bone_one_trans.basis.set_quaternion(bone_one_quat * (rot_0 * rot_2));
|
||||
|
||||
stack->skeleton->update_bone_rest_forward_vector(joint_one_bone_idx);
|
||||
@ -290,8 +294,8 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
// alignment, and then apply it to the second joint.
|
||||
real_t ba_bc_0 = Math::acos(CLAMP(bone_two_trans.origin.direction_to(bone_one_trans.origin).dot(bone_two_trans.origin.direction_to(bone_two_tip_trans.origin)), -1, 1));
|
||||
real_t ba_bc_1 = Math::acos(CLAMP((sqr_three_length - sqr_one_length - sqr_two_length) / (-2.0 * joint_one_length * joint_two_length), -1, 1));
|
||||
Quaternionernion bone_two_quat = bone_two_trans.basis.get_rotation_quaternion();
|
||||
Quaternionernion rot_1 = Quaternionernion(bone_two_quat.inverse().xform(axis_0).normalized(), (ba_bc_1 - ba_bc_0));
|
||||
Quaternion bone_two_quat = bone_two_trans.basis.get_rotation_quaternion();
|
||||
Quaternion rot_1 = Quaternion(bone_two_quat.inverse().xform(axis_0).normalized(), (ba_bc_1 - ba_bc_0));
|
||||
bone_two_trans.basis.set_quaternion(bone_two_quat * rot_1);
|
||||
|
||||
stack->skeleton->update_bone_rest_forward_vector(joint_two_bone_idx);
|
||||
@ -304,8 +308,8 @@ void SkeletonModification3DTwoBoneIK::_execute(real_t p_delta) {
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonModification3DTwoBoneIK::_setup_modification(SkeletonModificationStack3D *p_stack) {
|
||||
stack = p_stack;
|
||||
void SkeletonModification3DTwoBoneIK::_setup_modification(Ref<SkeletonModificationStack3D> p_stack) {
|
||||
stack = p_stack.ptr();
|
||||
|
||||
if (stack != nullptr) {
|
||||
is_setup = true;
|
||||
@ -395,7 +399,7 @@ NodePath SkeletonModification3DTwoBoneIK::get_target_node() const {
|
||||
|
||||
void SkeletonModification3DTwoBoneIK::set_use_tip_node(const bool p_use_tip_node) {
|
||||
use_tip_node = p_use_tip_node;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DTwoBoneIK::get_use_tip_node() const {
|
||||
@ -413,7 +417,7 @@ NodePath SkeletonModification3DTwoBoneIK::get_tip_node() const {
|
||||
|
||||
void SkeletonModification3DTwoBoneIK::set_use_pole_node(const bool p_use_pole_node) {
|
||||
use_pole_node = p_use_pole_node;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DTwoBoneIK::get_use_pole_node() const {
|
||||
@ -434,7 +438,7 @@ void SkeletonModification3DTwoBoneIK::set_auto_calculate_joint_length(bool p_cal
|
||||
if (p_calculate) {
|
||||
calculate_joint_lengths();
|
||||
}
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
bool SkeletonModification3DTwoBoneIK::get_auto_calculate_joint_length() const {
|
||||
@ -450,20 +454,20 @@ void SkeletonModification3DTwoBoneIK::calculate_joint_lengths() {
|
||||
ERR_FAIL_COND_MSG(joint_one_bone_idx <= -1 || joint_two_bone_idx <= -1,
|
||||
"One of the bones in the TwoBoneIK modification are not set! Cannot calculate joint lengths!");
|
||||
|
||||
Transform3D bone_one_rest_trans = stack->skeleton->get_bone_global_pose(joint_one_bone_idx);
|
||||
Transform3D bone_two_rest_trans = stack->skeleton->get_bone_global_pose(joint_two_bone_idx);
|
||||
Transform bone_one_rest_trans = stack->skeleton->get_bone_global_pose(joint_one_bone_idx);
|
||||
Transform bone_two_rest_trans = stack->skeleton->get_bone_global_pose(joint_two_bone_idx);
|
||||
|
||||
joint_one_length = bone_one_rest_trans.origin.distance_to(bone_two_rest_trans.origin);
|
||||
|
||||
if (use_tip_node) {
|
||||
if (tip_node_cache.is_null()) {
|
||||
if (tip_node_cache == 0) {
|
||||
update_cache_tip();
|
||||
WARN_PRINT("Tip cache is out of date. Updating...");
|
||||
}
|
||||
|
||||
Node3D *tip = Object::cast_to<Node3D>(ObjectDB::get_instance(tip_node_cache));
|
||||
Spatial *tip = Object::cast_to<Spatial>(ObjectDB::get_instance(tip_node_cache));
|
||||
if (tip) {
|
||||
Transform3D bone_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
|
||||
Transform bone_tip_trans = stack->skeleton->world_transform_to_global_pose(tip->get_global_transform());
|
||||
joint_two_length = bone_two_rest_trans.origin.distance_to(bone_tip_trans.origin);
|
||||
}
|
||||
} else {
|
||||
@ -490,7 +494,7 @@ void SkeletonModification3DTwoBoneIK::set_joint_one_bone_name(String p_bone_name
|
||||
joint_one_bone_idx = stack->skeleton->find_bone(p_bone_name);
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
String SkeletonModification3DTwoBoneIK::get_joint_one_bone_name() const {
|
||||
@ -503,7 +507,7 @@ void SkeletonModification3DTwoBoneIK::set_joint_one_bone_idx(int p_bone_idx) {
|
||||
joint_one_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DTwoBoneIK::get_joint_one_bone_idx() const {
|
||||
@ -524,7 +528,7 @@ void SkeletonModification3DTwoBoneIK::set_joint_two_bone_name(String p_bone_name
|
||||
joint_two_bone_idx = stack->skeleton->find_bone(p_bone_name);
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
String SkeletonModification3DTwoBoneIK::get_joint_two_bone_name() const {
|
||||
@ -537,7 +541,7 @@ void SkeletonModification3DTwoBoneIK::set_joint_two_bone_idx(int p_bone_idx) {
|
||||
joint_two_bone_name = stack->skeleton->get_bone_name(p_bone_idx);
|
||||
}
|
||||
execution_error_found = false;
|
||||
notify_property_list_changed();
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
int SkeletonModification3DTwoBoneIK::get_joint_two_bone_idx() const {
|
||||
@ -604,13 +608,31 @@ void SkeletonModification3DTwoBoneIK::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_joint_two_roll", "roll"), &SkeletonModification3DTwoBoneIK::set_joint_two_roll);
|
||||
ClassDB::bind_method(D_METHOD("get_joint_two_roll"), &SkeletonModification3DTwoBoneIK::get_joint_two_roll);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_target_node", "get_target_node");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Spatial"), "set_target_node", "get_target_node");
|
||||
ADD_GROUP("", "");
|
||||
}
|
||||
|
||||
SkeletonModification3DTwoBoneIK::SkeletonModification3DTwoBoneIK() {
|
||||
stack = nullptr;
|
||||
is_setup = false;
|
||||
|
||||
target_node_cache = 0;
|
||||
|
||||
use_tip_node = false;
|
||||
tip_node_cache = 0;
|
||||
|
||||
use_pole_node = false;
|
||||
pole_node_cache = 0;
|
||||
|
||||
joint_one_bone_idx = -1;
|
||||
joint_two_bone_idx = -1;
|
||||
|
||||
auto_calculate_joint_length = false;
|
||||
joint_one_length = -1;
|
||||
joint_two_length = -1;
|
||||
|
||||
joint_one_roll = 0;
|
||||
joint_two_roll = 0;
|
||||
}
|
||||
|
||||
SkeletonModification3DTwoBoneIK::~SkeletonModification3DTwoBoneIK() {
|
@ -1,3 +1,7 @@
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H
|
||||
#define SKELETON_MODIFICATION_3D_TWOBONEIK_H
|
||||
|
||||
/*************************************************************************/
|
||||
/* skeleton_modification_3d_twoboneik.h */
|
||||
/*************************************************************************/
|
||||
@ -28,11 +32,9 @@
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene/3d/skeleton_3d.h"
|
||||
#include "scene/resources/skeleton_modification_3d.h"
|
||||
|
||||
#ifndef SKELETON_MODIFICATION_3D_TWOBONEIK_H
|
||||
#define SKELETON_MODIFICATION_3D_TWOBONEIK_H
|
||||
class Skeleton;
|
||||
|
||||
class SkeletonModification3DTwoBoneIK : public SkeletonModification3D {
|
||||
GDCLASS(SkeletonModification3DTwoBoneIK, SkeletonModification3D);
|
||||
@ -41,25 +43,25 @@ private:
|
||||
NodePath target_node;
|
||||
ObjectID target_node_cache;
|
||||
|
||||
bool use_tip_node = false;
|
||||
bool use_tip_node;
|
||||
NodePath tip_node;
|
||||
ObjectID tip_node_cache;
|
||||
|
||||
bool use_pole_node = false;
|
||||
bool use_pole_node;
|
||||
NodePath pole_node;
|
||||
ObjectID pole_node_cache;
|
||||
|
||||
String joint_one_bone_name = "";
|
||||
int joint_one_bone_idx = -1;
|
||||
String joint_two_bone_name = "";
|
||||
int joint_two_bone_idx = -1;
|
||||
String joint_one_bone_name;
|
||||
int joint_one_bone_idx;
|
||||
String joint_two_bone_name;
|
||||
int joint_two_bone_idx;
|
||||
|
||||
bool auto_calculate_joint_length = false;
|
||||
real_t joint_one_length = -1;
|
||||
real_t joint_two_length = -1;
|
||||
bool auto_calculate_joint_length;
|
||||
real_t joint_one_length;
|
||||
real_t joint_two_length;
|
||||
|
||||
real_t joint_one_roll = 0;
|
||||
real_t joint_two_roll = 0;
|
||||
real_t joint_one_roll;
|
||||
real_t joint_two_roll;
|
||||
|
||||
void update_cache_target();
|
||||
void update_cache_tip();
|
||||
@ -72,8 +74,8 @@ protected:
|
||||
void _get_property_list(List<PropertyInfo> *p_list) const;
|
||||
|
||||
public:
|
||||
virtual void _execute(real_t p_delta) override;
|
||||
virtual void _setup_modification(SkeletonModificationStack3D *p_stack) override;
|
||||
virtual void _execute(real_t p_delta);
|
||||
virtual void _setup_modification(Ref<SkeletonModificationStack3D> p_stack);
|
||||
|
||||
void set_target_node(const NodePath &p_target_node);
|
||||
NodePath get_target_node() const;
|
Loading…
Reference in New Issue
Block a user