Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/3d/bone_constraint_3d.cpp
21155 views
1
/**************************************************************************/
2
/* bone_constraint_3d.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 "bone_constraint_3d.h"
32
33
bool BoneConstraint3D::_set(const StringName &p_path, const Variant &p_value) {
34
String path = p_path;
35
36
if (path.begins_with("settings/")) {
37
int which = path.get_slicec('/', 1).to_int();
38
String what = path.get_slicec('/', 2);
39
ERR_FAIL_INDEX_V(which, (int)settings.size(), false);
40
41
if (what == "amount") {
42
set_amount(which, p_value);
43
} else if (what == "reference_type") {
44
set_reference_type(which, static_cast<ReferenceType>((int)p_value));
45
} else if (what == "apply_bone_name") {
46
set_apply_bone_name(which, p_value);
47
} else if (what == "reference_bone_name") {
48
set_reference_bone_name(which, p_value);
49
} else if (what == "apply_bone") {
50
set_apply_bone(which, p_value);
51
} else if (what == "reference_bone") {
52
set_reference_bone(which, p_value);
53
} else if (what == "reference_node") {
54
set_reference_node(which, p_value);
55
} else {
56
return false;
57
}
58
}
59
return true;
60
}
61
62
bool BoneConstraint3D::_get(const StringName &p_path, Variant &r_ret) const {
63
String path = p_path;
64
65
if (path.begins_with("settings/")) {
66
int which = path.get_slicec('/', 1).to_int();
67
String what = path.get_slicec('/', 2);
68
ERR_FAIL_INDEX_V(which, (int)settings.size(), false);
69
70
if (what == "amount") {
71
r_ret = get_amount(which);
72
} else if (what == "reference_type") {
73
r_ret = (int)get_reference_type(which);
74
} else if (what == "apply_bone_name") {
75
r_ret = get_apply_bone_name(which);
76
} else if (what == "reference_bone_name") {
77
r_ret = get_reference_bone_name(which);
78
} else if (what == "apply_bone") {
79
r_ret = get_apply_bone(which);
80
} else if (what == "reference_bone") {
81
r_ret = get_reference_bone(which);
82
} else if (what == "reference_node") {
83
r_ret = get_reference_node(which);
84
} else {
85
return false;
86
}
87
}
88
return true;
89
}
90
91
void BoneConstraint3D::get_property_list(List<PropertyInfo> *p_list) const {
92
String enum_hint;
93
Skeleton3D *skeleton = get_skeleton();
94
if (skeleton) {
95
enum_hint = skeleton->get_concatenated_bone_names();
96
}
97
98
LocalVector<PropertyInfo> props;
99
100
for (uint32_t i = 0; i < settings.size(); i++) {
101
String path = "settings/" + itos(i) + "/";
102
props.push_back(PropertyInfo(Variant::FLOAT, path + "amount", PROPERTY_HINT_RANGE, "0,1,0.001"));
103
props.push_back(PropertyInfo(Variant::STRING, path + "apply_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
104
props.push_back(PropertyInfo(Variant::INT, path + "apply_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
105
props.push_back(PropertyInfo(Variant::INT, path + "reference_type", PROPERTY_HINT_ENUM, "Bone,Node"));
106
props.push_back(PropertyInfo(Variant::STRING, path + "reference_bone_name", PROPERTY_HINT_ENUM_SUGGESTION, enum_hint));
107
props.push_back(PropertyInfo(Variant::INT, path + "reference_bone", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
108
props.push_back(PropertyInfo(Variant::NODE_PATH, path + "reference_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"));
109
}
110
111
for (PropertyInfo &p : props) {
112
_validate_dynamic_prop(p);
113
p_list->push_back(p);
114
}
115
}
116
117
void BoneConstraint3D::_validate_dynamic_prop(PropertyInfo &p_property) const {
118
PackedStringArray split = p_property.name.split("/");
119
if (split.size() > 2 && split[0] == "settings") {
120
int which = split[1].to_int();
121
if (split[2].begins_with("reference_bone") && get_reference_type(which) != REFERENCE_TYPE_BONE) {
122
p_property.usage = PROPERTY_USAGE_NONE;
123
}
124
if (split[2].begins_with("reference_node") && get_reference_type(which) != REFERENCE_TYPE_NODE) {
125
p_property.usage = PROPERTY_USAGE_NONE;
126
}
127
}
128
}
129
130
void BoneConstraint3D::set_setting_count(int p_count) {
131
ERR_FAIL_COND(p_count < 0);
132
133
int delta = p_count - (int)settings.size();
134
if (delta < 0) {
135
for (int i = delta; i < 0; i++) {
136
memdelete(settings[(int)settings.size() + i]);
137
settings[(int)settings.size() + i] = nullptr;
138
}
139
}
140
settings.resize(p_count);
141
delta++;
142
143
if (delta > 1) {
144
for (int i = 1; i < delta; i++) {
145
_validate_setting(p_count - i);
146
}
147
}
148
149
notify_property_list_changed();
150
}
151
152
int BoneConstraint3D::get_setting_count() const {
153
return (int)settings.size();
154
}
155
156
void BoneConstraint3D::_validate_setting(int p_index) {
157
settings[p_index] = memnew(BoneConstraint3DSetting);
158
}
159
160
void BoneConstraint3D::clear_settings() {
161
set_setting_count(0);
162
}
163
164
void BoneConstraint3D::set_amount(int p_index, float p_amount) {
165
ERR_FAIL_INDEX(p_index, (int)settings.size());
166
settings[p_index]->amount = p_amount;
167
}
168
169
float BoneConstraint3D::get_amount(int p_index) const {
170
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0.0);
171
return settings[p_index]->amount;
172
}
173
174
void BoneConstraint3D::set_apply_bone_name(int p_index, const String &p_bone_name) {
175
ERR_FAIL_INDEX(p_index, (int)settings.size());
176
settings[p_index]->apply_bone_name = p_bone_name;
177
Skeleton3D *sk = get_skeleton();
178
if (sk) {
179
set_apply_bone(p_index, sk->find_bone(settings[p_index]->apply_bone_name));
180
}
181
}
182
183
String BoneConstraint3D::get_apply_bone_name(int p_index) const {
184
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), String());
185
return settings[p_index]->apply_bone_name;
186
}
187
188
void BoneConstraint3D::set_apply_bone(int p_index, int p_bone) {
189
ERR_FAIL_INDEX(p_index, (int)settings.size());
190
settings[p_index]->apply_bone = p_bone;
191
Skeleton3D *sk = get_skeleton();
192
if (sk) {
193
if (settings[p_index]->apply_bone <= -1 || settings[p_index]->apply_bone >= sk->get_bone_count()) {
194
WARN_PRINT("Apply bone index out of range!");
195
settings[p_index]->apply_bone = -1;
196
} else {
197
settings[p_index]->apply_bone_name = sk->get_bone_name(settings[p_index]->apply_bone);
198
}
199
}
200
}
201
202
int BoneConstraint3D::get_apply_bone(int p_index) const {
203
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), -1);
204
return settings[p_index]->apply_bone;
205
}
206
207
void BoneConstraint3D::set_reference_type(int p_index, ReferenceType p_type) {
208
ERR_FAIL_INDEX(p_index, (int)settings.size());
209
settings[p_index]->reference_type = p_type;
210
notify_property_list_changed();
211
}
212
213
BoneConstraint3D::ReferenceType BoneConstraint3D::get_reference_type(int p_index) const {
214
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), REFERENCE_TYPE_BONE);
215
return settings[p_index]->reference_type;
216
}
217
218
void BoneConstraint3D::set_reference_bone_name(int p_index, const String &p_bone_name) {
219
ERR_FAIL_INDEX(p_index, (int)settings.size());
220
settings[p_index]->reference_bone_name = p_bone_name;
221
Skeleton3D *sk = get_skeleton();
222
if (sk) {
223
set_reference_bone(p_index, sk->find_bone(settings[p_index]->reference_bone_name));
224
}
225
}
226
227
String BoneConstraint3D::get_reference_bone_name(int p_index) const {
228
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), String());
229
return settings[p_index]->reference_bone_name;
230
}
231
232
void BoneConstraint3D::set_reference_bone(int p_index, int p_bone) {
233
ERR_FAIL_INDEX(p_index, (int)settings.size());
234
settings[p_index]->reference_bone = p_bone;
235
Skeleton3D *sk = get_skeleton();
236
if (sk) {
237
if (settings[p_index]->reference_bone <= -1 || settings[p_index]->reference_bone >= sk->get_bone_count()) {
238
WARN_PRINT("reference bone index out of range!");
239
settings[p_index]->reference_bone = -1;
240
} else {
241
settings[p_index]->reference_bone_name = sk->get_bone_name(settings[p_index]->reference_bone);
242
}
243
}
244
}
245
246
int BoneConstraint3D::get_reference_bone(int p_index) const {
247
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), -1);
248
return settings[p_index]->reference_bone;
249
}
250
251
void BoneConstraint3D::set_reference_node(int p_index, const NodePath &p_node) {
252
ERR_FAIL_INDEX(p_index, (int)settings.size());
253
settings[p_index]->reference_node = p_node;
254
}
255
256
NodePath BoneConstraint3D::get_reference_node(int p_index) const {
257
ERR_FAIL_INDEX_V(p_index, (int)settings.size(), NodePath());
258
return settings[p_index]->reference_node;
259
}
260
261
void BoneConstraint3D::_bind_methods() {
262
ClassDB::bind_method(D_METHOD("set_amount", "index", "amount"), &BoneConstraint3D::set_amount);
263
ClassDB::bind_method(D_METHOD("get_amount", "index"), &BoneConstraint3D::get_amount);
264
ClassDB::bind_method(D_METHOD("set_apply_bone_name", "index", "bone_name"), &BoneConstraint3D::set_apply_bone_name);
265
ClassDB::bind_method(D_METHOD("get_apply_bone_name", "index"), &BoneConstraint3D::get_apply_bone_name);
266
ClassDB::bind_method(D_METHOD("set_apply_bone", "index", "bone"), &BoneConstraint3D::set_apply_bone);
267
ClassDB::bind_method(D_METHOD("get_apply_bone", "index"), &BoneConstraint3D::get_apply_bone);
268
ClassDB::bind_method(D_METHOD("set_reference_type", "index", "type"), &BoneConstraint3D::set_reference_type);
269
ClassDB::bind_method(D_METHOD("get_reference_type", "index"), &BoneConstraint3D::get_reference_type);
270
ClassDB::bind_method(D_METHOD("set_reference_bone_name", "index", "bone_name"), &BoneConstraint3D::set_reference_bone_name);
271
ClassDB::bind_method(D_METHOD("get_reference_bone_name", "index"), &BoneConstraint3D::get_reference_bone_name);
272
ClassDB::bind_method(D_METHOD("set_reference_bone", "index", "bone"), &BoneConstraint3D::set_reference_bone);
273
ClassDB::bind_method(D_METHOD("get_reference_bone", "index"), &BoneConstraint3D::get_reference_bone);
274
ClassDB::bind_method(D_METHOD("set_reference_node", "index", "node"), &BoneConstraint3D::set_reference_node);
275
ClassDB::bind_method(D_METHOD("get_reference_node", "index"), &BoneConstraint3D::get_reference_node);
276
277
ClassDB::bind_method(D_METHOD("set_setting_count", "count"), &BoneConstraint3D::set_setting_count);
278
ClassDB::bind_method(D_METHOD("get_setting_count"), &BoneConstraint3D::get_setting_count);
279
ClassDB::bind_method(D_METHOD("clear_setting"), &BoneConstraint3D::clear_settings);
280
281
BIND_ENUM_CONSTANT(REFERENCE_TYPE_BONE);
282
BIND_ENUM_CONSTANT(REFERENCE_TYPE_NODE);
283
}
284
285
void BoneConstraint3D::_validate_bone_names() {
286
for (int i = 0; i < (int)settings.size(); i++) {
287
// Prior bone name.
288
if (!settings[i]->apply_bone_name.is_empty()) {
289
set_apply_bone_name(i, settings[i]->apply_bone_name);
290
} else if (settings[i]->apply_bone != -1) {
291
set_apply_bone(i, settings[i]->apply_bone);
292
}
293
// Prior bone name.
294
if (!settings[i]->reference_bone_name.is_empty()) {
295
set_reference_bone_name(i, settings[i]->reference_bone_name);
296
} else if (settings[i]->reference_bone != -1) {
297
set_reference_bone(i, settings[i]->reference_bone);
298
}
299
}
300
}
301
302
void BoneConstraint3D::_process_modification(double p_delta) {
303
Skeleton3D *skeleton = get_skeleton();
304
if (!skeleton) {
305
return;
306
}
307
308
for (int i = 0; i < (int)settings.size(); i++) {
309
float amount = settings[i]->amount;
310
if (amount <= 0) {
311
continue;
312
}
313
314
int apply_bone = settings[i]->apply_bone;
315
if (apply_bone < 0) {
316
continue;
317
}
318
319
if (settings[i]->reference_type == REFERENCE_TYPE_BONE) {
320
int reference_bone = settings[i]->reference_bone;
321
if (reference_bone < 0) {
322
continue;
323
}
324
_process_constraint_by_bone(i, skeleton, apply_bone, reference_bone, amount);
325
} else {
326
NodePath pt = settings[i]->reference_node;
327
if (pt.is_empty()) {
328
continue;
329
}
330
_process_constraint_by_node(i, skeleton, apply_bone, pt, amount);
331
}
332
}
333
}
334
335
void BoneConstraint3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) {
336
//
337
}
338
339
void BoneConstraint3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) {
340
//
341
}
342
343
BoneConstraint3D::~BoneConstraint3D() {
344
clear_settings();
345
}
346
347