diff --git a/doc/classes/BoneConstraint3D.xml b/doc/classes/BoneConstraint3D.xml index 41c894614f8..3dba9e0eec2 100644 --- a/doc/classes/BoneConstraint3D.xml +++ b/doc/classes/BoneConstraint3D.xml @@ -52,6 +52,21 @@ This bone will be only referenced and not modified by this modifier. + + + + + Returns the reference node path of the setting at [param index]. + This node will be only referenced and not modified by this modifier. + + + + + + + Returns the reference target type of the setting at [param index]. See also [enum ReferenceType]. + + @@ -100,6 +115,23 @@ This bone will be only referenced and not modified by this modifier. + + + + + + Sets the reference node path of the setting at [param index] to [param node]. + This node will be only referenced and not modified by this modifier. + + + + + + + + Sets the reference target type of the setting at [param index] to [param type]. See also [enum ReferenceType]. + + @@ -108,4 +140,13 @@ + + + The reference target is a bone. In this case, the reference target spaces is local space. + + + The reference target is a [Node3D]. In this case, the reference target spaces is model space. + In other words, the reference target's coordinates are treated as if it were placed directly under [Skeleton3D] which parent of the [BoneConstraint3D]. + + diff --git a/doc/classes/ConvertTransformModifier3D.xml b/doc/classes/ConvertTransformModifier3D.xml index b69ace77fbd..e6845eff41f 100644 --- a/doc/classes/ConvertTransformModifier3D.xml +++ b/doc/classes/ConvertTransformModifier3D.xml @@ -14,6 +14,7 @@ - Extract reference pose absolutely and add it to the apply bone's pose. [b]Not Relative + Not Additive:[/b] - Extract reference pose absolutely and the apply bone's pose is replaced with it. + [b]Note:[/b] Relative option is available only in the case [method BoneConstraint3D.get_reference_type] is [constant BoneConstraint3D.REFERENCE_TYPE_BONE]. See also [enum BoneConstraint3D.ReferenceType]. diff --git a/doc/classes/CopyTransformModifier3D.xml b/doc/classes/CopyTransformModifier3D.xml index c75d8c1429c..1c5c3947680 100644 --- a/doc/classes/CopyTransformModifier3D.xml +++ b/doc/classes/CopyTransformModifier3D.xml @@ -14,6 +14,7 @@ - Extract reference pose absolutely and add it to the apply bone's pose. [b]Not Relative + Not Additive:[/b] - Extract reference pose absolutely and the apply bone's pose is replaced with it. + [b]Note:[/b] Relative option is available only in the case [method BoneConstraint3D.get_reference_type] is [constant BoneConstraint3D.REFERENCE_TYPE_BONE]. See also [enum BoneConstraint3D.ReferenceType]. diff --git a/scene/3d/aim_modifier_3d.cpp b/scene/3d/aim_modifier_3d.cpp index 71e3a872da8..30f9694eb3b 100644 --- a/scene/3d/aim_modifier_3d.cpp +++ b/scene/3d/aim_modifier_3d.cpp @@ -37,7 +37,7 @@ bool AimModifier3D::_set(const StringName &p_path, const Variant &p_value) { if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "forward_axis") { set_forward_axis(which, static_cast((int)p_value)); @@ -60,7 +60,7 @@ bool AimModifier3D::_get(const StringName &p_path, Variant &r_ret) const { if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "forward_axis") { r_ret = (int)get_forward_axis(which); @@ -80,7 +80,7 @@ bool AimModifier3D::_get(const StringName &p_path, Variant &r_ret) const { void AimModifier3D::_get_property_list(List *p_list) const { BoneConstraint3D::get_property_list(p_list); - for (int i = 0; i < settings.size(); i++) { + for (uint32_t i = 0; i < settings.size(); i++) { String path = "settings/" + itos(i) + "/"; int rotation_usage = is_using_euler(i) ? PROPERTY_USAGE_DEFAULT : PROPERTY_USAGE_NONE; @@ -93,7 +93,7 @@ void AimModifier3D::_get_property_list(List *p_list) const { PackedStringArray AimModifier3D::get_configuration_warnings() const { PackedStringArray warnings = BoneConstraint3D::get_configuration_warnings(); - for (int i = 0; i < settings.size(); i++) { + for (uint32_t i = 0; i < settings.size(); i++) { if (is_using_euler(i) && get_axis_from_bone_axis(get_forward_axis(i)) == get_primary_rotation_axis(i)) { warnings.push_back(vformat(RTR("Forward axis and primary rotation axis must not be parallel in setting %s."), itos(i))); } @@ -103,24 +103,24 @@ PackedStringArray AimModifier3D::get_configuration_warnings() const { } void AimModifier3D::_validate_setting(int p_index) { - settings.write[p_index] = memnew(AimModifier3DSetting); + settings[p_index] = memnew(AimModifier3DSetting); } void AimModifier3D::set_forward_axis(int p_index, BoneAxis p_axis) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); AimModifier3DSetting *setting = static_cast(settings[p_index]); setting->forward_axis = p_axis; update_configuration_warnings(); } SkeletonModifier3D::BoneAxis AimModifier3D::get_forward_axis(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), BONE_AXIS_PLUS_Y); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), BONE_AXIS_PLUS_Y); AimModifier3DSetting *setting = static_cast(settings[p_index]); return setting->forward_axis; } void AimModifier3D::set_use_euler(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); AimModifier3DSetting *setting = static_cast(settings[p_index]); setting->use_euler = p_enabled; notify_property_list_changed(); @@ -128,32 +128,32 @@ void AimModifier3D::set_use_euler(int p_index, bool p_enabled) { } bool AimModifier3D::is_using_euler(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); AimModifier3DSetting *setting = static_cast(settings[p_index]); return setting->use_euler; } void AimModifier3D::set_primary_rotation_axis(int p_index, Vector3::Axis p_axis) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); AimModifier3DSetting *setting = static_cast(settings[p_index]); setting->primary_rotation_axis = p_axis; update_configuration_warnings(); } Vector3::Axis AimModifier3D::get_primary_rotation_axis(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), Vector3::AXIS_X); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), Vector3::AXIS_X); AimModifier3DSetting *setting = static_cast(settings[p_index]); return setting->primary_rotation_axis; } void AimModifier3D::set_use_secondary_rotation(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); AimModifier3DSetting *setting = static_cast(settings[p_index]); setting->use_secondary_rotation = p_enabled; } bool AimModifier3D::is_using_secondary_rotation(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); AimModifier3DSetting *setting = static_cast(settings[p_index]); return setting->use_secondary_rotation; } @@ -171,16 +171,28 @@ void AimModifier3D::_bind_methods() { ADD_ARRAY_COUNT("Settings", "setting_count", "set_setting_count", "get_setting_count", "settings/"); } -void AimModifier3D::_process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { +void AimModifier3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { if (p_apply_bone == p_reference_bone) { ERR_PRINT_ONCE_ED(vformat("In setting %s, the reference bone must not be same with the apply bone.", itos(p_index))); return; } + Vector3 reference_origin = p_skeleton->get_bone_global_pose(p_reference_bone).origin; + _process_aim(p_index, p_skeleton, p_apply_bone, reference_origin, p_amount); +} +void AimModifier3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) { + Node3D *nd = Object::cast_to(get_node_or_null(p_reference_node)); + if (!nd) { + return; + } + Vector3 reference_origin = nd->get_global_transform_interpolated().origin - p_skeleton->get_global_transform_interpolated().origin; + _process_aim(p_index, p_skeleton, p_apply_bone, reference_origin, p_amount); +} + +void AimModifier3D::_process_aim(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, Vector3 p_target, float p_amount) { AimModifier3DSetting *setting = static_cast(settings[p_index]); // Prepare forward_vector and rest. - Vector3 reference_origin = p_skeleton->get_bone_global_pose(p_reference_bone).origin; Transform3D src_bone_rest = p_skeleton->get_bone_rest(p_apply_bone); Transform3D bone_rest_space; int parent_bone = p_skeleton->get_bone_parent(p_apply_bone); @@ -190,7 +202,7 @@ void AimModifier3D::_process_constraint(int p_index, Skeleton3D *p_skeleton, int bone_rest_space = p_skeleton->get_bone_global_pose(parent_bone); bone_rest_space.translate_local(src_bone_rest.origin); } - Vector3 forward_vector = bone_rest_space.basis.get_rotation_quaternion().xform_inv(reference_origin - bone_rest_space.origin); + Vector3 forward_vector = bone_rest_space.basis.get_rotation_quaternion().xform_inv(p_target - bone_rest_space.origin); if (forward_vector.is_zero_approx()) { return; } diff --git a/scene/3d/aim_modifier_3d.h b/scene/3d/aim_modifier_3d.h index a50c9c2af83..58019a4b8a9 100644 --- a/scene/3d/aim_modifier_3d.h +++ b/scene/3d/aim_modifier_3d.h @@ -51,7 +51,9 @@ protected: static void _bind_methods(); - virtual void _process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) override; + virtual void _process_aim(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, Vector3 p_target, float p_amount); virtual void _validate_setting(int p_index) override; public: diff --git a/scene/3d/bone_constraint_3d.cpp b/scene/3d/bone_constraint_3d.cpp index 5bad937633e..8fd14d014c4 100644 --- a/scene/3d/bone_constraint_3d.cpp +++ b/scene/3d/bone_constraint_3d.cpp @@ -36,10 +36,12 @@ bool BoneConstraint3D::_set(const StringName &p_path, const Variant &p_value) { if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "amount") { set_amount(which, p_value); + } else if (what == "reference_type") { + set_reference_type(which, static_cast((int)p_value)); } else if (what == "apply_bone_name") { set_apply_bone_name(which, p_value); } else if (what == "reference_bone_name") { @@ -48,6 +50,8 @@ bool BoneConstraint3D::_set(const StringName &p_path, const Variant &p_value) { set_apply_bone(which, p_value); } else if (what == "reference_bone") { set_reference_bone(which, p_value); + } else if (what == "reference_node") { + set_reference_node(which, p_value); } else { return false; } @@ -61,10 +65,12 @@ bool BoneConstraint3D::_get(const StringName &p_path, Variant &r_ret) const { if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "amount") { r_ret = get_amount(which); + } else if (what == "reference_type") { + r_ret = (int)get_reference_type(which); } else if (what == "apply_bone_name") { r_ret = get_apply_bone_name(which); } else if (what == "reference_bone_name") { @@ -73,6 +79,8 @@ bool BoneConstraint3D::_get(const StringName &p_path, Variant &r_ret) const { r_ret = get_apply_bone(which); } else if (what == "reference_bone") { r_ret = get_reference_bone(which); + } else if (what == "reference_node") { + r_ret = get_reference_node(which); } else { return false; } @@ -87,23 +95,46 @@ void BoneConstraint3D::get_property_list(List *p_list) const { enum_hint = skeleton->get_concatenated_bone_names(); } - for (int i = 0; i < settings.size(); i++) { + LocalVector props; + + for (uint32_t i = 0; i < settings.size(); i++) { String path = "settings/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::FLOAT, path + "amount", PROPERTY_HINT_RANGE, "0,1,0.001")); - p_list->push_back(PropertyInfo(Variant::STRING, path + "apply_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint)); - p_list->push_back(PropertyInfo(Variant::INT, path + "apply_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::STRING, path + "reference_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint)); - p_list->push_back(PropertyInfo(Variant::INT, path + "reference_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + props.push_back(PropertyInfo(Variant::FLOAT, path + "amount", PROPERTY_HINT_RANGE, "0,1,0.001")); + props.push_back(PropertyInfo(Variant::STRING, path + "apply_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint)); + props.push_back(PropertyInfo(Variant::INT, path + "apply_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + props.push_back(PropertyInfo(Variant::INT, path + "reference_type", PROPERTY_HINT_ENUM, "Bone,Node")); + props.push_back(PropertyInfo(Variant::STRING, path + "reference_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint)); + props.push_back(PropertyInfo(Variant::INT, path + "reference_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + props.push_back(PropertyInfo(Variant::NODE_PATH, path + "reference_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D")); + } + + for (PropertyInfo &p : props) { + _validate_dynamic_prop(p); + p_list->push_back(p); + } +} + +void BoneConstraint3D::_validate_dynamic_prop(PropertyInfo &p_property) const { + PackedStringArray split = p_property.name.split("/"); + if (split.size() > 2 && split[0] == "settings") { + int which = split[1].to_int(); + if (split[2].begins_with("reference_bone") && get_reference_type(which) != REFERENCE_TYPE_BONE) { + p_property.usage = PROPERTY_USAGE_NONE; + } + if (split[2].begins_with("reference_node") && get_reference_type(which) != REFERENCE_TYPE_NODE) { + p_property.usage = PROPERTY_USAGE_NONE; + } } } void BoneConstraint3D::set_setting_count(int p_count) { ERR_FAIL_COND(p_count < 0); - int delta = p_count - settings.size(); + int delta = p_count - (int)settings.size(); if (delta < 0) { for (int i = delta; i < 0; i++) { - memdelete(settings[settings.size() + i]); + memdelete(settings[(int)settings.size() + i]); + settings[(int)settings.size() + i] = nullptr; } } settings.resize(p_count); @@ -119,11 +150,11 @@ void BoneConstraint3D::set_setting_count(int p_count) { } int BoneConstraint3D::get_setting_count() const { - return settings.size(); + return (int)settings.size(); } void BoneConstraint3D::_validate_setting(int p_index) { - settings.write[p_index] = memnew(BoneConstraint3DSetting); + settings[p_index] = memnew(BoneConstraint3DSetting); } void BoneConstraint3D::clear_settings() { @@ -131,17 +162,17 @@ void BoneConstraint3D::clear_settings() { } void BoneConstraint3D::set_amount(int p_index, float p_amount) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); settings[p_index]->amount = p_amount; } float BoneConstraint3D::get_amount(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0.0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0.0); return settings[p_index]->amount; } void BoneConstraint3D::set_apply_bone_name(int p_index, const String &p_bone_name) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); settings[p_index]->apply_bone_name = p_bone_name; Skeleton3D *sk = get_skeleton(); if (sk) { @@ -150,12 +181,12 @@ void BoneConstraint3D::set_apply_bone_name(int p_index, const String &p_bone_nam } String BoneConstraint3D::get_apply_bone_name(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), String()); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), String()); return settings[p_index]->apply_bone_name; } void BoneConstraint3D::set_apply_bone(int p_index, int p_bone) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); settings[p_index]->apply_bone = p_bone; Skeleton3D *sk = get_skeleton(); if (sk) { @@ -169,12 +200,23 @@ void BoneConstraint3D::set_apply_bone(int p_index, int p_bone) { } int BoneConstraint3D::get_apply_bone(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), -1); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), -1); return settings[p_index]->apply_bone; } +void BoneConstraint3D::set_reference_type(int p_index, ReferenceType p_type) { + ERR_FAIL_INDEX(p_index, (int)settings.size()); + settings[p_index]->reference_type = p_type; + notify_property_list_changed(); +} + +BoneConstraint3D::ReferenceType BoneConstraint3D::get_reference_type(int p_index) const { + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), REFERENCE_TYPE_BONE); + return settings[p_index]->reference_type; +} + void BoneConstraint3D::set_reference_bone_name(int p_index, const String &p_bone_name) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); settings[p_index]->reference_bone_name = p_bone_name; Skeleton3D *sk = get_skeleton(); if (sk) { @@ -183,12 +225,12 @@ void BoneConstraint3D::set_reference_bone_name(int p_index, const String &p_bone } String BoneConstraint3D::get_reference_bone_name(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), String()); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), String()); return settings[p_index]->reference_bone_name; } void BoneConstraint3D::set_reference_bone(int p_index, int p_bone) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); settings[p_index]->reference_bone = p_bone; Skeleton3D *sk = get_skeleton(); if (sk) { @@ -202,10 +244,20 @@ void BoneConstraint3D::set_reference_bone(int p_index, int p_bone) { } int BoneConstraint3D::get_reference_bone(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), -1); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), -1); return settings[p_index]->reference_bone; } +void BoneConstraint3D::set_reference_node(int p_index, const NodePath &p_node) { + ERR_FAIL_INDEX(p_index, (int)settings.size()); + settings[p_index]->reference_node = p_node; +} + +NodePath BoneConstraint3D::get_reference_node(int p_index) const { + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), NodePath()); + return settings[p_index]->reference_node; +} + void BoneConstraint3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_amount", "index", "amount"), &BoneConstraint3D::set_amount); ClassDB::bind_method(D_METHOD("get_amount", "index"), &BoneConstraint3D::get_amount); @@ -213,18 +265,25 @@ void BoneConstraint3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_apply_bone_name", "index"), &BoneConstraint3D::get_apply_bone_name); ClassDB::bind_method(D_METHOD("set_apply_bone", "index", "bone"), &BoneConstraint3D::set_apply_bone); ClassDB::bind_method(D_METHOD("get_apply_bone", "index"), &BoneConstraint3D::get_apply_bone); + ClassDB::bind_method(D_METHOD("set_reference_type", "index", "type"), &BoneConstraint3D::set_reference_type); + ClassDB::bind_method(D_METHOD("get_reference_type", "index"), &BoneConstraint3D::get_reference_type); ClassDB::bind_method(D_METHOD("set_reference_bone_name", "index", "bone_name"), &BoneConstraint3D::set_reference_bone_name); ClassDB::bind_method(D_METHOD("get_reference_bone_name", "index"), &BoneConstraint3D::get_reference_bone_name); ClassDB::bind_method(D_METHOD("set_reference_bone", "index", "bone"), &BoneConstraint3D::set_reference_bone); ClassDB::bind_method(D_METHOD("get_reference_bone", "index"), &BoneConstraint3D::get_reference_bone); + ClassDB::bind_method(D_METHOD("set_reference_node", "index", "node"), &BoneConstraint3D::set_reference_node); + ClassDB::bind_method(D_METHOD("get_reference_node", "index"), &BoneConstraint3D::get_reference_node); ClassDB::bind_method(D_METHOD("set_setting_count", "count"), &BoneConstraint3D::set_setting_count); ClassDB::bind_method(D_METHOD("get_setting_count"), &BoneConstraint3D::get_setting_count); ClassDB::bind_method(D_METHOD("clear_setting"), &BoneConstraint3D::clear_settings); + + BIND_ENUM_CONSTANT(REFERENCE_TYPE_BONE); + BIND_ENUM_CONSTANT(REFERENCE_TYPE_NODE); } void BoneConstraint3D::_validate_bone_names() { - for (int i = 0; i < settings.size(); i++) { + for (int i = 0; i < (int)settings.size(); i++) { // Prior bone name. if (!settings[i]->apply_bone_name.is_empty()) { set_apply_bone_name(i, settings[i]->apply_bone_name); @@ -246,27 +305,38 @@ void BoneConstraint3D::_process_modification(double p_delta) { return; } - for (int i = 0; i < settings.size(); i++) { - int apply_bone = settings[i]->apply_bone; - if (apply_bone < 0) { - continue; - } - - int reference_bone = settings[i]->reference_bone; - if (reference_bone < 0) { - continue; - } - + for (int i = 0; i < (int)settings.size(); i++) { float amount = settings[i]->amount; if (amount <= 0) { continue; } - _process_constraint(i, skeleton, apply_bone, reference_bone, amount); + int apply_bone = settings[i]->apply_bone; + if (apply_bone < 0) { + continue; + } + + if (settings[i]->reference_type == REFERENCE_TYPE_BONE) { + int reference_bone = settings[i]->reference_bone; + if (reference_bone < 0) { + continue; + } + _process_constraint_by_bone(i, skeleton, apply_bone, reference_bone, amount); + } else { + NodePath pt = settings[i]->reference_node; + if (pt.is_empty()) { + continue; + } + _process_constraint_by_node(i, skeleton, apply_bone, pt, amount); + } } } -void BoneConstraint3D::_process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { +void BoneConstraint3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { + // +} + +void BoneConstraint3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) { // } diff --git a/scene/3d/bone_constraint_3d.h b/scene/3d/bone_constraint_3d.h index 3da28f24ab7..da27acb479f 100644 --- a/scene/3d/bone_constraint_3d.h +++ b/scene/3d/bone_constraint_3d.h @@ -36,18 +36,27 @@ class BoneConstraint3D : public SkeletonModifier3D { GDCLASS(BoneConstraint3D, SkeletonModifier3D); public: + enum ReferenceType { + REFERENCE_TYPE_BONE, + REFERENCE_TYPE_NODE, + }; + struct BoneConstraint3DSetting { float amount = 1.0; String apply_bone_name; int apply_bone = -1; + ReferenceType reference_type = REFERENCE_TYPE_BONE; + String reference_bone_name; int reference_bone = -1; + + NodePath reference_node; }; protected: - Vector settings; + LocalVector settings; bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); @@ -55,13 +64,15 @@ protected: // Define get_property_list() instead of _get_property_list() // to merge child class properties into parent class array inspector. void get_property_list(List *p_list) const; // Will be called by child classes. + void _validate_dynamic_prop(PropertyInfo &p_property) const; virtual void _validate_bone_names() override; static void _bind_methods(); virtual void _process_modification(double p_delta) override; - virtual void _process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount); + virtual void _process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount); + virtual void _process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount); virtual void _validate_setting(int p_index); public: @@ -73,11 +84,17 @@ public: void set_apply_bone(int p_index, int p_bone); int get_apply_bone(int p_index) const; + void set_reference_type(int p_index, ReferenceType p_type); + ReferenceType get_reference_type(int p_index) const; + void set_reference_bone_name(int p_index, const String &p_bone_name); String get_reference_bone_name(int p_index) const; void set_reference_bone(int p_index, int p_bone); int get_reference_bone(int p_index) const; + void set_reference_node(int p_index, const NodePath &p_node); + NodePath get_reference_node(int p_index) const; + void set_setting_count(int p_count); int get_setting_count() const; @@ -85,3 +102,5 @@ public: ~BoneConstraint3D(); }; + +VARIANT_ENUM_CAST(BoneConstraint3D::ReferenceType); diff --git a/scene/3d/convert_transform_modifier_3d.cpp b/scene/3d/convert_transform_modifier_3d.cpp index 3fdf147b22d..55c9f565339 100644 --- a/scene/3d/convert_transform_modifier_3d.cpp +++ b/scene/3d/convert_transform_modifier_3d.cpp @@ -40,7 +40,7 @@ bool ConvertTransformModifier3D::_set(const StringName &p_path, const Variant &p if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String where = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); String what = path.get_slicec('/', 3); if (where == "apply") { @@ -84,7 +84,7 @@ bool ConvertTransformModifier3D::_get(const StringName &p_path, Variant &r_ret) if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String where = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); String what = path.get_slicec('/', 3); if (where == "apply") { @@ -125,7 +125,9 @@ bool ConvertTransformModifier3D::_get(const StringName &p_path, Variant &r_ret) void ConvertTransformModifier3D::_get_property_list(List *p_list) const { BoneConstraint3D::get_property_list(p_list); - for (int i = 0; i < settings.size(); i++) { + LocalVector props; + + for (uint32_t i = 0; i < settings.size(); i++) { String path = "settings/" + itos(i) + "/"; String hint_apply_range; @@ -136,10 +138,10 @@ void ConvertTransformModifier3D::_get_property_list(List *p_list) } else { hint_apply_range = HINT_SCALE; } - p_list->push_back(PropertyInfo(Variant::INT, path + "apply/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale")); - p_list->push_back(PropertyInfo(Variant::INT, path + "apply/axis", PROPERTY_HINT_ENUM, "X,Y,Z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_min", PROPERTY_HINT_RANGE, hint_apply_range)); - p_list->push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_max", PROPERTY_HINT_RANGE, hint_apply_range)); + props.push_back(PropertyInfo(Variant::INT, path + "apply/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale")); + props.push_back(PropertyInfo(Variant::INT, path + "apply/axis", PROPERTY_HINT_ENUM, "X,Y,Z")); + props.push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_min", PROPERTY_HINT_RANGE, hint_apply_range)); + props.push_back(PropertyInfo(Variant::FLOAT, path + "apply/range_max", PROPERTY_HINT_RANGE, hint_apply_range)); String hint_reference_range; if (get_reference_transform_mode(i) == TRANSFORM_MODE_POSITION) { @@ -149,138 +151,153 @@ void ConvertTransformModifier3D::_get_property_list(List *p_list) } else { hint_reference_range = HINT_SCALE; } - p_list->push_back(PropertyInfo(Variant::INT, path + "reference/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale")); - p_list->push_back(PropertyInfo(Variant::INT, path + "reference/axis", PROPERTY_HINT_ENUM, "X,Y,Z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_min", PROPERTY_HINT_RANGE, hint_reference_range)); - p_list->push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_max", PROPERTY_HINT_RANGE, hint_reference_range)); + props.push_back(PropertyInfo(Variant::INT, path + "reference/transform_mode", PROPERTY_HINT_ENUM, "Position,Rotation,Scale")); + props.push_back(PropertyInfo(Variant::INT, path + "reference/axis", PROPERTY_HINT_ENUM, "X,Y,Z")); + props.push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_min", PROPERTY_HINT_RANGE, hint_reference_range)); + props.push_back(PropertyInfo(Variant::FLOAT, path + "reference/range_max", PROPERTY_HINT_RANGE, hint_reference_range)); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "relative")); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "additive")); + props.push_back(PropertyInfo(Variant::BOOL, path + "relative")); + props.push_back(PropertyInfo(Variant::BOOL, path + "additive")); + } + + for (PropertyInfo &p : props) { + _validate_dynamic_prop(p); + p_list->push_back(p); + } +} + +void ConvertTransformModifier3D::_validate_dynamic_prop(PropertyInfo &p_property) const { + PackedStringArray split = p_property.name.split("/"); + if (split.size() > 2 && split[0] == "settings") { + int which = split[1].to_int(); + if (split[2].begins_with("relative") && get_reference_type(which) != REFERENCE_TYPE_BONE) { + p_property.usage = PROPERTY_USAGE_NONE; + } } } void ConvertTransformModifier3D::_validate_setting(int p_index) { - settings.write[p_index] = memnew(ConvertTransform3DSetting); + settings[p_index] = memnew(ConvertTransform3DSetting); } void ConvertTransformModifier3D::set_apply_transform_mode(int p_index, TransformMode p_transform_mode) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->apply_transform_mode = p_transform_mode; notify_property_list_changed(); } ConvertTransformModifier3D::TransformMode ConvertTransformModifier3D::get_apply_transform_mode(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), TRANSFORM_MODE_POSITION); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), TRANSFORM_MODE_POSITION); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->apply_transform_mode; } void ConvertTransformModifier3D::set_apply_axis(int p_index, Vector3::Axis p_axis) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->apply_axis = p_axis; } Vector3::Axis ConvertTransformModifier3D::get_apply_axis(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), Vector3::AXIS_X); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), Vector3::AXIS_X); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->apply_axis; } void ConvertTransformModifier3D::set_apply_range_min(int p_index, float p_range_min) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->apply_range_min = p_range_min; } float ConvertTransformModifier3D::get_apply_range_min(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->apply_range_min; } void ConvertTransformModifier3D::set_apply_range_max(int p_index, float p_range_max) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->apply_range_max = p_range_max; } float ConvertTransformModifier3D::get_apply_range_max(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->apply_range_max; } void ConvertTransformModifier3D::set_reference_transform_mode(int p_index, TransformMode p_transform_mode) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->reference_transform_mode = p_transform_mode; notify_property_list_changed(); } ConvertTransformModifier3D::TransformMode ConvertTransformModifier3D::get_reference_transform_mode(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), TRANSFORM_MODE_POSITION); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), TRANSFORM_MODE_POSITION); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->reference_transform_mode; } void ConvertTransformModifier3D::set_reference_axis(int p_index, Vector3::Axis p_axis) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->reference_axis = p_axis; } Vector3::Axis ConvertTransformModifier3D::get_reference_axis(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), Vector3::AXIS_X); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), Vector3::AXIS_X); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->reference_axis; } void ConvertTransformModifier3D::set_reference_range_min(int p_index, float p_range_min) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->reference_range_min = p_range_min; } float ConvertTransformModifier3D::get_reference_range_min(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->reference_range_min; } void ConvertTransformModifier3D::set_reference_range_max(int p_index, float p_range_max) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->reference_range_max = p_range_max; } float ConvertTransformModifier3D::get_reference_range_max(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->reference_range_max; } void ConvertTransformModifier3D::set_relative(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->relative = p_enabled; } bool ConvertTransformModifier3D::is_relative(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); - return setting->relative; + return setting->is_relative(); } void ConvertTransformModifier3D::set_additive(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); setting->additive = p_enabled; } bool ConvertTransformModifier3D::is_additive(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); ConvertTransform3DSetting *setting = static_cast(settings[p_index]); return setting->additive; } @@ -316,16 +333,37 @@ void ConvertTransformModifier3D::_bind_methods() { BIND_ENUM_CONSTANT(TRANSFORM_MODE_SCALE); } -void ConvertTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { +void ConvertTransformModifier3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { ConvertTransform3DSetting *setting = static_cast(settings[p_index]); - Transform3D destination = p_skeleton->get_bone_pose(p_reference_bone); - if (setting->relative) { + if (setting->is_relative()) { Vector3 scl_relative = destination.basis.get_scale() / p_skeleton->get_bone_rest(p_reference_bone).basis.get_scale(); destination.basis = p_skeleton->get_bone_rest(p_reference_bone).basis.get_rotation_quaternion().inverse() * destination.basis.get_rotation_quaternion(); destination.basis.scale_local(scl_relative); destination.origin = destination.origin - p_skeleton->get_bone_rest(p_reference_bone).origin; } + _process_convert(p_index, p_skeleton, p_apply_bone, destination, p_amount); +} + +void ConvertTransformModifier3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) { + Node3D *nd = Object::cast_to(get_node_or_null(p_reference_node)); + if (!nd) { + return; + } + Transform3D skel_tr = p_skeleton->get_global_transform_interpolated(); + int parent = p_skeleton->get_bone_parent(p_apply_bone); + if (parent >= 0) { + skel_tr = skel_tr * p_skeleton->get_bone_global_pose(parent); + } + Transform3D dest_tr = nd->get_global_transform_interpolated(); + Transform3D reference_dest = skel_tr.affine_inverse() * dest_tr; + _process_convert(p_index, p_skeleton, p_apply_bone, reference_dest, p_amount); +} + +void ConvertTransformModifier3D::_process_convert(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const Transform3D &p_destination, float p_amount) { + ConvertTransform3DSetting *setting = static_cast(settings[p_index]); + + Transform3D destination = p_destination; // Retrieve point from reference. double point = 0.0; @@ -355,7 +393,7 @@ void ConvertTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_ case TRANSFORM_MODE_POSITION: { if (setting->additive) { point = p_skeleton->get_bone_pose(p_apply_bone).origin[axis] + point; - } else if (setting->relative) { + } else if (setting->is_relative()) { point = p_skeleton->get_bone_rest(p_apply_bone).origin[axis] + point; } destination.origin[axis] = point; @@ -369,7 +407,7 @@ void ConvertTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_ Quaternion rot = Quaternion(rot_axis, point); if (setting->additive) { destination.basis = p_skeleton->get_bone_pose(p_apply_bone).basis.get_rotation_quaternion() * rot; - } else if (setting->relative) { + } else if (setting->is_relative()) { destination.basis = p_skeleton->get_bone_rest(p_apply_bone).basis.get_rotation_quaternion() * rot; } else { destination.basis = rot; @@ -382,7 +420,7 @@ void ConvertTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_ if (setting->additive) { dest_scl = p_skeleton->get_bone_pose(p_apply_bone).basis.get_scale(); dest_scl[axis] = dest_scl[axis] * point; - } else if (setting->relative) { + } else if (setting->is_relative()) { dest_scl = p_skeleton->get_bone_rest(p_apply_bone).basis.get_scale(); dest_scl[axis] = dest_scl[axis] * point; } else { diff --git a/scene/3d/convert_transform_modifier_3d.h b/scene/3d/convert_transform_modifier_3d.h index d4d86360761..cca31779f6c 100644 --- a/scene/3d/convert_transform_modifier_3d.h +++ b/scene/3d/convert_transform_modifier_3d.h @@ -55,16 +55,26 @@ public: bool relative = true; bool additive = false; + + bool is_relative() { + if (reference_type == REFERENCE_TYPE_NODE) { + return false; + } + return relative; + } }; protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); void _get_property_list(List *p_list) const; + void _validate_dynamic_prop(PropertyInfo &p_property) const; static void _bind_methods(); - virtual void _process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) override; + virtual void _process_convert(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const Transform3D &p_destination, float p_amount); virtual void _validate_setting(int p_index) override; public: diff --git a/scene/3d/copy_transform_modifier_3d.cpp b/scene/3d/copy_transform_modifier_3d.cpp index 1f433fe41d9..067bfe68d86 100644 --- a/scene/3d/copy_transform_modifier_3d.cpp +++ b/scene/3d/copy_transform_modifier_3d.cpp @@ -36,7 +36,7 @@ bool CopyTransformModifier3D::_set(const StringName &p_path, const Variant &p_va if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "copy") { set_copy_flags(which, static_cast>((int)p_value)); @@ -61,7 +61,7 @@ bool CopyTransformModifier3D::_get(const StringName &p_path, Variant &r_ret) con if (path.begins_with("settings/")) { int which = path.get_slicec('/', 1).to_int(); String what = path.get_slicec('/', 2); - ERR_FAIL_INDEX_V(which, settings.size(), false); + ERR_FAIL_INDEX_V(which, (int)settings.size(), false); if (what == "copy") { r_ret = (int)get_copy_flags(which); @@ -83,61 +83,78 @@ bool CopyTransformModifier3D::_get(const StringName &p_path, Variant &r_ret) con void CopyTransformModifier3D::_get_property_list(List *p_list) const { BoneConstraint3D::get_property_list(p_list); - for (int i = 0; i < settings.size(); i++) { + LocalVector props; + + for (uint32_t i = 0; i < settings.size(); i++) { String path = "settings/" + itos(i) + "/"; - p_list->push_back(PropertyInfo(Variant::INT, path + "copy", PROPERTY_HINT_FLAGS, "Position,Rotation,Scale")); - p_list->push_back(PropertyInfo(Variant::INT, path + "axes", PROPERTY_HINT_FLAGS, "X,Y,Z")); - p_list->push_back(PropertyInfo(Variant::INT, path + "invert", PROPERTY_HINT_FLAGS, "X,Y,Z")); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "relative")); - p_list->push_back(PropertyInfo(Variant::BOOL, path + "additive")); + props.push_back(PropertyInfo(Variant::INT, path + "copy", PROPERTY_HINT_FLAGS, "Position,Rotation,Scale")); + props.push_back(PropertyInfo(Variant::INT, path + "axes", PROPERTY_HINT_FLAGS, "X,Y,Z")); + props.push_back(PropertyInfo(Variant::INT, path + "invert", PROPERTY_HINT_FLAGS, "X,Y,Z")); + props.push_back(PropertyInfo(Variant::BOOL, path + "relative")); + props.push_back(PropertyInfo(Variant::BOOL, path + "additive")); + } + + for (PropertyInfo &p : props) { + _validate_dynamic_prop(p); + p_list->push_back(p); + } +} + +void CopyTransformModifier3D::_validate_dynamic_prop(PropertyInfo &p_property) const { + PackedStringArray split = p_property.name.split("/"); + if (split.size() > 2 && split[0] == "settings") { + int which = split[1].to_int(); + if (split[2].begins_with("relative") && get_reference_type(which) != REFERENCE_TYPE_BONE) { + p_property.usage = PROPERTY_USAGE_NONE; + } } } void CopyTransformModifier3D::_validate_setting(int p_index) { - settings.write[p_index] = memnew(CopyTransform3DSetting); + settings[p_index] = memnew(CopyTransform3DSetting); } void CopyTransformModifier3D::set_copy_flags(int p_index, BitField p_copy_flags) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); setting->copy_flags = p_copy_flags; notify_property_list_changed(); } BitField CopyTransformModifier3D::get_copy_flags(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->copy_flags; } void CopyTransformModifier3D::set_axis_flags(int p_index, BitField p_axis_flags) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); setting->axis_flags = p_axis_flags; notify_property_list_changed(); } BitField CopyTransformModifier3D::get_axis_flags(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->axis_flags; } void CopyTransformModifier3D::set_invert_flags(int p_index, BitField p_axis_flags) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); setting->invert_flags = p_axis_flags; notify_property_list_changed(); } BitField CopyTransformModifier3D::get_invert_flags(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->invert_flags; } void CopyTransformModifier3D::set_copy_position(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->copy_flags.set_flag(TRANSFORM_FLAG_POSITION); @@ -147,13 +164,13 @@ void CopyTransformModifier3D::set_copy_position(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_position_copying(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->copy_flags.has_flag(TRANSFORM_FLAG_POSITION); } void CopyTransformModifier3D::set_copy_rotation(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->copy_flags.set_flag(TRANSFORM_FLAG_ROTATION); @@ -163,13 +180,13 @@ void CopyTransformModifier3D::set_copy_rotation(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_rotation_copying(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->copy_flags.has_flag(TRANSFORM_FLAG_ROTATION); } void CopyTransformModifier3D::set_copy_scale(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->copy_flags.set_flag(TRANSFORM_FLAG_SCALE); @@ -179,13 +196,13 @@ void CopyTransformModifier3D::set_copy_scale(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_scale_copying(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->copy_flags.has_flag(TRANSFORM_FLAG_SCALE); } void CopyTransformModifier3D::set_axis_x_enabled(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->axis_flags.set_flag(AXIS_FLAG_X); @@ -195,13 +212,13 @@ void CopyTransformModifier3D::set_axis_x_enabled(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_x_enabled(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->axis_flags.has_flag(AXIS_FLAG_X); } void CopyTransformModifier3D::set_axis_y_enabled(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->axis_flags.set_flag(AXIS_FLAG_Y); @@ -211,13 +228,13 @@ void CopyTransformModifier3D::set_axis_y_enabled(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_y_enabled(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->axis_flags.has_flag(AXIS_FLAG_Y); } void CopyTransformModifier3D::set_axis_z_enabled(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->axis_flags.set_flag(AXIS_FLAG_Z); @@ -227,13 +244,13 @@ void CopyTransformModifier3D::set_axis_z_enabled(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_z_enabled(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->axis_flags.has_flag(AXIS_FLAG_Z); } void CopyTransformModifier3D::set_axis_x_inverted(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->invert_flags.set_flag(AXIS_FLAG_X); @@ -243,13 +260,13 @@ void CopyTransformModifier3D::set_axis_x_inverted(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_x_inverted(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->invert_flags.has_flag(AXIS_FLAG_X); } void CopyTransformModifier3D::set_axis_y_inverted(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->invert_flags.set_flag(AXIS_FLAG_Y); @@ -259,13 +276,13 @@ void CopyTransformModifier3D::set_axis_y_inverted(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_y_inverted(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->invert_flags.has_flag(AXIS_FLAG_Y); } void CopyTransformModifier3D::set_axis_z_inverted(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); if (p_enabled) { setting->invert_flags.set_flag(AXIS_FLAG_Z); @@ -275,31 +292,31 @@ void CopyTransformModifier3D::set_axis_z_inverted(int p_index, bool p_enabled) { } bool CopyTransformModifier3D::is_axis_z_inverted(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), false); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->invert_flags.has_flag(AXIS_FLAG_Z); } void CopyTransformModifier3D::set_relative(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); setting->relative = p_enabled; } bool CopyTransformModifier3D::is_relative(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); CopyTransform3DSetting *setting = static_cast(settings[p_index]); - return setting->relative; + return setting->is_relative(); } void CopyTransformModifier3D::set_additive(int p_index, bool p_enabled) { - ERR_FAIL_INDEX(p_index, settings.size()); + ERR_FAIL_INDEX(p_index, (int)settings.size()); CopyTransform3DSetting *setting = static_cast(settings[p_index]); setting->additive = p_enabled; } bool CopyTransformModifier3D::is_additive(int p_index) const { - ERR_FAIL_INDEX_V(p_index, settings.size(), 0); + ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0); CopyTransform3DSetting *setting = static_cast(settings[p_index]); return setting->additive; } @@ -351,16 +368,37 @@ void CopyTransformModifier3D::_bind_methods() { BIND_BITFIELD_FLAG(AXIS_FLAG_ALL); } -void CopyTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { +void CopyTransformModifier3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) { CopyTransform3DSetting *setting = static_cast(settings[p_index]); - Transform3D destination = p_skeleton->get_bone_pose(p_reference_bone); - if (setting->relative) { + if (setting->is_relative()) { Vector3 scl_relative = destination.basis.get_scale() / p_skeleton->get_bone_rest(p_reference_bone).basis.get_scale(); destination.basis = p_skeleton->get_bone_rest(p_reference_bone).basis.get_rotation_quaternion().inverse() * destination.basis.get_rotation_quaternion(); destination.basis.scale_local(scl_relative); destination.origin = destination.origin - p_skeleton->get_bone_rest(p_reference_bone).origin; } + _process_copy(p_index, p_skeleton, p_apply_bone, destination, p_amount); +} + +void CopyTransformModifier3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) { + Node3D *nd = Object::cast_to(get_node_or_null(p_reference_node)); + if (!nd) { + return; + } + Transform3D skel_tr = p_skeleton->get_global_transform_interpolated(); + int parent = p_skeleton->get_bone_parent(p_apply_bone); + if (parent >= 0) { + skel_tr = skel_tr * p_skeleton->get_bone_global_pose(parent); + } + Transform3D dest_tr = nd->get_global_transform_interpolated(); + Transform3D reference_dest = skel_tr.affine_inverse() * dest_tr; + _process_copy(p_index, p_skeleton, p_apply_bone, reference_dest, p_amount); +} + +void CopyTransformModifier3D::_process_copy(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const Transform3D &p_destination, float p_amount) { + CopyTransform3DSetting *setting = static_cast(settings[p_index]); + + Transform3D destination = p_destination; Vector3 dest_pos = destination.origin; Quaternion dest_rot = destination.basis.get_rotation_quaternion(); Vector3 dest_scl = destination.basis.get_scale(); @@ -421,7 +459,7 @@ void CopyTransformModifier3D::_process_constraint(int p_index, Skeleton3D *p_ske destination.origin = p_skeleton->get_bone_pose_position(p_apply_bone) + dest_pos; destination.basis = p_skeleton->get_bone_pose_rotation(p_apply_bone) * Basis(dest_rot); destination.basis.scale_local(p_skeleton->get_bone_pose_scale(p_apply_bone) * dest_scl); - } else if (setting->relative) { + } else if (setting->is_relative()) { Transform3D rest = p_skeleton->get_bone_rest(p_apply_bone); destination.origin = rest.origin + dest_pos; destination.basis = rest.basis.get_rotation_quaternion() * Basis(dest_rot); diff --git a/scene/3d/copy_transform_modifier_3d.h b/scene/3d/copy_transform_modifier_3d.h index 4bdc8b6cc3e..a7749fde048 100644 --- a/scene/3d/copy_transform_modifier_3d.h +++ b/scene/3d/copy_transform_modifier_3d.h @@ -54,18 +54,29 @@ public: BitField copy_flags = TRANSFORM_FLAG_ALL; BitField axis_flags = AXIS_FLAG_ALL; BitField invert_flags = 0; + bool relative = true; bool additive = false; + + bool is_relative() { + if (reference_type == REFERENCE_TYPE_NODE) { + return false; + } + return relative; + } }; protected: bool _get(const StringName &p_path, Variant &r_ret) const; bool _set(const StringName &p_path, const Variant &p_value); void _get_property_list(List *p_list) const; + void _validate_dynamic_prop(PropertyInfo &p_property) const; static void _bind_methods(); - virtual void _process_constraint(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) override; + virtual void _process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) override; + virtual void _process_copy(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const Transform3D &p_destination, float p_amount); virtual void _validate_setting(int p_index) override; public: