Commit 24905bec by TwistedTwigleg

Made low level changes to the Skeleton3D class and Skeleton3D inspector. Changes listed below:

* Added helper functions to Skeleton3D for converting transforms from bone space to global space, and vice versa. * Updated the Skeleton3D class reference. * Changed the icon used for bones in the Skeleton3D inspector to use BoneAttachement3D's icon. * Changed the Skeleton3D inspector to use EditorPropertyTransform and EditorPropertyVector3 when possible. * Placed the Transform/Matrix for each bone in a sub-section, so it is visually similar to the Node3D inspector.
parent 1aeb8820
......@@ -31,6 +31,16 @@
[i]Deprecated soon.[/i]
</description>
</method>
<method name="bone_transform_to_world_transform">
<return type="Transform">
</return>
<argument index="0" name="bone_transform" type="Transform">
</argument>
<description>
Takes the given bone pose/transform and converts it to a world transform, relative to the [Skeleton3D] node.
This is useful for using the bone transform in calculations with transforms from [Node3D]-based nodes.
</description>
</method>
<method name="clear_bones">
<return type="void">
</return>
......@@ -42,6 +52,7 @@
<return type="void">
</return>
<description>
Removes the global pose override on all bones in the skeleton.
</description>
</method>
<method name="find_bone" qualifiers="const">
......@@ -136,12 +147,14 @@
<argument index="0" name="bone_idx" type="int">
</argument>
<description>
Returns whether the bone rest for the bone at [code]bone_idx[/code] is disabled.
</description>
</method>
<method name="localize_rests">
<return type="void">
</return>
<description>
Returns all bones in the skeleton to their rest poses.
</description>
</method>
<method name="physical_bones_add_collision_exception">
......@@ -150,6 +163,8 @@
<argument index="0" name="exception" type="RID">
</argument>
<description>
Adds a collision exception to the physical bone.
Works just like the [RigidBody3D] node.
</description>
</method>
<method name="physical_bones_remove_collision_exception">
......@@ -158,6 +173,8 @@
<argument index="0" name="exception" type="RID">
</argument>
<description>
Removes a collision exception to the physical bone.
Works just like the [RigidBody3D] node.
</description>
</method>
<method name="physical_bones_start_simulation">
......@@ -166,12 +183,15 @@
<argument index="0" name="bones" type="StringName[]" default="[ ]">
</argument>
<description>
Tells the [PhysicalBone3D] nodes in the Skeleton to start simulating and reacting to the physics world.
Optionally, a list of bone names can be passed-in, allowing only the passed-in bones to be simulated.
</description>
</method>
<method name="physical_bones_stop_simulation">
<return type="void">
</return>
<description>
Tells the [PhysicalBone3D] nodes in the Skeleton to stop simulating.
</description>
</method>
<method name="register_skin">
......@@ -180,6 +200,7 @@
<argument index="0" name="skin" type="Skin">
</argument>
<description>
Binds the given Skin to the Skeleton.
</description>
</method>
<method name="set_bone_custom_pose">
......@@ -190,6 +211,8 @@
<argument index="1" name="custom_pose" type="Transform">
</argument>
<description>
Sets the custom pose transform, [code]custom_pose[/code], for the bone at [code]bone_idx[/code]. This pose is an addition to the bone rest pose.
[b]Note[/b]: The pose transform needs to be in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space.
</description>
</method>
<method name="set_bone_disable_rest">
......@@ -200,6 +223,7 @@
<argument index="1" name="disable" type="bool">
</argument>
<description>
Disables the rest pose for the bone at [code]bone_idx[/code] if [code]true[/code], enables the bone rest if [code]false[/code].
</description>
</method>
<method name="set_bone_global_pose_override">
......@@ -214,6 +238,9 @@
<argument index="3" name="persistent" type="bool" default="false">
</argument>
<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 in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space.
</description>
</method>
<method name="set_bone_parent">
......@@ -237,6 +264,7 @@
</argument>
<description>
Returns 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_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space.
</description>
</method>
<method name="set_bone_rest">
......@@ -267,6 +295,17 @@
<argument index="0" name="bone_idx" type="int">
</argument>
<description>
Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of it's parent prior to being reset.
</description>
</method>
<method name="world_transform_to_bone_transform">
<return type="Transform">
</return>
<argument index="0" name="world_transform" type="Transform">
</argument>
<description>
Takes the given world transform, relative to the [Skeleton3D], and converts it to a bone pose/transform.
This is useful for using setting bone poses using transforms from [Node3D]-based nodes.
</description>
</method>
</methods>
......
......@@ -1283,14 +1283,25 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) {
}
void EditorPropertyVector3::update_property() {
Vector3 val = get_edited_object()->get(get_edited_property());
update_using_vector(get_edited_object()->get(get_edited_property()));
}
void EditorPropertyVector3::update_using_vector(Vector3 p_vector) {
setting = true;
spin[0]->set_value(val.x);
spin[1]->set_value(val.y);
spin[2]->set_value(val.z);
spin[0]->set_value(p_vector.x);
spin[1]->set_value(p_vector.y);
spin[2]->set_value(p_vector.z);
setting = false;
}
Vector3 EditorPropertyVector3::get_vector() {
Vector3 v3;
v3.x = spin[0]->get_value();
v3.y = spin[1]->get_value();
v3.z = spin[2]->get_value();
return v3;
}
void EditorPropertyVector3::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
Color base = get_theme_color("accent_color", "Editor");
......@@ -1434,7 +1445,7 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) {
setting = false;
}
///////////////////// RECT2 /////////////////////////
///////////////////// RECT2i /////////////////////////
void EditorPropertyRect2i::_value_changed(double val, const String &p_name) {
if (setting) {
......@@ -1520,7 +1531,7 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
setting = false;
}
///////////////////// VECTOR3 /////////////////////////
///////////////////// VECTOR3i /////////////////////////
void EditorPropertyVector3i::_value_changed(double val, const String &p_name) {
if (setting) {
......@@ -2029,21 +2040,23 @@ void EditorPropertyTransform::_value_changed(double val, const String &p_name) {
}
void EditorPropertyTransform::update_property() {
Transform val = get_edited_object()->get(get_edited_property());
setting = true;
spin[0]->set_value(val.basis[0][0]);
spin[1]->set_value(val.basis[1][0]);
spin[2]->set_value(val.basis[2][0]);
spin[3]->set_value(val.basis[0][1]);
spin[4]->set_value(val.basis[1][1]);
spin[5]->set_value(val.basis[2][1]);
spin[6]->set_value(val.basis[0][2]);
spin[7]->set_value(val.basis[1][2]);
spin[8]->set_value(val.basis[2][2]);
spin[9]->set_value(val.origin[0]);
spin[10]->set_value(val.origin[1]);
spin[11]->set_value(val.origin[2]);
update_using_transform(get_edited_object()->get(get_edited_property()));
}
void EditorPropertyTransform::update_using_transform(Transform p_transform) {
setting = true;
spin[0]->set_value(p_transform.basis[0][0]);
spin[1]->set_value(p_transform.basis[1][0]);
spin[2]->set_value(p_transform.basis[2][0]);
spin[3]->set_value(p_transform.basis[0][1]);
spin[4]->set_value(p_transform.basis[1][1]);
spin[5]->set_value(p_transform.basis[2][1]);
spin[6]->set_value(p_transform.basis[0][2]);
spin[7]->set_value(p_transform.basis[1][2]);
spin[8]->set_value(p_transform.basis[2][2]);
spin[9]->set_value(p_transform.origin[0]);
spin[10]->set_value(p_transform.origin[1]);
spin[11]->set_value(p_transform.origin[2]);
setting = false;
}
......
......@@ -392,6 +392,8 @@ protected:
public:
virtual void update_property();
virtual void update_using_vector(Vector3 p_vector);
virtual Vector3 get_vector();
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
EditorPropertyVector3(bool p_force_wide = false);
};
......@@ -536,6 +538,7 @@ protected:
public:
virtual void update_property();
virtual void update_using_transform(Transform p_transform);
void setup(double p_min, double p_max, double p_step, bool p_no_slider);
EditorPropertyTransform();
};
......
......@@ -41,30 +41,19 @@ class PhysicalBone3D;
class Skeleton3DEditorPlugin;
class Button;
class CheckBox;
class EditorPropertyTransform;
class EditorPropertyVector3;
class BoneTransformEditor : public VBoxContainer {
GDCLASS(BoneTransformEditor, VBoxContainer);
static const int32_t TRANSLATION_COMPONENTS = 3;
static const int32_t ROTATION_DEGREES_COMPONENTS = 3;
static const int32_t SCALE_COMPONENTS = 3;
static const int32_t BASIS_COMPONENTS = 9;
static const int32_t BASIS_SPLIT_COMPONENTS = 3;
static const int32_t TRANSFORM_COMPONENTS = 12;
static const int32_t TRANSFORM_SPLIT_COMPONENTS = 3;
static const int32_t TRANSFORM_CONTROL_COMPONENTS = 3;
EditorInspectorSection *section;
GridContainer *translation_grid;
GridContainer *rotation_grid;
GridContainer *scale_grid;
GridContainer *transform_grid;
EditorSpinSlider *translation_slider[TRANSLATION_COMPONENTS];
EditorSpinSlider *rotation_slider[ROTATION_DEGREES_COMPONENTS];
EditorSpinSlider *scale_slider[SCALE_COMPONENTS];
EditorSpinSlider *transform_slider[TRANSFORM_COMPONENTS];
EditorPropertyVector3 *translation_property;
EditorPropertyVector3 *rotation_property;
EditorPropertyVector3 *scale_property;
EditorInspectorSection *transform_section;
EditorPropertyTransform *transform_property;
Rect2 background_rects[5];
......@@ -83,17 +72,22 @@ class BoneTransformEditor : public VBoxContainer {
String label;
void create_editors();
void setup_spinner(EditorSpinSlider *spinner, const bool is_transform_spinner);
void _value_changed(const double p_value, const bool p_from_transform);
Transform compute_transform(const bool p_from_transform) const;
// Called when one of the EditorSpinSliders are changed.
void _value_changed(const double p_value);
// Called when the one of the EditorPropertyVector3 are updated.
void _value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean);
// Called when the transform_property is updated.
void _value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean);
// Changes the transform to the given transform and updates the UI accordingly.
void _change_transform(Transform p_new_transform);
// Creates a Transform using the EditorPropertyVector3 properties.
Transform compute_transform_from_vector3s() const;
void update_enabled_checkbox();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
BoneTransformEditor(Skeleton3D *p_skeleton);
......
......@@ -67,6 +67,8 @@ SkinReference::~SkinReference() {
RS::get_singleton()->free(skeleton);
}
///////////////////////////////////////
bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) {
String path = p_path;
......@@ -853,6 +855,15 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
return skin_ref;
}
// helper functions
Transform Skeleton3D::bone_transform_to_world_transform(Transform p_bone_transform) {
return get_global_transform() * p_bone_transform;
}
Transform Skeleton3D::world_transform_to_bone_transform(Transform p_world_transform) {
return get_global_transform().affine_inverse() * p_world_transform;
}
void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_process_orders"), &Skeleton3D::get_bone_process_orders);
ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton3D::add_bone);
......@@ -892,6 +903,9 @@ void Skeleton3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose);
ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose);
ClassDB::bind_method(D_METHOD("bone_transform_to_world_transform", "bone_transform"), &Skeleton3D::bone_transform_to_world_transform);
ClassDB::bind_method(D_METHOD("world_transform_to_bone_transform", "world_transform"), &Skeleton3D::world_transform_to_bone_transform);
#ifndef _3D_DISABLED
ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones);
......
......@@ -71,10 +71,6 @@ class Skeleton3D : public Node3D {
private:
friend class SkinReference;
Set<SkinReference *> skin_bindings;
void _skin_changed();
struct Bone {
String name;
......@@ -116,6 +112,10 @@ private:
}
};
Set<SkinReference *> skin_bindings;
void _skin_changed();
bool animate_physical_bones;
Vector<Bone> bones;
Vector<int> process_order;
......@@ -200,6 +200,10 @@ public:
Ref<SkinReference> register_skin(const Ref<Skin> &p_skin);
// Helper functions
Transform bone_transform_to_world_transform(Transform p_transform);
Transform world_transform_to_bone_transform(Transform p_transform);
#ifndef _3D_DISABLED
// Physical bone API
......@@ -213,7 +217,7 @@ public:
PhysicalBone3D *get_physical_bone_parent(int p_bone);
private:
/// This is a slow API os it's cached
/// This is a slow API, so it's cached
PhysicalBone3D *_get_physical_bone_parent(int p_bone);
void _rebuild_physical_bones_cache();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment