1 | /**************************************************************************/ |
2 | /* skeleton_modification_2d_jiggle.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "skeleton_modification_2d_jiggle.h" |
32 | |
33 | #include "scene/2d/skeleton_2d.h" |
34 | #include "scene/resources/world_2d.h" |
35 | |
36 | bool SkeletonModification2DJiggle::_set(const StringName &p_path, const Variant &p_value) { |
37 | String path = p_path; |
38 | |
39 | if (path.begins_with("joint_data/" )) { |
40 | int which = path.get_slicec('/', 1).to_int(); |
41 | String what = path.get_slicec('/', 2); |
42 | ERR_FAIL_INDEX_V(which, jiggle_data_chain.size(), false); |
43 | |
44 | if (what == "bone2d_node" ) { |
45 | set_jiggle_joint_bone2d_node(which, p_value); |
46 | } else if (what == "bone_index" ) { |
47 | set_jiggle_joint_bone_index(which, p_value); |
48 | } else if (what == "override_defaults" ) { |
49 | set_jiggle_joint_override(which, p_value); |
50 | } else if (what == "stiffness" ) { |
51 | set_jiggle_joint_stiffness(which, p_value); |
52 | } else if (what == "mass" ) { |
53 | set_jiggle_joint_mass(which, p_value); |
54 | } else if (what == "damping" ) { |
55 | set_jiggle_joint_damping(which, p_value); |
56 | } else if (what == "use_gravity" ) { |
57 | set_jiggle_joint_use_gravity(which, p_value); |
58 | } else if (what == "gravity" ) { |
59 | set_jiggle_joint_gravity(which, p_value); |
60 | } |
61 | return true; |
62 | } else { |
63 | if (path == "use_colliders" ) { |
64 | set_use_colliders(p_value); |
65 | } else if (path == "collision_mask" ) { |
66 | set_collision_mask(p_value); |
67 | } |
68 | } |
69 | return true; |
70 | } |
71 | |
72 | bool SkeletonModification2DJiggle::_get(const StringName &p_path, Variant &r_ret) const { |
73 | String path = p_path; |
74 | |
75 | if (path.begins_with("joint_data/" )) { |
76 | int which = path.get_slicec('/', 1).to_int(); |
77 | String what = path.get_slicec('/', 2); |
78 | ERR_FAIL_INDEX_V(which, jiggle_data_chain.size(), false); |
79 | |
80 | if (what == "bone2d_node" ) { |
81 | r_ret = get_jiggle_joint_bone2d_node(which); |
82 | } else if (what == "bone_index" ) { |
83 | r_ret = get_jiggle_joint_bone_index(which); |
84 | } else if (what == "override_defaults" ) { |
85 | r_ret = get_jiggle_joint_override(which); |
86 | } else if (what == "stiffness" ) { |
87 | r_ret = get_jiggle_joint_stiffness(which); |
88 | } else if (what == "mass" ) { |
89 | r_ret = get_jiggle_joint_mass(which); |
90 | } else if (what == "damping" ) { |
91 | r_ret = get_jiggle_joint_damping(which); |
92 | } else if (what == "use_gravity" ) { |
93 | r_ret = get_jiggle_joint_use_gravity(which); |
94 | } else if (what == "gravity" ) { |
95 | r_ret = get_jiggle_joint_gravity(which); |
96 | } |
97 | return true; |
98 | } else { |
99 | if (path == "use_colliders" ) { |
100 | r_ret = get_use_colliders(); |
101 | } else if (path == "collision_mask" ) { |
102 | r_ret = get_collision_mask(); |
103 | } |
104 | } |
105 | return true; |
106 | } |
107 | |
108 | void SkeletonModification2DJiggle::_get_property_list(List<PropertyInfo> *p_list) const { |
109 | p_list->push_back(PropertyInfo(Variant::BOOL, "use_colliders" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_DEFAULT)); |
110 | if (use_colliders) { |
111 | p_list->push_back(PropertyInfo(Variant::INT, "collision_mask" , PROPERTY_HINT_LAYERS_2D_PHYSICS, "" , PROPERTY_USAGE_DEFAULT)); |
112 | } |
113 | |
114 | for (int i = 0; i < jiggle_data_chain.size(); i++) { |
115 | String base_string = "joint_data/" + itos(i) + "/" ; |
116 | |
117 | p_list->push_back(PropertyInfo(Variant::INT, base_string + "bone_index" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_DEFAULT)); |
118 | p_list->push_back(PropertyInfo(Variant::NODE_PATH, base_string + "bone2d_node" , PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D" , PROPERTY_USAGE_DEFAULT)); |
119 | p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "override_defaults" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_DEFAULT)); |
120 | |
121 | if (jiggle_data_chain[i].override_defaults) { |
122 | p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "stiffness" , PROPERTY_HINT_RANGE, "0, 1000, 0.01" , PROPERTY_USAGE_DEFAULT)); |
123 | p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "mass" , PROPERTY_HINT_RANGE, "0, 1000, 0.01" , PROPERTY_USAGE_DEFAULT)); |
124 | p_list->push_back(PropertyInfo(Variant::FLOAT, base_string + "damping" , PROPERTY_HINT_RANGE, "0, 1, 0.01" , PROPERTY_USAGE_DEFAULT)); |
125 | p_list->push_back(PropertyInfo(Variant::BOOL, base_string + "use_gravity" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_DEFAULT)); |
126 | if (jiggle_data_chain[i].use_gravity) { |
127 | p_list->push_back(PropertyInfo(Variant::VECTOR2, base_string + "gravity" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_DEFAULT)); |
128 | } |
129 | } |
130 | } |
131 | } |
132 | |
133 | void SkeletonModification2DJiggle::_execute(float p_delta) { |
134 | ERR_FAIL_COND_MSG(!stack || !is_setup || stack->skeleton == nullptr, |
135 | "Modification is not setup and therefore cannot execute!" ); |
136 | if (!enabled) { |
137 | return; |
138 | } |
139 | if (target_node_cache.is_null()) { |
140 | WARN_PRINT_ONCE("Target cache is out of date. Attempting to update..." ); |
141 | update_target_cache(); |
142 | return; |
143 | } |
144 | Node2D *target = Object::cast_to<Node2D>(ObjectDB::get_instance(target_node_cache)); |
145 | if (!target || !target->is_inside_tree()) { |
146 | ERR_PRINT_ONCE("Target node is not in the scene tree. Cannot execute modification!" ); |
147 | return; |
148 | } |
149 | |
150 | for (int i = 0; i < jiggle_data_chain.size(); i++) { |
151 | _execute_jiggle_joint(i, target, p_delta); |
152 | } |
153 | } |
154 | |
155 | void SkeletonModification2DJiggle::_execute_jiggle_joint(int p_joint_idx, Node2D *p_target, float p_delta) { |
156 | // Adopted from: https://wiki.unity3d.com/index.php/JiggleBone |
157 | // With modifications by TwistedTwigleg. |
158 | |
159 | if (jiggle_data_chain[p_joint_idx].bone_idx <= -1 || jiggle_data_chain[p_joint_idx].bone_idx > stack->skeleton->get_bone_count()) { |
160 | ERR_PRINT_ONCE("Jiggle joint " + itos(p_joint_idx) + " bone index is invalid. Cannot execute modification on joint..." ); |
161 | return; |
162 | } |
163 | |
164 | if (jiggle_data_chain[p_joint_idx].bone2d_node_cache.is_null() && !jiggle_data_chain[p_joint_idx].bone2d_node.is_empty()) { |
165 | WARN_PRINT_ONCE("Bone2D cache for joint " + itos(p_joint_idx) + " is out of date. Updating..." ); |
166 | jiggle_joint_update_bone2d_cache(p_joint_idx); |
167 | } |
168 | |
169 | Bone2D *operation_bone = stack->skeleton->get_bone(jiggle_data_chain[p_joint_idx].bone_idx); |
170 | if (!operation_bone) { |
171 | ERR_PRINT_ONCE("Jiggle joint " + itos(p_joint_idx) + " does not have a Bone2D node or it cannot be found!" ); |
172 | return; |
173 | } |
174 | |
175 | Transform2D operation_bone_trans = operation_bone->get_global_transform(); |
176 | Vector2 target_position = p_target->get_global_position(); |
177 | |
178 | jiggle_data_chain.write[p_joint_idx].force = (target_position - jiggle_data_chain[p_joint_idx].dynamic_position) * jiggle_data_chain[p_joint_idx].stiffness * p_delta; |
179 | |
180 | if (jiggle_data_chain[p_joint_idx].use_gravity) { |
181 | jiggle_data_chain.write[p_joint_idx].force += jiggle_data_chain[p_joint_idx].gravity * p_delta; |
182 | } |
183 | |
184 | jiggle_data_chain.write[p_joint_idx].acceleration = jiggle_data_chain[p_joint_idx].force / jiggle_data_chain[p_joint_idx].mass; |
185 | jiggle_data_chain.write[p_joint_idx].velocity += jiggle_data_chain[p_joint_idx].acceleration * (1 - jiggle_data_chain[p_joint_idx].damping); |
186 | |
187 | jiggle_data_chain.write[p_joint_idx].dynamic_position += jiggle_data_chain[p_joint_idx].velocity + jiggle_data_chain[p_joint_idx].force; |
188 | jiggle_data_chain.write[p_joint_idx].dynamic_position += operation_bone_trans.get_origin() - jiggle_data_chain[p_joint_idx].last_position; |
189 | jiggle_data_chain.write[p_joint_idx].last_position = operation_bone_trans.get_origin(); |
190 | |
191 | // Collision detection/response |
192 | if (use_colliders) { |
193 | if (execution_mode == SkeletonModificationStack2D::EXECUTION_MODE::execution_mode_physics_process) { |
194 | Ref<World2D> world_2d = stack->skeleton->get_world_2d(); |
195 | ERR_FAIL_COND(world_2d.is_null()); |
196 | PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space()); |
197 | PhysicsDirectSpaceState2D::RayResult ray_result; |
198 | |
199 | PhysicsDirectSpaceState2D::RayParameters ray_params; |
200 | ray_params.from = operation_bone_trans.get_origin(); |
201 | ray_params.to = jiggle_data_chain[p_joint_idx].dynamic_position; |
202 | ray_params.collision_mask = collision_mask; |
203 | |
204 | // Add exception support? |
205 | bool ray_hit = space_state->intersect_ray(ray_params, ray_result); |
206 | |
207 | if (ray_hit) { |
208 | jiggle_data_chain.write[p_joint_idx].dynamic_position = jiggle_data_chain[p_joint_idx].last_noncollision_position; |
209 | jiggle_data_chain.write[p_joint_idx].acceleration = Vector2(0, 0); |
210 | jiggle_data_chain.write[p_joint_idx].velocity = Vector2(0, 0); |
211 | } else { |
212 | jiggle_data_chain.write[p_joint_idx].last_noncollision_position = jiggle_data_chain[p_joint_idx].dynamic_position; |
213 | } |
214 | } else { |
215 | WARN_PRINT_ONCE("Jiggle 2D modifier: You cannot detect colliders without the stack mode being set to _physics_process!" ); |
216 | } |
217 | } |
218 | |
219 | // Rotate the bone using the dynamic position! |
220 | operation_bone_trans = operation_bone_trans.looking_at(jiggle_data_chain[p_joint_idx].dynamic_position); |
221 | operation_bone_trans.set_rotation(operation_bone_trans.get_rotation() - operation_bone->get_bone_angle()); |
222 | |
223 | // Reset scale |
224 | operation_bone_trans.set_scale(operation_bone->get_global_scale()); |
225 | |
226 | operation_bone->set_global_transform(operation_bone_trans); |
227 | stack->skeleton->set_bone_local_pose_override(jiggle_data_chain[p_joint_idx].bone_idx, operation_bone->get_transform(), stack->strength, true); |
228 | } |
229 | |
230 | void SkeletonModification2DJiggle::_update_jiggle_joint_data() { |
231 | for (int i = 0; i < jiggle_data_chain.size(); i++) { |
232 | if (!jiggle_data_chain[i].override_defaults) { |
233 | set_jiggle_joint_stiffness(i, stiffness); |
234 | set_jiggle_joint_mass(i, mass); |
235 | set_jiggle_joint_damping(i, damping); |
236 | set_jiggle_joint_use_gravity(i, use_gravity); |
237 | set_jiggle_joint_gravity(i, gravity); |
238 | } |
239 | } |
240 | } |
241 | |
242 | void SkeletonModification2DJiggle::_setup_modification(SkeletonModificationStack2D *p_stack) { |
243 | stack = p_stack; |
244 | |
245 | if (stack) { |
246 | is_setup = true; |
247 | |
248 | if (stack->skeleton) { |
249 | for (int i = 0; i < jiggle_data_chain.size(); i++) { |
250 | int bone_idx = jiggle_data_chain[i].bone_idx; |
251 | if (bone_idx > 0 && bone_idx < stack->skeleton->get_bone_count()) { |
252 | Bone2D *bone2d_node = stack->skeleton->get_bone(bone_idx); |
253 | jiggle_data_chain.write[i].dynamic_position = bone2d_node->get_global_position(); |
254 | } |
255 | } |
256 | } |
257 | |
258 | update_target_cache(); |
259 | } |
260 | } |
261 | |
262 | void SkeletonModification2DJiggle::update_target_cache() { |
263 | if (!is_setup || !stack) { |
264 | ERR_PRINT_ONCE("Cannot update target cache: modification is not properly setup!" ); |
265 | return; |
266 | } |
267 | |
268 | target_node_cache = ObjectID(); |
269 | if (stack->skeleton) { |
270 | if (stack->skeleton->is_inside_tree()) { |
271 | if (stack->skeleton->has_node(target_node)) { |
272 | Node *node = stack->skeleton->get_node(target_node); |
273 | ERR_FAIL_COND_MSG(!node || stack->skeleton == node, |
274 | "Cannot update target cache: node is this modification's skeleton or cannot be found!" ); |
275 | ERR_FAIL_COND_MSG(!node->is_inside_tree(), |
276 | "Cannot update target cache: node is not in scene tree!" ); |
277 | target_node_cache = node->get_instance_id(); |
278 | } |
279 | } |
280 | } |
281 | } |
282 | |
283 | void SkeletonModification2DJiggle::jiggle_joint_update_bone2d_cache(int p_joint_idx) { |
284 | ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Cannot update bone2d cache: joint index out of range!" ); |
285 | if (!is_setup || !stack) { |
286 | ERR_PRINT_ONCE("Cannot update Jiggle " + itos(p_joint_idx) + " Bone2D cache: modification is not properly setup!" ); |
287 | return; |
288 | } |
289 | |
290 | jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = ObjectID(); |
291 | if (stack->skeleton) { |
292 | if (stack->skeleton->is_inside_tree()) { |
293 | if (stack->skeleton->has_node(jiggle_data_chain[p_joint_idx].bone2d_node)) { |
294 | Node *node = stack->skeleton->get_node(jiggle_data_chain[p_joint_idx].bone2d_node); |
295 | ERR_FAIL_COND_MSG(!node || stack->skeleton == node, |
296 | "Cannot update Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: node is this modification's skeleton or cannot be found!" ); |
297 | ERR_FAIL_COND_MSG(!node->is_inside_tree(), |
298 | "Cannot update Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: node is not in scene tree!" ); |
299 | jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = node->get_instance_id(); |
300 | |
301 | Bone2D *bone = Object::cast_to<Bone2D>(node); |
302 | if (bone) { |
303 | jiggle_data_chain.write[p_joint_idx].bone_idx = bone->get_index_in_skeleton(); |
304 | } else { |
305 | ERR_FAIL_MSG("Jiggle joint " + itos(p_joint_idx) + " Bone2D cache: Nodepath to Bone2D is not a Bone2D node!" ); |
306 | } |
307 | } |
308 | } |
309 | } |
310 | } |
311 | |
312 | void SkeletonModification2DJiggle::set_target_node(const NodePath &p_target_node) { |
313 | target_node = p_target_node; |
314 | update_target_cache(); |
315 | } |
316 | |
317 | NodePath SkeletonModification2DJiggle::get_target_node() const { |
318 | return target_node; |
319 | } |
320 | |
321 | void SkeletonModification2DJiggle::set_stiffness(float p_stiffness) { |
322 | ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!" ); |
323 | stiffness = p_stiffness; |
324 | _update_jiggle_joint_data(); |
325 | } |
326 | |
327 | float SkeletonModification2DJiggle::get_stiffness() const { |
328 | return stiffness; |
329 | } |
330 | |
331 | void SkeletonModification2DJiggle::set_mass(float p_mass) { |
332 | ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!" ); |
333 | mass = p_mass; |
334 | _update_jiggle_joint_data(); |
335 | } |
336 | |
337 | float SkeletonModification2DJiggle::get_mass() const { |
338 | return mass; |
339 | } |
340 | |
341 | void SkeletonModification2DJiggle::set_damping(float p_damping) { |
342 | ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!" ); |
343 | ERR_FAIL_COND_MSG(p_damping > 1, "Damping cannot be more than one!" ); |
344 | damping = p_damping; |
345 | _update_jiggle_joint_data(); |
346 | } |
347 | |
348 | float SkeletonModification2DJiggle::get_damping() const { |
349 | return damping; |
350 | } |
351 | |
352 | void SkeletonModification2DJiggle::set_use_gravity(bool p_use_gravity) { |
353 | use_gravity = p_use_gravity; |
354 | _update_jiggle_joint_data(); |
355 | } |
356 | |
357 | bool SkeletonModification2DJiggle::get_use_gravity() const { |
358 | return use_gravity; |
359 | } |
360 | |
361 | void SkeletonModification2DJiggle::set_gravity(Vector2 p_gravity) { |
362 | gravity = p_gravity; |
363 | _update_jiggle_joint_data(); |
364 | } |
365 | |
366 | Vector2 SkeletonModification2DJiggle::get_gravity() const { |
367 | return gravity; |
368 | } |
369 | |
370 | void SkeletonModification2DJiggle::set_use_colliders(bool p_use_colliders) { |
371 | use_colliders = p_use_colliders; |
372 | notify_property_list_changed(); |
373 | } |
374 | |
375 | bool SkeletonModification2DJiggle::get_use_colliders() const { |
376 | return use_colliders; |
377 | } |
378 | |
379 | void SkeletonModification2DJiggle::set_collision_mask(int p_mask) { |
380 | collision_mask = p_mask; |
381 | } |
382 | |
383 | int SkeletonModification2DJiggle::get_collision_mask() const { |
384 | return collision_mask; |
385 | } |
386 | |
387 | // Jiggle joint data functions |
388 | int SkeletonModification2DJiggle::get_jiggle_data_chain_length() { |
389 | return jiggle_data_chain.size(); |
390 | } |
391 | |
392 | void SkeletonModification2DJiggle::set_jiggle_data_chain_length(int p_length) { |
393 | ERR_FAIL_COND(p_length < 0); |
394 | jiggle_data_chain.resize(p_length); |
395 | notify_property_list_changed(); |
396 | } |
397 | |
398 | void SkeletonModification2DJiggle::set_jiggle_joint_bone2d_node(int p_joint_idx, const NodePath &p_target_node) { |
399 | ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Jiggle joint out of range!" ); |
400 | jiggle_data_chain.write[p_joint_idx].bone2d_node = p_target_node; |
401 | jiggle_joint_update_bone2d_cache(p_joint_idx); |
402 | |
403 | notify_property_list_changed(); |
404 | } |
405 | |
406 | NodePath SkeletonModification2DJiggle::get_jiggle_joint_bone2d_node(int p_joint_idx) const { |
407 | ERR_FAIL_INDEX_V_MSG(p_joint_idx, jiggle_data_chain.size(), NodePath(), "Jiggle joint out of range!" ); |
408 | return jiggle_data_chain[p_joint_idx].bone2d_node; |
409 | } |
410 | |
411 | void SkeletonModification2DJiggle::set_jiggle_joint_bone_index(int p_joint_idx, int p_bone_idx) { |
412 | ERR_FAIL_INDEX_MSG(p_joint_idx, jiggle_data_chain.size(), "Jiggle joint out of range!" ); |
413 | ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!" ); |
414 | |
415 | if (is_setup) { |
416 | if (stack->skeleton) { |
417 | ERR_FAIL_INDEX_MSG(p_bone_idx, stack->skeleton->get_bone_count(), "Passed-in Bone index is out of range!" ); |
418 | jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx; |
419 | jiggle_data_chain.write[p_joint_idx].bone2d_node_cache = stack->skeleton->get_bone(p_bone_idx)->get_instance_id(); |
420 | jiggle_data_chain.write[p_joint_idx].bone2d_node = stack->skeleton->get_path_to(stack->skeleton->get_bone(p_bone_idx)); |
421 | } else { |
422 | WARN_PRINT("Cannot verify the Jiggle joint " + itos(p_joint_idx) + " bone index for this modification..." ); |
423 | jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx; |
424 | } |
425 | } else { |
426 | WARN_PRINT("Cannot verify the Jiggle joint " + itos(p_joint_idx) + " bone index for this modification..." ); |
427 | jiggle_data_chain.write[p_joint_idx].bone_idx = p_bone_idx; |
428 | } |
429 | |
430 | notify_property_list_changed(); |
431 | } |
432 | |
433 | int SkeletonModification2DJiggle::get_jiggle_joint_bone_index(int p_joint_idx) const { |
434 | ERR_FAIL_INDEX_V_MSG(p_joint_idx, jiggle_data_chain.size(), -1, "Jiggle joint out of range!" ); |
435 | return jiggle_data_chain[p_joint_idx].bone_idx; |
436 | } |
437 | |
438 | void SkeletonModification2DJiggle::set_jiggle_joint_override(int p_joint_idx, bool p_override) { |
439 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
440 | jiggle_data_chain.write[p_joint_idx].override_defaults = p_override; |
441 | _update_jiggle_joint_data(); |
442 | notify_property_list_changed(); |
443 | } |
444 | |
445 | bool SkeletonModification2DJiggle::get_jiggle_joint_override(int p_joint_idx) const { |
446 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), false); |
447 | return jiggle_data_chain[p_joint_idx].override_defaults; |
448 | } |
449 | |
450 | void SkeletonModification2DJiggle::set_jiggle_joint_stiffness(int p_joint_idx, float p_stiffness) { |
451 | ERR_FAIL_COND_MSG(p_stiffness < 0, "Stiffness cannot be set to a negative value!" ); |
452 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
453 | jiggle_data_chain.write[p_joint_idx].stiffness = p_stiffness; |
454 | } |
455 | |
456 | float SkeletonModification2DJiggle::get_jiggle_joint_stiffness(int p_joint_idx) const { |
457 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1); |
458 | return jiggle_data_chain[p_joint_idx].stiffness; |
459 | } |
460 | |
461 | void SkeletonModification2DJiggle::set_jiggle_joint_mass(int p_joint_idx, float p_mass) { |
462 | ERR_FAIL_COND_MSG(p_mass < 0, "Mass cannot be set to a negative value!" ); |
463 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
464 | jiggle_data_chain.write[p_joint_idx].mass = p_mass; |
465 | } |
466 | |
467 | float SkeletonModification2DJiggle::get_jiggle_joint_mass(int p_joint_idx) const { |
468 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1); |
469 | return jiggle_data_chain[p_joint_idx].mass; |
470 | } |
471 | |
472 | void SkeletonModification2DJiggle::set_jiggle_joint_damping(int p_joint_idx, float p_damping) { |
473 | ERR_FAIL_COND_MSG(p_damping < 0, "Damping cannot be set to a negative value!" ); |
474 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
475 | jiggle_data_chain.write[p_joint_idx].damping = p_damping; |
476 | } |
477 | |
478 | float SkeletonModification2DJiggle::get_jiggle_joint_damping(int p_joint_idx) const { |
479 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), -1); |
480 | return jiggle_data_chain[p_joint_idx].damping; |
481 | } |
482 | |
483 | void SkeletonModification2DJiggle::set_jiggle_joint_use_gravity(int p_joint_idx, bool p_use_gravity) { |
484 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
485 | jiggle_data_chain.write[p_joint_idx].use_gravity = p_use_gravity; |
486 | notify_property_list_changed(); |
487 | } |
488 | |
489 | bool SkeletonModification2DJiggle::get_jiggle_joint_use_gravity(int p_joint_idx) const { |
490 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), false); |
491 | return jiggle_data_chain[p_joint_idx].use_gravity; |
492 | } |
493 | |
494 | void SkeletonModification2DJiggle::set_jiggle_joint_gravity(int p_joint_idx, Vector2 p_gravity) { |
495 | ERR_FAIL_INDEX(p_joint_idx, jiggle_data_chain.size()); |
496 | jiggle_data_chain.write[p_joint_idx].gravity = p_gravity; |
497 | } |
498 | |
499 | Vector2 SkeletonModification2DJiggle::get_jiggle_joint_gravity(int p_joint_idx) const { |
500 | ERR_FAIL_INDEX_V(p_joint_idx, jiggle_data_chain.size(), Vector2(0, 0)); |
501 | return jiggle_data_chain[p_joint_idx].gravity; |
502 | } |
503 | |
504 | void SkeletonModification2DJiggle::_bind_methods() { |
505 | ClassDB::bind_method(D_METHOD("set_target_node" , "target_nodepath" ), &SkeletonModification2DJiggle::set_target_node); |
506 | ClassDB::bind_method(D_METHOD("get_target_node" ), &SkeletonModification2DJiggle::get_target_node); |
507 | |
508 | ClassDB::bind_method(D_METHOD("set_jiggle_data_chain_length" , "length" ), &SkeletonModification2DJiggle::set_jiggle_data_chain_length); |
509 | ClassDB::bind_method(D_METHOD("get_jiggle_data_chain_length" ), &SkeletonModification2DJiggle::get_jiggle_data_chain_length); |
510 | |
511 | ClassDB::bind_method(D_METHOD("set_stiffness" , "stiffness" ), &SkeletonModification2DJiggle::set_stiffness); |
512 | ClassDB::bind_method(D_METHOD("get_stiffness" ), &SkeletonModification2DJiggle::get_stiffness); |
513 | ClassDB::bind_method(D_METHOD("set_mass" , "mass" ), &SkeletonModification2DJiggle::set_mass); |
514 | ClassDB::bind_method(D_METHOD("get_mass" ), &SkeletonModification2DJiggle::get_mass); |
515 | ClassDB::bind_method(D_METHOD("set_damping" , "damping" ), &SkeletonModification2DJiggle::set_damping); |
516 | ClassDB::bind_method(D_METHOD("get_damping" ), &SkeletonModification2DJiggle::get_damping); |
517 | ClassDB::bind_method(D_METHOD("set_use_gravity" , "use_gravity" ), &SkeletonModification2DJiggle::set_use_gravity); |
518 | ClassDB::bind_method(D_METHOD("get_use_gravity" ), &SkeletonModification2DJiggle::get_use_gravity); |
519 | ClassDB::bind_method(D_METHOD("set_gravity" , "gravity" ), &SkeletonModification2DJiggle::set_gravity); |
520 | ClassDB::bind_method(D_METHOD("get_gravity" ), &SkeletonModification2DJiggle::get_gravity); |
521 | |
522 | ClassDB::bind_method(D_METHOD("set_use_colliders" , "use_colliders" ), &SkeletonModification2DJiggle::set_use_colliders); |
523 | ClassDB::bind_method(D_METHOD("get_use_colliders" ), &SkeletonModification2DJiggle::get_use_colliders); |
524 | ClassDB::bind_method(D_METHOD("set_collision_mask" , "collision_mask" ), &SkeletonModification2DJiggle::set_collision_mask); |
525 | ClassDB::bind_method(D_METHOD("get_collision_mask" ), &SkeletonModification2DJiggle::get_collision_mask); |
526 | |
527 | // Jiggle joint data functions |
528 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone2d_node" , "joint_idx" , "bone2d_node" ), &SkeletonModification2DJiggle::set_jiggle_joint_bone2d_node); |
529 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone2d_node" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_bone2d_node); |
530 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_bone_index" , "joint_idx" , "bone_idx" ), &SkeletonModification2DJiggle::set_jiggle_joint_bone_index); |
531 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_bone_index" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_bone_index); |
532 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_override" , "joint_idx" , "override" ), &SkeletonModification2DJiggle::set_jiggle_joint_override); |
533 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_override" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_override); |
534 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_stiffness" , "joint_idx" , "stiffness" ), &SkeletonModification2DJiggle::set_jiggle_joint_stiffness); |
535 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_stiffness" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_stiffness); |
536 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_mass" , "joint_idx" , "mass" ), &SkeletonModification2DJiggle::set_jiggle_joint_mass); |
537 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_mass" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_mass); |
538 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_damping" , "joint_idx" , "damping" ), &SkeletonModification2DJiggle::set_jiggle_joint_damping); |
539 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_damping" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_damping); |
540 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_use_gravity" , "joint_idx" , "use_gravity" ), &SkeletonModification2DJiggle::set_jiggle_joint_use_gravity); |
541 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_use_gravity" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_use_gravity); |
542 | ClassDB::bind_method(D_METHOD("set_jiggle_joint_gravity" , "joint_idx" , "gravity" ), &SkeletonModification2DJiggle::set_jiggle_joint_gravity); |
543 | ClassDB::bind_method(D_METHOD("get_jiggle_joint_gravity" , "joint_idx" ), &SkeletonModification2DJiggle::get_jiggle_joint_gravity); |
544 | |
545 | ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "target_nodepath" , PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D" ), "set_target_node" , "get_target_node" ); |
546 | 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" ); |
547 | ADD_GROUP("Default Joint Settings" , "" ); |
548 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "stiffness" ), "set_stiffness" , "get_stiffness" ); |
549 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass" ), "set_mass" , "get_mass" ); |
550 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "damping" , PROPERTY_HINT_RANGE, "0, 1, 0.01" ), "set_damping" , "get_damping" ); |
551 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_gravity" ), "set_use_gravity" , "get_use_gravity" ); |
552 | ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "gravity" ), "set_gravity" , "get_gravity" ); |
553 | ADD_GROUP("" , "" ); |
554 | } |
555 | |
556 | SkeletonModification2DJiggle::SkeletonModification2DJiggle() { |
557 | stack = nullptr; |
558 | is_setup = false; |
559 | jiggle_data_chain = Vector<Jiggle_Joint_Data2D>(); |
560 | stiffness = 3; |
561 | mass = 0.75; |
562 | damping = 0.75; |
563 | use_gravity = false; |
564 | gravity = Vector2(0, 6.0); |
565 | enabled = true; |
566 | editor_draw_gizmo = false; // Nothing to really show in a gizmo right now. |
567 | } |
568 | |
569 | SkeletonModification2DJiggle::~SkeletonModification2DJiggle() { |
570 | } |
571 | |