Skip to content

Commit a0fef2a

Browse files
committed
Add relative option to LookAt/AimModifier3D
1 parent c680327 commit a0fef2a

File tree

6 files changed

+62
-5
lines changed

6 files changed

+62
-5
lines changed

doc/classes/AimModifier3D.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@
2424
Returns the axis of the first rotation. It is enabled only if [method is_using_euler] is [code]true[/code].
2525
</description>
2626
</method>
27+
<method name="is_relative" qualifiers="const">
28+
<return type="bool" />
29+
<param index="0" name="index" type="int" />
30+
<description>
31+
Returns [code]true[/code] if the relative option is enabled in the setting at [param index].
32+
</description>
33+
</method>
2734
<method name="is_using_euler" qualifiers="const">
2835
<return type="bool" />
2936
<param index="0" name="index" type="int" />
@@ -54,6 +61,16 @@
5461
Sets the axis of the first rotation. It is enabled only if [method is_using_euler] is [code]true[/code].
5562
</description>
5663
</method>
64+
<method name="set_relative">
65+
<return type="void" />
66+
<param index="0" name="index" type="int" />
67+
<param index="1" name="enabled" type="bool" />
68+
<description>
69+
Sets relative option in the setting at [param index] to [param enabled].
70+
If sets [param enabled] to [code]true[/code], the rotation is applied relative to the pose.
71+
If sets [param enabled] to [code]false[/code], the rotation is applied relative to the rest.
72+
</description>
73+
</method>
5774
<method name="set_use_euler">
5875
<return type="void" />
5976
<param index="0" name="index" type="int" />

doc/classes/LookAtModifier3D.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@
9191
<member name="primary_rotation_axis" type="int" setter="set_primary_rotation_axis" getter="get_primary_rotation_axis" enum="Vector3.Axis" default="1">
9292
The axis of the first rotation. This [SkeletonModifier3D] works by compositing the rotation by Euler angles to prevent to rotate the [member forward_axis].
9393
</member>
94+
<member name="relative" type="bool" setter="set_relative" getter="is_relative" default="false">
95+
The relative option. If [code]true[/code], the rotation is applied relative to the pose. If [code]false[/code], the rotation is applied relative to the rest.
96+
</member>
9497
<member name="secondary_damp_threshold" type="float" setter="set_secondary_damp_threshold" getter="get_secondary_damp_threshold">
9598
The threshold to start damping for [member secondary_limit_angle].
9699
</member>

scene/3d/aim_modifier_3d.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ bool AimModifier3D::_set(const StringName &p_path, const Variant &p_value) {
4747
set_primary_rotation_axis(which, static_cast<Vector3::Axis>((int)p_value));
4848
} else if (what == "use_secondary_rotation") {
4949
set_use_secondary_rotation(which, p_value);
50+
} else if (what == "relative") {
51+
set_relative(which, p_value);
5052
} else {
5153
return false;
5254
}
@@ -70,6 +72,8 @@ bool AimModifier3D::_get(const StringName &p_path, Variant &r_ret) const {
7072
r_ret = (int)get_primary_rotation_axis(which);
7173
} else if (what == "use_secondary_rotation") {
7274
r_ret = is_using_secondary_rotation(which);
75+
} else if (what == "relative") {
76+
r_ret = is_relative(which);
7377
} else {
7478
return false;
7579
}
@@ -88,6 +92,7 @@ void AimModifier3D::_get_property_list(List<PropertyInfo> *p_list) const {
8892
p_list->push_back(PropertyInfo(Variant::BOOL, path + "use_euler"));
8993
p_list->push_back(PropertyInfo(Variant::INT, path + "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z", rotation_usage));
9094
p_list->push_back(PropertyInfo(Variant::BOOL, path + "use_secondary_rotation", PROPERTY_HINT_NONE, "", rotation_usage));
95+
p_list->push_back(PropertyInfo(Variant::BOOL, path + "relative"));
9196
}
9297
}
9398

@@ -158,6 +163,18 @@ bool AimModifier3D::is_using_secondary_rotation(int p_index) const {
158163
return setting->use_secondary_rotation;
159164
}
160165

166+
void AimModifier3D::set_relative(int p_index, bool p_enabled) {
167+
ERR_FAIL_INDEX(p_index, settings.size());
168+
AimModifier3DSetting *setting = static_cast<AimModifier3DSetting *>(settings[p_index]);
169+
setting->relative = p_enabled;
170+
}
171+
172+
bool AimModifier3D::is_relative(int p_index) const {
173+
ERR_FAIL_INDEX_V(p_index, settings.size(), 0);
174+
AimModifier3DSetting *setting = static_cast<AimModifier3DSetting *>(settings[p_index]);
175+
return setting->relative;
176+
}
177+
161178
void AimModifier3D::_bind_methods() {
162179
ClassDB::bind_method(D_METHOD("set_forward_axis", "index", "axis"), &AimModifier3D::set_forward_axis);
163180
ClassDB::bind_method(D_METHOD("get_forward_axis", "index"), &AimModifier3D::get_forward_axis);
@@ -167,6 +184,8 @@ void AimModifier3D::_bind_methods() {
167184
ClassDB::bind_method(D_METHOD("get_primary_rotation_axis", "index"), &AimModifier3D::get_primary_rotation_axis);
168185
ClassDB::bind_method(D_METHOD("set_use_secondary_rotation", "index", "enabled"), &AimModifier3D::set_use_secondary_rotation);
169186
ClassDB::bind_method(D_METHOD("is_using_secondary_rotation", "index"), &AimModifier3D::is_using_secondary_rotation);
187+
ClassDB::bind_method(D_METHOD("set_relative", "index", "enabled"), &AimModifier3D::set_relative);
188+
ClassDB::bind_method(D_METHOD("is_relative", "index"), &AimModifier3D::is_relative);
170189

171190
ADD_ARRAY_COUNT("Settings", "setting_count", "set_setting_count", "get_setting_count", "settings/");
172191
}
@@ -193,7 +212,7 @@ void AimModifier3D::_process_aim(int p_index, Skeleton3D *p_skeleton, int p_appl
193212
AimModifier3DSetting *setting = static_cast<AimModifier3DSetting *>(settings[p_index]);
194213

195214
// Prepare forward_vector and rest.
196-
Transform3D src_bone_rest = p_skeleton->get_bone_rest(p_apply_bone);
215+
Transform3D src_bone_rest = setting->relative ? p_skeleton->get_bone_pose(p_apply_bone) : p_skeleton->get_bone_rest(p_apply_bone);
197216
Transform3D bone_rest_space;
198217
int parent_bone = p_skeleton->get_bone_parent(p_apply_bone);
199218
if (parent_bone < 0) {

scene/3d/aim_modifier_3d.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class AimModifier3D : public BoneConstraint3D {
4141
bool use_euler = false;
4242
Vector3::Axis primary_rotation_axis = Vector3::AXIS_X;
4343
bool use_secondary_rotation = true;
44+
bool relative = false;
4445
};
4546

4647
protected:
@@ -65,6 +66,8 @@ class AimModifier3D : public BoneConstraint3D {
6566
Vector3::Axis get_primary_rotation_axis(int p_index) const;
6667
void set_use_secondary_rotation(int p_index, bool p_enabled);
6768
bool is_using_secondary_rotation(int p_index) const;
69+
void set_relative(int p_index, bool p_enabled);
70+
bool is_relative(int p_index) const;
6871

6972
~AimModifier3D();
7073
};

scene/3d/look_at_modifier_3d.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ bool LookAtModifier3D::is_using_secondary_rotation() const {
143143
return use_secondary_rotation;
144144
}
145145

146+
void LookAtModifier3D::set_relative(bool p_enabled) {
147+
relative = p_enabled;
148+
}
149+
150+
bool LookAtModifier3D::is_relative() const {
151+
return relative;
152+
}
153+
146154
void LookAtModifier3D::set_target_node(const NodePath &p_target_node) {
147155
if (target_node != p_target_node) {
148156
init_transition();
@@ -394,9 +402,11 @@ void LookAtModifier3D::_bind_methods() {
394402
ClassDB::bind_method(D_METHOD("get_primary_rotation_axis"), &LookAtModifier3D::get_primary_rotation_axis);
395403
ClassDB::bind_method(D_METHOD("set_use_secondary_rotation", "enabled"), &LookAtModifier3D::set_use_secondary_rotation);
396404
ClassDB::bind_method(D_METHOD("is_using_secondary_rotation"), &LookAtModifier3D::is_using_secondary_rotation);
405+
ClassDB::bind_method(D_METHOD("set_relative", "enabled"), &LookAtModifier3D::set_relative);
406+
ClassDB::bind_method(D_METHOD("is_relative"), &LookAtModifier3D::is_relative);
407+
397408
ClassDB::bind_method(D_METHOD("set_origin_safe_margin", "margin"), &LookAtModifier3D::set_origin_safe_margin);
398409
ClassDB::bind_method(D_METHOD("get_origin_safe_margin"), &LookAtModifier3D::get_origin_safe_margin);
399-
400410
ClassDB::bind_method(D_METHOD("set_origin_from", "origin_from"), &LookAtModifier3D::set_origin_from);
401411
ClassDB::bind_method(D_METHOD("get_origin_from"), &LookAtModifier3D::get_origin_from);
402412
ClassDB::bind_method(D_METHOD("set_origin_bone_name", "bone_name"), &LookAtModifier3D::set_origin_bone_name);
@@ -460,6 +470,7 @@ void LookAtModifier3D::_bind_methods() {
460470
ADD_PROPERTY(PropertyInfo(Variant::INT, "forward_axis", PROPERTY_HINT_ENUM, SkeletonModifier3D::get_hint_bone_axis()), "set_forward_axis", "get_forward_axis");
461471
ADD_PROPERTY(PropertyInfo(Variant::INT, "primary_rotation_axis", PROPERTY_HINT_ENUM, "X,Y,Z"), "set_primary_rotation_axis", "get_primary_rotation_axis");
462472
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_secondary_rotation"), "set_use_secondary_rotation", "is_using_secondary_rotation");
473+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "relative"), "set_relative", "is_relative");
463474

464475
ADD_GROUP("Origin Settings", "origin_");
465476
ADD_PROPERTY(PropertyInfo(Variant::INT, "origin_from", PROPERTY_HINT_ENUM, "Self,SpecificBone,ExternalNode"), "set_origin_from", "get_origin_from");
@@ -506,14 +517,15 @@ void LookAtModifier3D::_process_modification(double p_delta) {
506517
}
507518

508519
// Calculate bone rest space in the world.
520+
Transform3D bone_rest = relative ? skeleton->get_bone_pose(bone) : skeleton->get_bone_rest(bone);
509521
Transform3D bone_rest_space;
510522
int parent_bone = skeleton->get_bone_parent(bone);
511523
if (parent_bone < 0) {
512524
bone_rest_space = skeleton->get_global_transform_interpolated();
513-
bone_rest_space.translate_local(skeleton->get_bone_rest(bone).origin);
525+
bone_rest_space.translate_local(bone_rest.origin);
514526
} else {
515527
bone_rest_space = skeleton->get_global_transform_interpolated() * skeleton->get_bone_global_pose(parent_bone);
516-
bone_rest_space.translate_local(skeleton->get_bone_rest(bone).origin);
528+
bone_rest_space.translate_local(bone_rest.origin);
517529
}
518530

519531
// Calculate forward_vector and destination.
@@ -543,7 +555,7 @@ void LookAtModifier3D::_process_modification(double p_delta) {
543555
destination = skeleton->get_bone_pose_rotation(bone);
544556
forward_vector = Vector3(0, 0, 0); // The zero-vector to be used for checking in the line immediately below to avoid animation glitch.
545557
} else {
546-
destination = look_at_with_axes(skeleton->get_bone_rest(bone)).basis.get_rotation_quaternion();
558+
destination = look_at_with_axes(bone_rest).basis.get_rotation_quaternion();
547559
}
548560
}
549561

scene/3d/look_at_modifier_3d.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class LookAtModifier3D : public SkeletonModifier3D {
5353
Vector3::Axis primary_rotation_axis = Vector3::AXIS_Y;
5454
Vector3::Axis secondary_rotation_axis = Vector3::AXIS_X;
5555
bool use_secondary_rotation = true;
56+
bool relative = false;
5657

5758
OriginFrom origin_from = ORIGIN_FROM_SELF;
5859
String origin_bone_name;
@@ -123,6 +124,8 @@ class LookAtModifier3D : public SkeletonModifier3D {
123124
Vector3::Axis get_primary_rotation_axis() const;
124125
void set_use_secondary_rotation(bool p_enabled);
125126
bool is_using_secondary_rotation() const;
127+
void set_relative(bool p_enabled);
128+
bool is_relative() const;
126129

127130
void set_origin_from(OriginFrom p_origin_from);
128131
OriginFrom get_origin_from() const;

0 commit comments

Comments
 (0)