Allow for getting/setting indexed properties of objects using get/set_indexed
Performance is around the same as using pure set() through GDScript.
This commit is contained in:
parent
7bbde636e8
commit
0cf9597758
@ -324,7 +324,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|||||||
ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
|
ERR_FAIL_COND_V(len < 12, ERR_INVALID_DATA);
|
||||||
Vector<StringName> names;
|
Vector<StringName> names;
|
||||||
Vector<StringName> subnames;
|
Vector<StringName> subnames;
|
||||||
StringName prop;
|
|
||||||
|
|
||||||
uint32_t namecount = strlen &= 0x7FFFFFFF;
|
uint32_t namecount = strlen &= 0x7FFFFFFF;
|
||||||
uint32_t subnamecount = decode_uint32(buf + 4);
|
uint32_t subnamecount = decode_uint32(buf + 4);
|
||||||
@ -333,9 +332,10 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|||||||
len -= 12;
|
len -= 12;
|
||||||
buf += 12;
|
buf += 12;
|
||||||
|
|
||||||
|
if (flags & 2) // Obsolete format with property seperate from subpath
|
||||||
|
subnamecount++;
|
||||||
|
|
||||||
uint32_t total = namecount + subnamecount;
|
uint32_t total = namecount + subnamecount;
|
||||||
if (flags & 2)
|
|
||||||
total++;
|
|
||||||
|
|
||||||
if (r_len)
|
if (r_len)
|
||||||
(*r_len) += 12;
|
(*r_len) += 12;
|
||||||
@ -359,10 +359,8 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|||||||
|
|
||||||
if (i < namecount)
|
if (i < namecount)
|
||||||
names.push_back(str);
|
names.push_back(str);
|
||||||
else if (i < namecount + subnamecount)
|
|
||||||
subnames.push_back(str);
|
|
||||||
else
|
else
|
||||||
prop = str;
|
subnames.push_back(str);
|
||||||
|
|
||||||
buf += strlen + pad;
|
buf += strlen + pad;
|
||||||
len -= strlen + pad;
|
len -= strlen + pad;
|
||||||
@ -371,7 +369,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
|
|||||||
(*r_len) += 4 + strlen + pad;
|
(*r_len) += 4 + strlen + pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
r_variant = NodePath(names, subnames, flags & 1, prop);
|
r_variant = NodePath(names, subnames, flags & 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//old format, just a string
|
//old format, just a string
|
||||||
@ -919,8 +917,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
if (np.is_absolute())
|
if (np.is_absolute())
|
||||||
flags |= 1;
|
flags |= 1;
|
||||||
if (np.get_property() != StringName())
|
|
||||||
flags |= 2;
|
|
||||||
|
|
||||||
encode_uint32(flags, buf + 8);
|
encode_uint32(flags, buf + 8);
|
||||||
|
|
||||||
@ -930,8 +926,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|||||||
r_len += 12;
|
r_len += 12;
|
||||||
|
|
||||||
int total = np.get_name_count() + np.get_subname_count();
|
int total = np.get_name_count() + np.get_subname_count();
|
||||||
if (np.get_property() != StringName())
|
|
||||||
total++;
|
|
||||||
|
|
||||||
for (int i = 0; i < total; i++) {
|
for (int i = 0; i < total; i++) {
|
||||||
|
|
||||||
@ -939,10 +933,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
|||||||
|
|
||||||
if (i < np.get_name_count())
|
if (i < np.get_name_count())
|
||||||
str = np.get_name(i);
|
str = np.get_name(i);
|
||||||
else if (i < np.get_name_count() + np.get_subname_count())
|
|
||||||
str = np.get_subname(i - np.get_subname_count());
|
|
||||||
else
|
else
|
||||||
str = np.get_property();
|
str = np.get_subname(i - np.get_name_count());
|
||||||
|
|
||||||
CharString utf8 = str.utf8();
|
CharString utf8 = str.utf8();
|
||||||
|
|
||||||
|
@ -267,7 +267,6 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
|
|||||||
|
|
||||||
Vector<StringName> names;
|
Vector<StringName> names;
|
||||||
Vector<StringName> subnames;
|
Vector<StringName> subnames;
|
||||||
StringName property;
|
|
||||||
bool absolute;
|
bool absolute;
|
||||||
|
|
||||||
int name_count = f->get_16();
|
int name_count = f->get_16();
|
||||||
@ -279,9 +278,8 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
|
|||||||
names.push_back(_get_string());
|
names.push_back(_get_string());
|
||||||
for (uint32_t i = 0; i < subname_count; i++)
|
for (uint32_t i = 0; i < subname_count; i++)
|
||||||
subnames.push_back(_get_string());
|
subnames.push_back(_get_string());
|
||||||
property = _get_string();
|
|
||||||
|
|
||||||
NodePath np = NodePath(names, subnames, absolute, property);
|
NodePath np = NodePath(names, subnames, absolute);
|
||||||
|
|
||||||
r_v = np;
|
r_v = np;
|
||||||
|
|
||||||
@ -1454,7 +1452,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(const Variant &p_property,
|
|||||||
f->store_32(get_string_index(np.get_name(i)));
|
f->store_32(get_string_index(np.get_name(i)));
|
||||||
for (int i = 0; i < np.get_subname_count(); i++)
|
for (int i = 0; i < np.get_subname_count(); i++)
|
||||||
f->store_32(get_string_index(np.get_subname(i)));
|
f->store_32(get_string_index(np.get_subname(i)));
|
||||||
f->store_32(get_string_index(np.get_property()));
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case Variant::_RID: {
|
case Variant::_RID: {
|
||||||
@ -1685,7 +1682,6 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
|
|||||||
get_string_index(np.get_name(i));
|
get_string_index(np.get_name(i));
|
||||||
for (int i = 0; i < np.get_subname_count(); i++)
|
for (int i = 0; i < np.get_subname_count(); i++)
|
||||||
get_string_index(np.get_subname(i));
|
get_string_index(np.get_subname(i));
|
||||||
get_string_index(np.get_property());
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: {}
|
default: {}
|
||||||
|
@ -48,8 +48,6 @@ uint32_t NodePath::hash() const {
|
|||||||
h = h ^ ssn[i].hash();
|
h = h ^ ssn[i].hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
h = h ^ data->property.hash();
|
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,13 +79,6 @@ StringName NodePath::get_name(int p_idx) const {
|
|||||||
return data->path[p_idx];
|
return data->path[p_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
StringName NodePath::get_property() const {
|
|
||||||
|
|
||||||
if (!data)
|
|
||||||
return StringName();
|
|
||||||
return data->property;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NodePath::get_subname_count() const {
|
int NodePath::get_subname_count() const {
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
@ -128,9 +119,6 @@ bool NodePath::operator==(const NodePath &p_path) const {
|
|||||||
if (data->subpath.size() != p_path.data->subpath.size())
|
if (data->subpath.size() != p_path.data->subpath.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (data->property != p_path.data->property)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int i = 0; i < data->path.size(); i++) {
|
for (int i = 0; i < data->path.size(); i++) {
|
||||||
|
|
||||||
if (data->path[i] != p_path.data->path[i])
|
if (data->path[i] != p_path.data->path[i])
|
||||||
@ -184,8 +172,6 @@ NodePath::operator String() const {
|
|||||||
ret += ":" + data->subpath[i].operator String();
|
ret += ":" + data->subpath[i].operator String();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->property.operator String() != "")
|
|
||||||
ret += ":" + String(data->property);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +191,7 @@ Vector<StringName> NodePath::get_names() const {
|
|||||||
return data->path;
|
return data->path;
|
||||||
return Vector<StringName>();
|
return Vector<StringName>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<StringName> NodePath::get_subnames() const {
|
Vector<StringName> NodePath::get_subnames() const {
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
@ -212,6 +199,21 @@ Vector<StringName> NodePath::get_subnames() const {
|
|||||||
return Vector<StringName>();
|
return Vector<StringName>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringName NodePath::get_concatenated_subnames() const {
|
||||||
|
ERR_FAIL_COND_V(!data, StringName());
|
||||||
|
|
||||||
|
if (!data->concatenated_subpath) {
|
||||||
|
int spc = data->subpath.size();
|
||||||
|
String concatenated;
|
||||||
|
const StringName *ssn = data->subpath.ptr();
|
||||||
|
for (int i = 0; i < spc; i++) {
|
||||||
|
concatenated += i == 0 ? ssn[i].operator String() : "." + ssn[i];
|
||||||
|
}
|
||||||
|
data->concatenated_subpath = concatenated;
|
||||||
|
}
|
||||||
|
return data->concatenated_subpath;
|
||||||
|
}
|
||||||
|
|
||||||
NodePath NodePath::rel_path_to(const NodePath &p_np) const {
|
NodePath NodePath::rel_path_to(const NodePath &p_np) const {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!is_absolute(), NodePath());
|
ERR_FAIL_COND_V(!is_absolute(), NodePath());
|
||||||
@ -250,10 +252,23 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const {
|
|||||||
if (relpath.size() == 0)
|
if (relpath.size() == 0)
|
||||||
relpath.push_back(".");
|
relpath.push_back(".");
|
||||||
|
|
||||||
return NodePath(relpath, p_np.get_subnames(), false, p_np.get_property());
|
return NodePath(relpath, p_np.get_subnames(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute, const String &p_property) {
|
NodePath NodePath::get_as_property_path() const {
|
||||||
|
|
||||||
|
if (data->has_slashes || !data->path.size()) {
|
||||||
|
return NodePath(Vector<StringName>(), data->subpath, false);
|
||||||
|
} else {
|
||||||
|
ERR_FAIL_COND_V(data->path.size() != 1, NodePath());
|
||||||
|
|
||||||
|
Vector<StringName> new_path = data->subpath;
|
||||||
|
new_path.insert(0, data->path[0]);
|
||||||
|
return NodePath(Vector<StringName>(), new_path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) {
|
||||||
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
||||||
@ -264,14 +279,14 @@ NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute, const Stri
|
|||||||
data->refcount.init();
|
data->refcount.init();
|
||||||
data->absolute = p_absolute;
|
data->absolute = p_absolute;
|
||||||
data->path = p_path;
|
data->path = p_path;
|
||||||
data->property = p_property;
|
data->has_slashes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute, const String &p_property) {
|
NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute) {
|
||||||
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
||||||
if (p_path.size() == 0)
|
if (p_path.size() == 0 && p_subpath.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data = memnew(Data);
|
data = memnew(Data);
|
||||||
@ -279,7 +294,7 @@ NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p
|
|||||||
data->absolute = p_absolute;
|
data->absolute = p_absolute;
|
||||||
data->path = p_path;
|
data->path = p_path;
|
||||||
data->subpath = p_subpath;
|
data->subpath = p_subpath;
|
||||||
data->property = p_property;
|
data->has_slashes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodePath::simplify() {
|
void NodePath::simplify() {
|
||||||
@ -325,6 +340,7 @@ NodePath::NodePath(const String &p_path) {
|
|||||||
|
|
||||||
int absolute = (path[0] == '/') ? 1 : 0;
|
int absolute = (path[0] == '/') ? 1 : 0;
|
||||||
bool last_is_slash = true;
|
bool last_is_slash = true;
|
||||||
|
bool has_slashes = false;
|
||||||
int slices = 0;
|
int slices = 0;
|
||||||
int subpath_pos = path.find(":");
|
int subpath_pos = path.find(":");
|
||||||
|
|
||||||
@ -337,16 +353,13 @@ NodePath::NodePath(const String &p_path) {
|
|||||||
if (path[i] == ':' || path[i] == 0) {
|
if (path[i] == ':' || path[i] == 0) {
|
||||||
|
|
||||||
String str = path.substr(from, i - from);
|
String str = path.substr(from, i - from);
|
||||||
if (path[i] == ':') {
|
|
||||||
if (str == "") {
|
if (str == "") {
|
||||||
|
if (path[i] == 0) continue; // Allow end-of-path :
|
||||||
|
|
||||||
ERR_EXPLAIN("Invalid NodePath: " + p_path);
|
ERR_EXPLAIN("Invalid NodePath: " + p_path);
|
||||||
ERR_FAIL();
|
ERR_FAIL();
|
||||||
}
|
}
|
||||||
subpath.push_back(str);
|
subpath.push_back(str);
|
||||||
} else {
|
|
||||||
//property can be empty
|
|
||||||
property = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
from = i + 1;
|
from = i + 1;
|
||||||
}
|
}
|
||||||
@ -360,6 +373,7 @@ NodePath::NodePath(const String &p_path) {
|
|||||||
if (path[i] == '/') {
|
if (path[i] == '/') {
|
||||||
|
|
||||||
last_is_slash = true;
|
last_is_slash = true;
|
||||||
|
has_slashes = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (last_is_slash)
|
if (last_is_slash)
|
||||||
@ -369,13 +383,13 @@ NodePath::NodePath(const String &p_path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slices == 0 && !absolute && !property)
|
if (slices == 0 && !absolute && !subpath.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data = memnew(Data);
|
data = memnew(Data);
|
||||||
data->refcount.init();
|
data->refcount.init();
|
||||||
data->absolute = absolute ? true : false;
|
data->absolute = absolute ? true : false;
|
||||||
data->property = property;
|
data->has_slashes = has_slashes;
|
||||||
data->subpath = subpath;
|
data->subpath = subpath;
|
||||||
|
|
||||||
if (slices == 0)
|
if (slices == 0)
|
||||||
|
@ -41,10 +41,11 @@ class NodePath {
|
|||||||
struct Data {
|
struct Data {
|
||||||
|
|
||||||
SafeRefCount refcount;
|
SafeRefCount refcount;
|
||||||
StringName property;
|
|
||||||
Vector<StringName> path;
|
Vector<StringName> path;
|
||||||
Vector<StringName> subpath;
|
Vector<StringName> subpath;
|
||||||
|
StringName concatenated_subpath;
|
||||||
bool absolute;
|
bool absolute;
|
||||||
|
bool has_slashes;
|
||||||
};
|
};
|
||||||
|
|
||||||
Data *data;
|
Data *data;
|
||||||
@ -53,7 +54,7 @@ class NodePath {
|
|||||||
public:
|
public:
|
||||||
_FORCE_INLINE_ StringName get_sname() const {
|
_FORCE_INLINE_ StringName get_sname() const {
|
||||||
|
|
||||||
if (data && data->path.size() == 1 && data->subpath.empty() && !data->property) {
|
if (data && data->path.size() == 1 && data->subpath.empty()) {
|
||||||
return data->path[0];
|
return data->path[0];
|
||||||
} else {
|
} else {
|
||||||
return operator String();
|
return operator String();
|
||||||
@ -67,13 +68,13 @@ public:
|
|||||||
StringName get_subname(int p_idx) const;
|
StringName get_subname(int p_idx) const;
|
||||||
Vector<StringName> get_names() const;
|
Vector<StringName> get_names() const;
|
||||||
Vector<StringName> get_subnames() const;
|
Vector<StringName> get_subnames() const;
|
||||||
|
StringName get_concatenated_subnames() const;
|
||||||
|
|
||||||
NodePath rel_path_to(const NodePath &p_np) const;
|
NodePath rel_path_to(const NodePath &p_np) const;
|
||||||
|
NodePath get_as_property_path() const;
|
||||||
|
|
||||||
void prepend_period();
|
void prepend_period();
|
||||||
|
|
||||||
StringName get_property() const;
|
|
||||||
|
|
||||||
NodePath get_parent() const;
|
NodePath get_parent() const;
|
||||||
|
|
||||||
uint32_t hash() const;
|
uint32_t hash() const;
|
||||||
@ -88,8 +89,8 @@ public:
|
|||||||
void simplify();
|
void simplify();
|
||||||
NodePath simplified() const;
|
NodePath simplified() const;
|
||||||
|
|
||||||
NodePath(const Vector<StringName> &p_path, bool p_absolute, const String &p_property = "");
|
NodePath(const Vector<StringName> &p_path, bool p_absolute);
|
||||||
NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute, const String &p_property = "");
|
NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute);
|
||||||
NodePath(const NodePath &p_path);
|
NodePath(const NodePath &p_path);
|
||||||
NodePath(const String &p_path);
|
NodePath(const String &p_path);
|
||||||
NodePath();
|
NodePath();
|
||||||
|
123
core/object.cpp
123
core/object.cpp
@ -517,6 +517,80 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) {
|
||||||
|
if (p_names.empty()) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p_names.size() == 1) {
|
||||||
|
set(p_names[0], p_value, r_valid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
if (!r_valid) r_valid = &valid;
|
||||||
|
|
||||||
|
List<Variant> value_stack;
|
||||||
|
|
||||||
|
value_stack.push_back(get(p_names[0], r_valid));
|
||||||
|
|
||||||
|
if (!*r_valid) {
|
||||||
|
value_stack.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < p_names.size() - 1; i++) {
|
||||||
|
value_stack.push_back(value_stack.back()->get().get_named(p_names[i], r_valid));
|
||||||
|
|
||||||
|
if (!*r_valid) {
|
||||||
|
value_stack.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value_stack.push_back(p_value); // p_names[p_names.size() - 1]
|
||||||
|
|
||||||
|
for (int i = p_names.size() - 1; i > 0; i--) {
|
||||||
|
|
||||||
|
value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid);
|
||||||
|
value_stack.pop_back();
|
||||||
|
|
||||||
|
if (!*r_valid) {
|
||||||
|
value_stack.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(p_names[0], value_stack.back()->get(), r_valid);
|
||||||
|
value_stack.pop_back();
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!value_stack.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const {
|
||||||
|
if (p_names.empty()) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
bool valid = false;
|
||||||
|
|
||||||
|
Variant current_value = get(p_names[0]);
|
||||||
|
for (int i = 1; i < p_names.size(); i++) {
|
||||||
|
current_value = current_value.get_named(p_names[i], &valid);
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = true;
|
||||||
|
return current_value;
|
||||||
|
}
|
||||||
|
|
||||||
void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
|
void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const {
|
||||||
|
|
||||||
if (script_instance && p_reversed) {
|
if (script_instance && p_reversed) {
|
||||||
@ -1416,6 +1490,16 @@ Variant Object::_get_bind(const String &p_name) const {
|
|||||||
return get(p_name);
|
return get(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Object::_set_indexed_bind(const NodePath &p_name, const Variant &p_value) {
|
||||||
|
|
||||||
|
set_indexed(p_name.get_as_property_path().get_subnames(), p_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant Object::_get_indexed_bind(const NodePath &p_name) const {
|
||||||
|
|
||||||
|
return get_indexed(p_name.get_as_property_path().get_subnames());
|
||||||
|
}
|
||||||
|
|
||||||
void Object::initialize_class() {
|
void Object::initialize_class() {
|
||||||
|
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@ -1513,6 +1597,8 @@ void Object::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("is_class", "type"), &Object::is_class);
|
ClassDB::bind_method(D_METHOD("is_class", "type"), &Object::is_class);
|
||||||
ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind);
|
ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind);
|
||||||
ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind);
|
ClassDB::bind_method(D_METHOD("get", "property"), &Object::_get_bind);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_indexed", "property", "value"), &Object::_set_indexed_bind);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_indexed", "property"), &Object::_get_indexed_bind);
|
||||||
ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
|
ClassDB::bind_method(D_METHOD("get_property_list"), &Object::_get_property_list_bind);
|
||||||
ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
|
ClassDB::bind_method(D_METHOD("get_method_list"), &Object::_get_method_list_bind);
|
||||||
ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("notification", "what", "reversed"), &Object::notification, DEFVAL(false));
|
||||||
@ -1661,6 +1747,43 @@ Variant::Type Object::get_static_property_type(const StringName &p_property, boo
|
|||||||
return Variant::NIL;
|
return Variant::NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const {
|
||||||
|
|
||||||
|
bool valid = false;
|
||||||
|
Variant::Type t = get_static_property_type(p_path[0], &valid);
|
||||||
|
if (!valid) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
|
||||||
|
return Variant::NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant::CallError ce;
|
||||||
|
Variant check = Variant::construct(t, NULL, 0, ce);
|
||||||
|
|
||||||
|
for (int i = 1; i < p_path.size(); i++) {
|
||||||
|
if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
|
||||||
|
// We cannot be sure about the type of properties this types can have
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
return Variant::NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
check = check.get_named(p_path[i], &valid);
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = false;
|
||||||
|
return Variant::NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_valid)
|
||||||
|
*r_valid = true;
|
||||||
|
|
||||||
|
return check.get_type();
|
||||||
|
}
|
||||||
|
|
||||||
bool Object::is_queued_for_deletion() const {
|
bool Object::is_queued_for_deletion() const {
|
||||||
return _is_queued_for_deletion;
|
return _is_queued_for_deletion;
|
||||||
}
|
}
|
||||||
|
@ -477,6 +477,8 @@ private:
|
|||||||
Array _get_incoming_connections() const;
|
Array _get_incoming_connections() const;
|
||||||
void _set_bind(const String &p_set, const Variant &p_value);
|
void _set_bind(const String &p_set, const Variant &p_value);
|
||||||
Variant _get_bind(const String &p_name) const;
|
Variant _get_bind(const String &p_name) const;
|
||||||
|
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
|
||||||
|
Variant _get_indexed_bind(const NodePath &p_name) const;
|
||||||
|
|
||||||
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
|
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
|
||||||
|
|
||||||
@ -627,6 +629,8 @@ public:
|
|||||||
|
|
||||||
void set(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL);
|
void set(const StringName &p_name, const Variant &p_value, bool *r_valid = NULL);
|
||||||
Variant get(const StringName &p_name, bool *r_valid = NULL) const;
|
Variant get(const StringName &p_name, bool *r_valid = NULL) const;
|
||||||
|
void set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid = NULL);
|
||||||
|
Variant get_indexed(const Vector<StringName> &p_names, bool *r_valid = NULL) const;
|
||||||
|
|
||||||
void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
|
void get_property_list(List<PropertyInfo> *p_list, bool p_reversed = false) const;
|
||||||
|
|
||||||
@ -687,6 +691,7 @@ public:
|
|||||||
bool is_blocking_signals() const;
|
bool is_blocking_signals() const;
|
||||||
|
|
||||||
Variant::Type get_static_property_type(const StringName &p_property, bool *r_valid = NULL) const;
|
Variant::Type get_static_property_type(const StringName &p_property, bool *r_valid = NULL) const;
|
||||||
|
Variant::Type get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid = NULL) const;
|
||||||
|
|
||||||
virtual void get_translatable_strings(List<String> *p_strings) const;
|
virtual void get_translatable_strings(List<String> *p_strings) const;
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ struct _VariantCall {
|
|||||||
VCALL_LOCALMEM1R(NodePath, get_name);
|
VCALL_LOCALMEM1R(NodePath, get_name);
|
||||||
VCALL_LOCALMEM0R(NodePath, get_subname_count);
|
VCALL_LOCALMEM0R(NodePath, get_subname_count);
|
||||||
VCALL_LOCALMEM1R(NodePath, get_subname);
|
VCALL_LOCALMEM1R(NodePath, get_subname);
|
||||||
VCALL_LOCALMEM0R(NodePath, get_property);
|
VCALL_LOCALMEM0R(NodePath, get_concatenated_subnames);
|
||||||
VCALL_LOCALMEM0R(NodePath, is_empty);
|
VCALL_LOCALMEM0R(NodePath, is_empty);
|
||||||
|
|
||||||
VCALL_LOCALMEM0R(Dictionary, size);
|
VCALL_LOCALMEM0R(Dictionary, size);
|
||||||
@ -1590,7 +1590,7 @@ void register_variant_methods() {
|
|||||||
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
|
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
|
||||||
ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray());
|
ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray());
|
||||||
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
|
ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
|
||||||
ADDFUNC0R(NODE_PATH, STRING, NodePath, get_property, varray());
|
ADDFUNC0R(NODE_PATH, STRING, NodePath, get_concatenated_subnames, varray());
|
||||||
ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray());
|
ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray());
|
||||||
|
|
||||||
ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray());
|
ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray());
|
||||||
|
@ -966,7 +966,9 @@ void AnimationKeyEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
|||||||
Object *obj = NULL;
|
Object *obj = NULL;
|
||||||
|
|
||||||
RES res;
|
RES res;
|
||||||
Node *node = root->get_node_and_resource(p_animation->track_get_path(i), res);
|
Vector<StringName> leftover_path;
|
||||||
|
|
||||||
|
Node *node = root->get_node_and_resource(p_animation->track_get_path(i), res, leftover_path);
|
||||||
|
|
||||||
if (res.is_valid()) {
|
if (res.is_valid()) {
|
||||||
obj = res.ptr();
|
obj = res.ptr();
|
||||||
@ -975,7 +977,7 @@ void AnimationKeyEditor::_cleanup_animation(Ref<Animation> p_animation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj && p_animation->track_get_type(i) == Animation::TYPE_VALUE) {
|
if (obj && p_animation->track_get_type(i) == Animation::TYPE_VALUE) {
|
||||||
valid_type = obj->get_static_property_type(p_animation->track_get_path(i).get_property(), &prop_exists);
|
valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj && cleanup_tracks->is_pressed()) {
|
if (!obj && cleanup_tracks->is_pressed()) {
|
||||||
@ -1315,7 +1317,9 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
Object *obj = NULL;
|
Object *obj = NULL;
|
||||||
|
|
||||||
RES res;
|
RES res;
|
||||||
Node *node = root ? root->get_node_and_resource(animation->track_get_path(idx), res) : (Node *)NULL;
|
Vector<StringName> leftover_path;
|
||||||
|
|
||||||
|
Node *node = root ? root->get_node_and_resource(animation->track_get_path(idx), res, leftover_path) : (Node *)NULL;
|
||||||
|
|
||||||
if (res.is_valid()) {
|
if (res.is_valid()) {
|
||||||
obj = res.ptr();
|
obj = res.ptr();
|
||||||
@ -1324,7 +1328,8 @@ void AnimationKeyEditor::_track_editor_draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj && animation->track_get_type(idx) == Animation::TYPE_VALUE) {
|
if (obj && animation->track_get_type(idx) == Animation::TYPE_VALUE) {
|
||||||
valid_type = obj->get_static_property_type(animation->track_get_path(idx).get_property(), &prop_exists);
|
// While leftover_path might be still empty, we wouldn't be able to get here anyway
|
||||||
|
valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx == mouse_over.track) {
|
if (/*mouse_over.over!=MouseOver::OVER_NONE &&*/ idx == mouse_over.track) {
|
||||||
@ -1649,27 +1654,35 @@ PropertyInfo AnimationKeyEditor::_find_hint_for_track(int p_idx, NodePath &r_bas
|
|||||||
return PropertyInfo();
|
return PropertyInfo();
|
||||||
|
|
||||||
RES res;
|
RES res;
|
||||||
Node *node = root->get_node_and_resource(path, res);
|
Vector<StringName> leftover_path;
|
||||||
|
Node *node = root->get_node_and_resource(path, res, leftover_path, true);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
r_base_path = node->get_path();
|
r_base_path = node->get_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
String property = path.get_property();
|
if (leftover_path.empty())
|
||||||
if (property == "")
|
|
||||||
return PropertyInfo();
|
return PropertyInfo();
|
||||||
|
|
||||||
List<PropertyInfo> pinfo;
|
Variant property_info_base;
|
||||||
if (res.is_valid())
|
if (res.is_valid())
|
||||||
res->get_property_list(&pinfo);
|
property_info_base = res;
|
||||||
else if (node)
|
else if (node)
|
||||||
node->get_property_list(&pinfo);
|
property_info_base = node;
|
||||||
|
|
||||||
|
for (int i = 0; i < leftover_path.size() - 1; i++) {
|
||||||
|
property_info_base = property_info_base.get_named(leftover_path[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PropertyInfo> pinfo;
|
||||||
|
property_info_base.get_property_list(&pinfo);
|
||||||
|
|
||||||
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
|
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
|
||||||
|
|
||||||
if (E->get().name == property)
|
if (E->get().name == leftover_path[leftover_path.size() - 1]) {
|
||||||
return E->get();
|
return E->get();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return PropertyInfo();
|
return PropertyInfo();
|
||||||
}
|
}
|
||||||
@ -2780,7 +2793,8 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
|
|||||||
Object *obj = NULL;
|
Object *obj = NULL;
|
||||||
|
|
||||||
RES res;
|
RES res;
|
||||||
Node *node = root->get_node_and_resource(animation->track_get_path(idx), res);
|
Vector<StringName> leftover_path;
|
||||||
|
Node *node = root->get_node_and_resource(animation->track_get_path(idx), res, leftover_path);
|
||||||
|
|
||||||
if (res.is_valid()) {
|
if (res.is_valid()) {
|
||||||
obj = res.ptr();
|
obj = res.ptr();
|
||||||
@ -2789,7 +2803,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
valid_type = obj->get_static_property_type(animation->track_get_path(idx).get_property(), &prop_exists);
|
valid_type = obj->get_static_property_type_indexed(leftover_path, &prop_exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
text += "type: " + Variant::get_type_name(v.get_type()) + "\n";
|
text += "type: " + Variant::get_type_name(v.get_type()) + "\n";
|
||||||
|
@ -1196,14 +1196,14 @@ void AnimationTreeEditor::_edit_filters() {
|
|||||||
if (base) {
|
if (base) {
|
||||||
NodePath np = E->get();
|
NodePath np = E->get();
|
||||||
|
|
||||||
if (np.get_property() != StringName()) {
|
if (np.get_subname_count() == 1) {
|
||||||
Node *n = base->get_node(np);
|
Node *n = base->get_node(np);
|
||||||
Skeleton *s = Object::cast_to<Skeleton>(n);
|
Skeleton *s = Object::cast_to<Skeleton>(n);
|
||||||
if (s) {
|
if (s) {
|
||||||
|
|
||||||
String skelbase = E->get().substr(0, E->get().find(":"));
|
String skelbase = E->get().substr(0, E->get().find(":"));
|
||||||
|
|
||||||
int bidx = s->find_bone(np.get_property());
|
int bidx = s->find_bone(np.get_subname(0));
|
||||||
|
|
||||||
if (bidx != -1) {
|
if (bidx != -1) {
|
||||||
int bparent = s->get_bone_parent(bidx);
|
int bparent = s->get_bone_parent(bidx);
|
||||||
@ -1213,7 +1213,7 @@ void AnimationTreeEditor::_edit_filters() {
|
|||||||
String bpn = skelbase + ":" + s->get_bone_name(bparent);
|
String bpn = skelbase + ":" + s->get_bone_name(bparent);
|
||||||
if (pm.has(bpn)) {
|
if (pm.has(bpn)) {
|
||||||
parent = pm[bpn];
|
parent = pm[bpn];
|
||||||
descr = np.get_property();
|
descr = np.get_subname(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -1050,7 +1050,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
|
|||||||
//will be renamed
|
//will be renamed
|
||||||
NodePath rel_path = new_root_path.rel_path_to(E->get().second);
|
NodePath rel_path = new_root_path.rel_path_to(E->get().second);
|
||||||
|
|
||||||
NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false, track_np.get_property());
|
NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
|
||||||
if (new_path == track_np)
|
if (new_path == track_np)
|
||||||
continue; //bleh
|
continue; //bleh
|
||||||
editor_data->get_undo_redo().add_do_method(anim.ptr(), "track_set_path", i, new_path);
|
editor_data->get_undo_redo().add_do_method(anim.ptr(), "track_set_path", i, new_path);
|
||||||
|
@ -93,10 +93,10 @@ godot_string GDAPI godot_node_path_get_subname(const godot_node_path *p_self, co
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
godot_string GDAPI godot_node_path_get_property(const godot_node_path *p_self) {
|
godot_string GDAPI godot_node_path_get_concatenated_subnames(const godot_node_path *p_self) {
|
||||||
godot_string dest;
|
godot_string dest;
|
||||||
const NodePath *self = (const NodePath *)p_self;
|
const NodePath *self = (const NodePath *)p_self;
|
||||||
memnew_placement(&dest, String(self->get_property()));
|
memnew_placement(&dest, String(self->get_concatenated_subnames()));
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2898,7 +2898,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "godot_node_path_get_property",
|
"name": "godot_node_path_get_concatenated_subnames",
|
||||||
"return_type": "godot_string",
|
"return_type": "godot_string",
|
||||||
"arguments": [
|
"arguments": [
|
||||||
["const godot_node_path *", "p_self"]
|
["const godot_node_path *", "p_self"]
|
||||||
|
@ -73,7 +73,7 @@ godot_int GDAPI godot_node_path_get_subname_count(const godot_node_path *p_self)
|
|||||||
|
|
||||||
godot_string GDAPI godot_node_path_get_subname(const godot_node_path *p_self, const godot_int p_idx);
|
godot_string GDAPI godot_node_path_get_subname(const godot_node_path *p_self, const godot_int p_idx);
|
||||||
|
|
||||||
godot_string GDAPI godot_node_path_get_property(const godot_node_path *p_self);
|
godot_string GDAPI godot_node_path_get_concatenated_subnames(const godot_node_path *p_self);
|
||||||
|
|
||||||
godot_bool GDAPI godot_node_path_is_empty(const godot_node_path *p_self);
|
godot_bool GDAPI godot_node_path_is_empty(const godot_node_path *p_self);
|
||||||
|
|
||||||
|
@ -87,39 +87,14 @@ void AnimationCache::_update_cache() {
|
|||||||
|
|
||||||
Ref<Resource> res;
|
Ref<Resource> res;
|
||||||
|
|
||||||
if (np.get_subname_count()) {
|
|
||||||
|
|
||||||
if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM) {
|
if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM) {
|
||||||
|
|
||||||
|
if (np.get_subname_count() > 1) {
|
||||||
path_cache.push_back(Path());
|
path_cache.push_back(Path());
|
||||||
ERR_EXPLAIN("Transform tracks can't have a subpath: " + np);
|
ERR_EXPLAIN("Transform tracks can't have a subpath: " + np);
|
||||||
ERR_CONTINUE(animation->track_get_type(i) == Animation::TYPE_TRANSFORM);
|
ERR_CONTINUE(animation->track_get_type(i) == Animation::TYPE_TRANSFORM);
|
||||||
}
|
}
|
||||||
|
|
||||||
RES res;
|
|
||||||
|
|
||||||
for (int j = 0; j < np.get_subname_count(); j++) {
|
|
||||||
res = j == 0 ? node->get(np.get_subname(j)) : res->get(np.get_subname(j));
|
|
||||||
if (res.is_null())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.is_null()) {
|
|
||||||
|
|
||||||
path_cache.push_back(Path());
|
|
||||||
ERR_EXPLAIN("Invalid Track SubPath in Animation: " + np);
|
|
||||||
ERR_CONTINUE(res.is_null());
|
|
||||||
}
|
|
||||||
|
|
||||||
path.resource = res;
|
|
||||||
path.object = res.ptr();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM) {
|
|
||||||
StringName property = np.get_property();
|
|
||||||
String ps = property;
|
|
||||||
|
|
||||||
Spatial *sp = Object::cast_to<Spatial>(node);
|
Spatial *sp = Object::cast_to<Spatial>(node);
|
||||||
|
|
||||||
if (!sp) {
|
if (!sp) {
|
||||||
@ -129,7 +104,9 @@ void AnimationCache::_update_cache() {
|
|||||||
ERR_CONTINUE(!sp);
|
ERR_CONTINUE(!sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps != "") {
|
if (np.get_subname_count() == 1) {
|
||||||
|
StringName property = np.get_subname(0);
|
||||||
|
String ps = property;
|
||||||
|
|
||||||
Skeleton *sk = Object::cast_to<Skeleton>(node);
|
Skeleton *sk = Object::cast_to<Skeleton>(node);
|
||||||
if (!sk) {
|
if (!sk) {
|
||||||
@ -141,7 +118,6 @@ void AnimationCache::_update_cache() {
|
|||||||
|
|
||||||
int idx = sk->find_bone(ps);
|
int idx = sk->find_bone(ps);
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
|
|
||||||
path_cache.push_back(Path());
|
path_cache.push_back(Path());
|
||||||
ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton Bone!: " + np);
|
ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton Bone!: " + np);
|
||||||
ERR_CONTINUE(idx == -1);
|
ERR_CONTINUE(idx == -1);
|
||||||
@ -152,30 +128,49 @@ void AnimationCache::_update_cache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
path.spatial = sp;
|
path.spatial = sp;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (np.get_subname_count() > 0) {
|
||||||
|
|
||||||
|
RES res;
|
||||||
|
Vector<StringName> leftover_subpath;
|
||||||
|
|
||||||
|
// We don't want to cache the last resource unless it is a method call
|
||||||
|
bool is_method = animation->track_get_type(i) == Animation::TYPE_METHOD;
|
||||||
|
root->get_node_and_resource(np, res, leftover_subpath, is_method);
|
||||||
|
|
||||||
|
if (res.is_valid()) {
|
||||||
|
path.resource = res;
|
||||||
|
} else {
|
||||||
|
path.node = node;
|
||||||
}
|
}
|
||||||
|
path.object = res.is_valid() ? res.ptr() : (Object *)node;
|
||||||
|
path.subpath = leftover_subpath;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
path.node = node;
|
path.node = node;
|
||||||
path.object = node;
|
path.object = node;
|
||||||
|
path.subpath = np.get_subnames();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animation->track_get_type(i) == Animation::TYPE_VALUE) {
|
if (animation->track_get_type(i) == Animation::TYPE_VALUE) {
|
||||||
|
|
||||||
if (np.get_property().operator String() == "") {
|
if (np.get_subname_count() == 0) {
|
||||||
|
|
||||||
path_cache.push_back(Path());
|
path_cache.push_back(Path());
|
||||||
ERR_EXPLAIN("Value Track lacks property: " + np);
|
ERR_EXPLAIN("Value Track lacks property: " + np);
|
||||||
ERR_CONTINUE(np.get_property().operator String() == "");
|
ERR_CONTINUE(np.get_subname_count() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
path.property = np.get_property();
|
|
||||||
|
|
||||||
} else if (animation->track_get_type(i) == Animation::TYPE_METHOD) {
|
} else if (animation->track_get_type(i) == Animation::TYPE_METHOD) {
|
||||||
|
|
||||||
if (np.get_property().operator String() != "") {
|
if (path.subpath.size() != 0) { // Trying to call a method of a non-resource
|
||||||
|
|
||||||
path_cache.push_back(Path());
|
path_cache.push_back(Path());
|
||||||
ERR_EXPLAIN("Method Track has property: " + np);
|
ERR_EXPLAIN("Method Track has property: " + np);
|
||||||
ERR_CONTINUE(np.get_property().operator String() != "");
|
ERR_CONTINUE(path.subpath.size() != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +221,7 @@ void AnimationCache::set_track_value(int p_idx, const Variant &p_value) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ERR_FAIL_COND(!p.object);
|
ERR_FAIL_COND(!p.object);
|
||||||
p.object->set(p.property, p_value);
|
p.object->set_indexed(p.subpath, p_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationCache::call_track(int p_idx, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
|
void AnimationCache::call_track(int p_idx, const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
|
||||||
|
@ -46,7 +46,7 @@ class AnimationCache : public Object {
|
|||||||
Spatial *spatial;
|
Spatial *spatial;
|
||||||
|
|
||||||
int bone_idx;
|
int bone_idx;
|
||||||
StringName property;
|
Vector<StringName> subpath;
|
||||||
bool valid;
|
bool valid;
|
||||||
Path() {
|
Path() {
|
||||||
object = NULL;
|
object = NULL;
|
||||||
|
@ -242,7 +242,8 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
|
|||||||
|
|
||||||
p_anim->node_cache[i] = NULL;
|
p_anim->node_cache[i] = NULL;
|
||||||
RES resource;
|
RES resource;
|
||||||
Node *child = parent->get_node_and_resource(a->track_get_path(i), resource);
|
Vector<StringName> leftover_path;
|
||||||
|
Node *child = parent->get_node_and_resource(a->track_get_path(i), resource, leftover_path);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
ERR_EXPLAIN("On Animation: '" + p_anim->name + "', couldn't resolve track: '" + String(a->track_get_path(i)) + "'");
|
ERR_EXPLAIN("On Animation: '" + p_anim->name + "', couldn't resolve track: '" + String(a->track_get_path(i)) + "'");
|
||||||
}
|
}
|
||||||
@ -250,9 +251,9 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
|
|||||||
uint32_t id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id();
|
uint32_t id = resource.is_valid() ? resource->get_instance_id() : child->get_instance_id();
|
||||||
int bone_idx = -1;
|
int bone_idx = -1;
|
||||||
|
|
||||||
if (a->track_get_path(i).get_property() && Object::cast_to<Skeleton>(child)) {
|
if (a->track_get_path(i).get_subname_count() == 1 && Object::cast_to<Skeleton>(child)) {
|
||||||
|
|
||||||
bone_idx = Object::cast_to<Skeleton>(child)->find_bone(a->track_get_path(i).get_property());
|
bone_idx = Object::cast_to<Skeleton>(child)->find_bone(a->track_get_path(i).get_subname(0));
|
||||||
if (bone_idx == -1) {
|
if (bone_idx == -1) {
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -289,8 +290,8 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
|
|||||||
p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton>(child);
|
p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton>(child);
|
||||||
if (p_anim->node_cache[i]->skeleton) {
|
if (p_anim->node_cache[i]->skeleton) {
|
||||||
|
|
||||||
StringName bone_name = a->track_get_path(i).get_property();
|
if (a->track_get_path(i).get_subname_count() == 1) {
|
||||||
if (bone_name.operator String() != "") {
|
StringName bone_name = a->track_get_path(i).get_subname(0);
|
||||||
|
|
||||||
p_anim->node_cache[i]->bone_idx = p_anim->node_cache[i]->skeleton->find_bone(bone_name);
|
p_anim->node_cache[i]->bone_idx = p_anim->node_cache[i]->skeleton->find_bone(bone_name);
|
||||||
if (p_anim->node_cache[i]->bone_idx < 0) {
|
if (p_anim->node_cache[i]->bone_idx < 0) {
|
||||||
@ -311,24 +312,23 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) {
|
|||||||
|
|
||||||
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
|
if (a->track_get_type(i) == Animation::TYPE_VALUE) {
|
||||||
|
|
||||||
StringName property = a->track_get_path(i).get_property();
|
if (!p_anim->node_cache[i]->property_anim.has(a->track_get_path(i).get_concatenated_subnames())) {
|
||||||
if (!p_anim->node_cache[i]->property_anim.has(property)) {
|
|
||||||
|
|
||||||
TrackNodeCache::PropertyAnim pa;
|
TrackNodeCache::PropertyAnim pa;
|
||||||
pa.prop = property;
|
pa.subpath = leftover_path;
|
||||||
pa.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child;
|
pa.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child;
|
||||||
pa.special = SP_NONE;
|
pa.special = SP_NONE;
|
||||||
pa.owner = p_anim->node_cache[i];
|
pa.owner = p_anim->node_cache[i];
|
||||||
if (false && p_anim->node_cache[i]->node_2d) {
|
if (false && p_anim->node_cache[i]->node_2d) {
|
||||||
|
|
||||||
if (pa.prop == SceneStringNames::get_singleton()->transform_pos)
|
if (leftover_path.size() == 1 && leftover_path[0] == SceneStringNames::get_singleton()->transform_pos)
|
||||||
pa.special = SP_NODE2D_POS;
|
pa.special = SP_NODE2D_POS;
|
||||||
else if (pa.prop == SceneStringNames::get_singleton()->transform_rot)
|
else if (leftover_path.size() == 1 && leftover_path[0] == SceneStringNames::get_singleton()->transform_rot)
|
||||||
pa.special = SP_NODE2D_ROT;
|
pa.special = SP_NODE2D_ROT;
|
||||||
else if (pa.prop == SceneStringNames::get_singleton()->transform_scale)
|
else if (leftover_path.size() == 1 && leftover_path[0] == SceneStringNames::get_singleton()->transform_scale)
|
||||||
pa.special = SP_NODE2D_SCALE;
|
pa.special = SP_NODE2D_SCALE;
|
||||||
}
|
}
|
||||||
p_anim->node_cache[i]->property_anim[property] = pa;
|
p_anim->node_cache[i]->property_anim[a->track_get_path(i).get_concatenated_subnames()] = pa;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
|
|||||||
|
|
||||||
//StringName property=a->track_get_path(i).get_property();
|
//StringName property=a->track_get_path(i).get_property();
|
||||||
|
|
||||||
Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.find(a->track_get_path(i).get_property());
|
Map<StringName, TrackNodeCache::PropertyAnim>::Element *E = nc->property_anim.find(a->track_get_path(i).get_concatenated_subnames());
|
||||||
ERR_CONTINUE(!E); //should it continue, or create a new one?
|
ERR_CONTINUE(!E); //should it continue, or create a new one?
|
||||||
|
|
||||||
TrackNodeCache::PropertyAnim *pa = &E->get();
|
TrackNodeCache::PropertyAnim *pa = &E->get();
|
||||||
@ -434,7 +434,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
|
|||||||
|
|
||||||
case SP_NONE: {
|
case SP_NONE: {
|
||||||
bool valid;
|
bool valid;
|
||||||
pa->object->set(pa->prop, value, &valid); //you are not speshul
|
pa->object->set_indexed(pa->subpath, value, &valid); //you are not speshul
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
|
ERR_PRINTS("Failed setting track value '" + String(pa->owner->path) + "'. Check if property exists or the type of key is valid. Animation '" + a->get_name() + "' at node '" + get_path() + "'.");
|
||||||
@ -615,7 +615,7 @@ void AnimationPlayer::_animation_update_transforms() {
|
|||||||
|
|
||||||
case SP_NONE: {
|
case SP_NONE: {
|
||||||
bool valid;
|
bool valid;
|
||||||
pa->object->set(pa->prop, pa->value_accum, &valid); //you are not speshul
|
pa->object->set_indexed(pa->subpath, pa->value_accum, &valid); //you are not speshul
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
ERR_PRINTS("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property");
|
ERR_PRINTS("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property");
|
||||||
|
@ -83,7 +83,7 @@ private:
|
|||||||
|
|
||||||
TrackNodeCache *owner;
|
TrackNodeCache *owner;
|
||||||
SpecialProperty special; //small optimization
|
SpecialProperty special; //small optimization
|
||||||
StringName prop;
|
Vector<StringName> subpath;
|
||||||
Object *object;
|
Object *object;
|
||||||
Variant value_accum;
|
Variant value_accum;
|
||||||
uint64_t accum_pass;
|
uint64_t accum_pass;
|
||||||
|
@ -811,7 +811,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
|
|||||||
t.scale.y = 0;
|
t.scale.y = 0;
|
||||||
t.scale.z = 0;
|
t.scale.z = 0;
|
||||||
|
|
||||||
t.value = t.object->get(t.property);
|
t.value = t.object->get_indexed(t.subpath);
|
||||||
t.value.zero();
|
t.value.zero();
|
||||||
|
|
||||||
t.skip = false;
|
t.skip = false;
|
||||||
@ -890,8 +890,8 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
|
|||||||
if (t.skip || !t.object)
|
if (t.skip || !t.object)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (t.property) { // value track
|
if (t.subpath.size()) { // value track
|
||||||
t.object->set(t.property, t.value);
|
t.object->set_indexed(t.subpath, t.value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,7 +1475,8 @@ AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_p
|
|||||||
ERR_FAIL_COND_V(!parent, NULL);
|
ERR_FAIL_COND_V(!parent, NULL);
|
||||||
|
|
||||||
RES resource;
|
RES resource;
|
||||||
Node *child = parent->get_node_and_resource(p_path, resource);
|
Vector<StringName> leftover_path;
|
||||||
|
Node *child = parent->get_node_and_resource(p_path, resource, leftover_path);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
String err = "Animation track references unknown Node: '" + String(p_path) + "'.";
|
String err = "Animation track references unknown Node: '" + String(p_path) + "'.";
|
||||||
WARN_PRINT(err.ascii().get_data());
|
WARN_PRINT(err.ascii().get_data());
|
||||||
@ -1483,21 +1484,18 @@ AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_p
|
|||||||
}
|
}
|
||||||
|
|
||||||
ObjectID id = child->get_instance_id();
|
ObjectID id = child->get_instance_id();
|
||||||
StringName property;
|
|
||||||
int bone_idx = -1;
|
int bone_idx = -1;
|
||||||
|
|
||||||
if (p_path.get_property()) {
|
if (p_path.get_subname_count()) {
|
||||||
|
|
||||||
if (Object::cast_to<Skeleton>(child))
|
if (Object::cast_to<Skeleton>(child))
|
||||||
bone_idx = Object::cast_to<Skeleton>(child)->find_bone(p_path.get_property());
|
bone_idx = Object::cast_to<Skeleton>(child)->find_bone(p_path.get_subname(0));
|
||||||
if (bone_idx == -1)
|
|
||||||
property = p_path.get_property();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackKey key;
|
TrackKey key;
|
||||||
key.id = id;
|
key.id = id;
|
||||||
key.bone_idx = bone_idx;
|
key.bone_idx = bone_idx;
|
||||||
key.property = property;
|
key.subpath_concatenated = p_path.get_concatenated_subnames();
|
||||||
|
|
||||||
if (!track_map.has(key)) {
|
if (!track_map.has(key)) {
|
||||||
|
|
||||||
@ -1507,7 +1505,7 @@ AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_p
|
|||||||
tr.skeleton = Object::cast_to<Skeleton>(child);
|
tr.skeleton = Object::cast_to<Skeleton>(child);
|
||||||
tr.spatial = Object::cast_to<Spatial>(child);
|
tr.spatial = Object::cast_to<Spatial>(child);
|
||||||
tr.bone_idx = bone_idx;
|
tr.bone_idx = bone_idx;
|
||||||
tr.property = property;
|
if (bone_idx == -1) tr.subpath = leftover_path;
|
||||||
|
|
||||||
track_map[key] = tr;
|
track_map[key] = tr;
|
||||||
}
|
}
|
||||||
|
@ -78,14 +78,14 @@ private:
|
|||||||
struct TrackKey {
|
struct TrackKey {
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
StringName property;
|
StringName subpath_concatenated;
|
||||||
int bone_idx;
|
int bone_idx;
|
||||||
|
|
||||||
inline bool operator<(const TrackKey &p_right) const {
|
inline bool operator<(const TrackKey &p_right) const {
|
||||||
|
|
||||||
if (id == p_right.id) {
|
if (id == p_right.id) {
|
||||||
if (bone_idx == p_right.bone_idx) {
|
if (bone_idx == p_right.bone_idx) {
|
||||||
return property < p_right.property;
|
return subpath_concatenated < p_right.subpath_concatenated;
|
||||||
} else
|
} else
|
||||||
return bone_idx < p_right.bone_idx;
|
return bone_idx < p_right.bone_idx;
|
||||||
} else
|
} else
|
||||||
@ -99,7 +99,7 @@ private:
|
|||||||
Spatial *spatial;
|
Spatial *spatial;
|
||||||
Skeleton *skeleton;
|
Skeleton *skeleton;
|
||||||
int bone_idx;
|
int bone_idx;
|
||||||
StringName property;
|
Vector<StringName> subpath;
|
||||||
|
|
||||||
Vector3 loc;
|
Vector3 loc;
|
||||||
Quat rot;
|
Quat rot;
|
||||||
|
@ -264,12 +264,12 @@ Variant &Tween::_get_initial_val(InterpolateData &p_data) {
|
|||||||
if (p_data.type == TARGETING_PROPERTY) {
|
if (p_data.type == TARGETING_PROPERTY) {
|
||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
initial_val = object->get(p_data.target_key, &valid);
|
initial_val = object->get_indexed(p_data.target_key, &valid);
|
||||||
ERR_FAIL_COND_V(!valid, p_data.initial_val);
|
ERR_FAIL_COND_V(!valid, p_data.initial_val);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Variant::CallError error;
|
Variant::CallError error;
|
||||||
initial_val = object->call(p_data.target_key, NULL, 0, error);
|
initial_val = object->call(p_data.target_key[0], NULL, 0, error);
|
||||||
ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val);
|
ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val);
|
||||||
}
|
}
|
||||||
return initial_val;
|
return initial_val;
|
||||||
@ -296,12 +296,12 @@ Variant &Tween::_get_delta_val(InterpolateData &p_data) {
|
|||||||
if (p_data.type == FOLLOW_PROPERTY) {
|
if (p_data.type == FOLLOW_PROPERTY) {
|
||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
final_val = target->get(p_data.target_key, &valid);
|
final_val = target->get_indexed(p_data.target_key, &valid);
|
||||||
ERR_FAIL_COND_V(!valid, p_data.initial_val);
|
ERR_FAIL_COND_V(!valid, p_data.initial_val);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Variant::CallError error;
|
Variant::CallError error;
|
||||||
final_val = target->call(p_data.target_key, NULL, 0, error);
|
final_val = target->call(p_data.target_key[0], NULL, 0, error);
|
||||||
ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val);
|
ERR_FAIL_COND_V(error.error != Variant::CallError::CALL_OK, p_data.initial_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +462,9 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
|||||||
|
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
default: {
|
||||||
|
result = initial_val;
|
||||||
|
} break;
|
||||||
};
|
};
|
||||||
#undef APPLY_EQUATION
|
#undef APPLY_EQUATION
|
||||||
|
|
||||||
@ -479,7 +482,7 @@ bool Tween::_apply_tween_value(InterpolateData &p_data, Variant &value) {
|
|||||||
case FOLLOW_PROPERTY:
|
case FOLLOW_PROPERTY:
|
||||||
case TARGETING_PROPERTY: {
|
case TARGETING_PROPERTY: {
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
object->set(p_data.key, value, &valid);
|
object->set_indexed(p_data.key, value, &valid);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,9 +492,9 @@ bool Tween::_apply_tween_value(InterpolateData &p_data, Variant &value) {
|
|||||||
Variant::CallError error;
|
Variant::CallError error;
|
||||||
if (value.get_type() != Variant::NIL) {
|
if (value.get_type() != Variant::NIL) {
|
||||||
Variant *arg[1] = { &value };
|
Variant *arg[1] = { &value };
|
||||||
object->call(p_data.key, (const Variant **)arg, 1, error);
|
object->call(p_data.key[0], (const Variant **)arg, 1, error);
|
||||||
} else {
|
} else {
|
||||||
object->call(p_data.key, NULL, 0, error);
|
object->call(p_data.key[0], NULL, 0, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error.error == Variant::CallError::CALL_OK)
|
if (error.error == Variant::CallError::CALL_OK)
|
||||||
@ -548,7 +551,7 @@ void Tween::_tween_process(float p_delta) {
|
|||||||
continue;
|
continue;
|
||||||
else if (prev_delaying) {
|
else if (prev_delaying) {
|
||||||
|
|
||||||
emit_signal("tween_started", object, data.key);
|
emit_signal("tween_started", object, NodePath(Vector<StringName>(), data.key, false));
|
||||||
_apply_tween_value(data, data.initial_val);
|
_apply_tween_value(data, data.initial_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,7 +565,7 @@ void Tween::_tween_process(float p_delta) {
|
|||||||
case INTER_PROPERTY:
|
case INTER_PROPERTY:
|
||||||
case INTER_METHOD: {
|
case INTER_METHOD: {
|
||||||
Variant result = _run_equation(data);
|
Variant result = _run_equation(data);
|
||||||
emit_signal("tween_step", object, data.key, data.elapsed, result);
|
emit_signal("tween_step", object, NodePath(Vector<StringName>(), data.key, false), data.elapsed, result);
|
||||||
_apply_tween_value(data, result);
|
_apply_tween_value(data, result);
|
||||||
if (data.finish)
|
if (data.finish)
|
||||||
_apply_tween_value(data, data.final_val);
|
_apply_tween_value(data, data.final_val);
|
||||||
@ -574,22 +577,22 @@ void Tween::_tween_process(float p_delta) {
|
|||||||
|
|
||||||
switch (data.args) {
|
switch (data.args) {
|
||||||
case 0:
|
case 0:
|
||||||
object->call_deferred(data.key);
|
object->call_deferred(data.key[0]);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
object->call_deferred(data.key, data.arg[0]);
|
object->call_deferred(data.key[0], data.arg[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
object->call_deferred(data.key, data.arg[0], data.arg[1]);
|
object->call_deferred(data.key[0], data.arg[0], data.arg[1]);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2]);
|
object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2]);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3]);
|
object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3]);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
object->call_deferred(data.key, data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]);
|
object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -601,17 +604,18 @@ void Tween::_tween_process(float p_delta) {
|
|||||||
&data.arg[3],
|
&data.arg[3],
|
||||||
&data.arg[4],
|
&data.arg[4],
|
||||||
};
|
};
|
||||||
object->call(data.key, (const Variant **)arg, data.args, error);
|
object->call(data.key[0], (const Variant **)arg, data.args, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.finish) {
|
if (data.finish) {
|
||||||
emit_signal("tween_completed", object, data.key);
|
emit_signal("tween_completed", object, NodePath(Vector<StringName>(), data.key, false));
|
||||||
// not repeat mode, remove completed action
|
// not repeat mode, remove completed action
|
||||||
if (!repeat)
|
if (!repeat)
|
||||||
call_deferred("_remove", object, data.key, true);
|
call_deferred("_remove", object, NodePath(Vector<StringName>(), data.key, false), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pending_update--;
|
pending_update--;
|
||||||
@ -690,7 +694,7 @@ bool Tween::start() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::reset(Object *p_object, String p_key) {
|
bool Tween::reset(Object *p_object, StringName p_key) {
|
||||||
|
|
||||||
pending_update++;
|
pending_update++;
|
||||||
for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
|
for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
|
||||||
@ -700,7 +704,7 @@ bool Tween::reset(Object *p_object, String p_key) {
|
|||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (object == p_object && (data.key == p_key || p_key == "")) {
|
if (object == p_object && (data.concatenated_key == p_key || p_key == "")) {
|
||||||
|
|
||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
data.finish = false;
|
data.finish = false;
|
||||||
@ -727,7 +731,7 @@ bool Tween::reset_all() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::stop(Object *p_object, String p_key) {
|
bool Tween::stop(Object *p_object, StringName p_key) {
|
||||||
|
|
||||||
pending_update++;
|
pending_update++;
|
||||||
for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
|
for (List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) {
|
||||||
@ -736,7 +740,7 @@ bool Tween::stop(Object *p_object, String p_key) {
|
|||||||
Object *object = ObjectDB::get_instance(data.id);
|
Object *object = ObjectDB::get_instance(data.id);
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (object == p_object && (data.key == p_key || p_key == ""))
|
if (object == p_object && (data.concatenated_key == p_key || p_key == ""))
|
||||||
data.active = false;
|
data.active = false;
|
||||||
}
|
}
|
||||||
pending_update--;
|
pending_update--;
|
||||||
@ -758,7 +762,7 @@ bool Tween::stop_all() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::resume(Object *p_object, String p_key) {
|
bool Tween::resume(Object *p_object, StringName p_key) {
|
||||||
|
|
||||||
set_active(true);
|
set_active(true);
|
||||||
_set_process(true);
|
_set_process(true);
|
||||||
@ -770,7 +774,7 @@ bool Tween::resume(Object *p_object, String p_key) {
|
|||||||
Object *object = ObjectDB::get_instance(data.id);
|
Object *object = ObjectDB::get_instance(data.id);
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (object == p_object && (data.key == p_key || p_key == ""))
|
if (object == p_object && (data.concatenated_key == p_key || p_key == ""))
|
||||||
data.active = true;
|
data.active = true;
|
||||||
}
|
}
|
||||||
pending_update--;
|
pending_update--;
|
||||||
@ -792,12 +796,12 @@ bool Tween::resume_all() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::remove(Object *p_object, String p_key) {
|
bool Tween::remove(Object *p_object, StringName p_key) {
|
||||||
_remove(p_object, p_key, false);
|
_remove(p_object, p_key, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tween::_remove(Object *p_object, String p_key, bool first_only) {
|
void Tween::_remove(Object *p_object, StringName p_key, bool first_only) {
|
||||||
|
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
call_deferred("_remove", p_object, p_key, first_only);
|
call_deferred("_remove", p_object, p_key, first_only);
|
||||||
@ -810,7 +814,7 @@ void Tween::_remove(Object *p_object, String p_key, bool first_only) {
|
|||||||
Object *object = ObjectDB::get_instance(data.id);
|
Object *object = ObjectDB::get_instance(data.id);
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (object == p_object && (data.key == p_key || p_key == "")) {
|
if (object == p_object && (data.concatenated_key == p_key || p_key == "")) {
|
||||||
for_removal.push_back(E);
|
for_removal.push_back(E);
|
||||||
if (first_only) {
|
if (first_only) {
|
||||||
break;
|
break;
|
||||||
@ -850,8 +854,9 @@ bool Tween::seek(real_t p_time) {
|
|||||||
|
|
||||||
data.finish = true;
|
data.finish = true;
|
||||||
data.elapsed = (data.delay + data.duration);
|
data.elapsed = (data.delay + data.duration);
|
||||||
} else
|
} else {
|
||||||
data.finish = false;
|
data.finish = false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case INTER_PROPERTY:
|
case INTER_PROPERTY:
|
||||||
@ -993,12 +998,14 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::interpolate_property(Object *p_object, NodePath p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("interpolate_property", p_object, p_property, p_initial_val, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("interpolate_property", p_object, p_property, p_initial_val, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (p_initial_val.get_type() == Variant::NIL) p_initial_val = p_object->get(p_property);
|
p_property = p_property.get_as_property_path();
|
||||||
|
|
||||||
|
if (p_initial_val.get_type() == Variant::NIL) p_initial_val = p_object->get_indexed(p_property.get_subnames());
|
||||||
|
|
||||||
// convert INT to REAL is better for interpolaters
|
// convert INT to REAL is better for interpolaters
|
||||||
if (p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
if (p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||||
@ -1013,7 +1020,7 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_
|
|||||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||||
|
|
||||||
bool prop_valid = false;
|
bool prop_valid = false;
|
||||||
p_object->get(p_property, &prop_valid);
|
p_object->get_indexed(p_property.get_subnames(), &prop_valid);
|
||||||
ERR_FAIL_COND_V(!prop_valid, false);
|
ERR_FAIL_COND_V(!prop_valid, false);
|
||||||
|
|
||||||
InterpolateData data;
|
InterpolateData data;
|
||||||
@ -1023,7 +1030,8 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_property;
|
data.key = p_property.get_subnames();
|
||||||
|
data.concatenated_key = p_property.get_concatenated_subnames();
|
||||||
data.initial_val = p_initial_val;
|
data.initial_val = p_initial_val;
|
||||||
data.final_val = p_final_val;
|
data.final_val = p_final_val;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
@ -1038,7 +1046,7 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::interpolate_method(Object *p_object, String p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::interpolate_method(Object *p_object, StringName p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("interpolate_method", p_object, p_method, p_initial_val, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("interpolate_method", p_object, p_method, p_initial_val, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
@ -1065,7 +1073,8 @@ bool Tween::interpolate_method(Object *p_object, String p_method, Variant p_init
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_method;
|
data.key.push_back(p_method);
|
||||||
|
data.concatenated_key = p_method;
|
||||||
data.initial_val = p_initial_val;
|
data.initial_val = p_initial_val;
|
||||||
data.final_val = p_final_val;
|
data.final_val = p_final_val;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
@ -1102,7 +1111,8 @@ bool Tween::interpolate_callback(Object *p_object, real_t p_duration, String p_c
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_callback;
|
data.key.push_back(p_callback);
|
||||||
|
data.concatenated_key = p_callback;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
data.delay = 0;
|
data.delay = 0;
|
||||||
|
|
||||||
@ -1154,7 +1164,8 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_callback;
|
data.key.push_back(p_callback);
|
||||||
|
data.concatenated_key = p_callback;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
data.delay = 0;
|
data.delay = 0;
|
||||||
|
|
||||||
@ -1185,12 +1196,15 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::follow_property(Object *p_object, String p_property, Variant p_initial_val, Object *p_target, String p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::follow_property(Object *p_object, NodePath p_property, Variant p_initial_val, Object *p_target, NodePath p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("follow_property", p_object, p_property, p_initial_val, p_target, p_target_property, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("follow_property", p_object, p_property, p_initial_val, p_target, p_target_property, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (p_initial_val.get_type() == Variant::NIL) p_initial_val = p_object->get(p_initial_val);
|
p_property = p_property.get_as_property_path();
|
||||||
|
p_target_property = p_target_property.get_as_property_path();
|
||||||
|
|
||||||
|
if (p_initial_val.get_type() == Variant::NIL) p_initial_val = p_object->get_indexed(p_property.get_subnames());
|
||||||
|
|
||||||
// convert INT to REAL is better for interpolaters
|
// convert INT to REAL is better for interpolaters
|
||||||
if (p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
if (p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t();
|
||||||
@ -1205,11 +1219,11 @@ bool Tween::follow_property(Object *p_object, String p_property, Variant p_initi
|
|||||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||||
|
|
||||||
bool prop_valid = false;
|
bool prop_valid = false;
|
||||||
p_object->get(p_property, &prop_valid);
|
p_object->get_indexed(p_property.get_subnames(), &prop_valid);
|
||||||
ERR_FAIL_COND_V(!prop_valid, false);
|
ERR_FAIL_COND_V(!prop_valid, false);
|
||||||
|
|
||||||
bool target_prop_valid = false;
|
bool target_prop_valid = false;
|
||||||
Variant target_val = p_target->get(p_target_property, &target_prop_valid);
|
Variant target_val = p_target->get_indexed(p_target_property.get_subnames(), &target_prop_valid);
|
||||||
ERR_FAIL_COND_V(!target_prop_valid, false);
|
ERR_FAIL_COND_V(!target_prop_valid, false);
|
||||||
|
|
||||||
// convert INT to REAL is better for interpolaters
|
// convert INT to REAL is better for interpolaters
|
||||||
@ -1223,10 +1237,11 @@ bool Tween::follow_property(Object *p_object, String p_property, Variant p_initi
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_property;
|
data.key = p_property.get_subnames();
|
||||||
|
data.concatenated_key = p_property.get_concatenated_subnames();
|
||||||
data.initial_val = p_initial_val;
|
data.initial_val = p_initial_val;
|
||||||
data.target_id = p_target->get_instance_id();
|
data.target_id = p_target->get_instance_id();
|
||||||
data.target_key = p_target_property;
|
data.target_key = p_target_property.get_subnames();
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
data.trans_type = p_trans_type;
|
data.trans_type = p_trans_type;
|
||||||
data.ease_type = p_ease_type;
|
data.ease_type = p_ease_type;
|
||||||
@ -1236,7 +1251,7 @@ bool Tween::follow_property(Object *p_object, String p_property, Variant p_initi
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::follow_method(Object *p_object, String p_method, Variant p_initial_val, Object *p_target, String p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::follow_method(Object *p_object, StringName p_method, Variant p_initial_val, Object *p_target, StringName p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("follow_method", p_object, p_method, p_initial_val, p_target, p_target_method, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("follow_method", p_object, p_method, p_initial_val, p_target, p_target_method, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
@ -1273,10 +1288,11 @@ bool Tween::follow_method(Object *p_object, String p_method, Variant p_initial_v
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_method;
|
data.key.push_back(p_method);
|
||||||
|
data.concatenated_key = p_method;
|
||||||
data.initial_val = p_initial_val;
|
data.initial_val = p_initial_val;
|
||||||
data.target_id = p_target->get_instance_id();
|
data.target_id = p_target->get_instance_id();
|
||||||
data.target_key = p_target_method;
|
data.target_key.push_back(p_target_method);
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
data.trans_type = p_trans_type;
|
data.trans_type = p_trans_type;
|
||||||
data.ease_type = p_ease_type;
|
data.ease_type = p_ease_type;
|
||||||
@ -1286,11 +1302,15 @@ bool Tween::follow_method(Object *p_object, String p_method, Variant p_initial_v
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::targeting_property(Object *p_object, String p_property, Object *p_initial, String p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::targeting_property(Object *p_object, NodePath p_property, Object *p_initial, NodePath p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
|
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("targeting_property", p_object, p_property, p_initial, p_initial_property, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("targeting_property", p_object, p_property, p_initial, p_initial_property, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
p_property = p_property.get_as_property_path();
|
||||||
|
p_initial_property = p_initial_property.get_as_property_path();
|
||||||
|
|
||||||
// convert INT to REAL is better for interpolaters
|
// convert INT to REAL is better for interpolaters
|
||||||
if (p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
if (p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t();
|
||||||
|
|
||||||
@ -1304,11 +1324,11 @@ bool Tween::targeting_property(Object *p_object, String p_property, Object *p_in
|
|||||||
ERR_FAIL_COND_V(p_delay < 0, false);
|
ERR_FAIL_COND_V(p_delay < 0, false);
|
||||||
|
|
||||||
bool prop_valid = false;
|
bool prop_valid = false;
|
||||||
p_object->get(p_property, &prop_valid);
|
p_object->get_indexed(p_property.get_subnames(), &prop_valid);
|
||||||
ERR_FAIL_COND_V(!prop_valid, false);
|
ERR_FAIL_COND_V(!prop_valid, false);
|
||||||
|
|
||||||
bool initial_prop_valid = false;
|
bool initial_prop_valid = false;
|
||||||
Variant initial_val = p_initial->get(p_initial_property, &initial_prop_valid);
|
Variant initial_val = p_initial->get_indexed(p_initial_property.get_subnames(), &initial_prop_valid);
|
||||||
ERR_FAIL_COND_V(!initial_prop_valid, false);
|
ERR_FAIL_COND_V(!initial_prop_valid, false);
|
||||||
|
|
||||||
// convert INT to REAL is better for interpolaters
|
// convert INT to REAL is better for interpolaters
|
||||||
@ -1322,9 +1342,10 @@ bool Tween::targeting_property(Object *p_object, String p_property, Object *p_in
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_property;
|
data.key = p_property.get_subnames();
|
||||||
|
data.concatenated_key = p_property.get_concatenated_subnames();
|
||||||
data.target_id = p_initial->get_instance_id();
|
data.target_id = p_initial->get_instance_id();
|
||||||
data.target_key = p_initial_property;
|
data.target_key = p_initial_property.get_subnames();
|
||||||
data.initial_val = initial_val;
|
data.initial_val = initial_val;
|
||||||
data.final_val = p_final_val;
|
data.final_val = p_final_val;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
@ -1339,7 +1360,7 @@ bool Tween::targeting_property(Object *p_object, String p_property, Object *p_in
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tween::targeting_method(Object *p_object, String p_method, Object *p_initial, String p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
bool Tween::targeting_method(Object *p_object, StringName p_method, Object *p_initial, StringName p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay) {
|
||||||
if (pending_update != 0) {
|
if (pending_update != 0) {
|
||||||
_add_pending_command("targeting_method", p_object, p_method, p_initial, p_initial_method, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
_add_pending_command("targeting_method", p_object, p_method, p_initial, p_initial_method, p_final_val, p_duration, p_trans_type, p_ease_type, p_delay);
|
||||||
return true;
|
return true;
|
||||||
@ -1376,9 +1397,10 @@ bool Tween::targeting_method(Object *p_object, String p_method, Object *p_initia
|
|||||||
data.elapsed = 0;
|
data.elapsed = 0;
|
||||||
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
data.key = p_method;
|
data.key.push_back(p_method);
|
||||||
|
data.concatenated_key = p_method;
|
||||||
data.target_id = p_initial->get_instance_id();
|
data.target_id = p_initial->get_instance_id();
|
||||||
data.target_key = p_initial_method;
|
data.target_key.push_back(p_initial_method);
|
||||||
data.initial_val = initial_val;
|
data.initial_val = initial_val;
|
||||||
data.final_val = p_final_val;
|
data.final_val = p_final_val;
|
||||||
data.duration = p_duration;
|
data.duration = p_duration;
|
||||||
|
@ -86,12 +86,13 @@ private:
|
|||||||
bool call_deferred;
|
bool call_deferred;
|
||||||
real_t elapsed;
|
real_t elapsed;
|
||||||
ObjectID id;
|
ObjectID id;
|
||||||
StringName key;
|
Vector<StringName> key;
|
||||||
|
StringName concatenated_key;
|
||||||
Variant initial_val;
|
Variant initial_val;
|
||||||
Variant delta_val;
|
Variant delta_val;
|
||||||
Variant final_val;
|
Variant final_val;
|
||||||
ObjectID target_id;
|
ObjectID target_id;
|
||||||
StringName target_key;
|
Vector<StringName> target_key;
|
||||||
real_t duration;
|
real_t duration;
|
||||||
TransitionType trans_type;
|
TransitionType trans_type;
|
||||||
EaseType ease_type;
|
EaseType ease_type;
|
||||||
@ -132,7 +133,7 @@ private:
|
|||||||
|
|
||||||
void _tween_process(float p_delta);
|
void _tween_process(float p_delta);
|
||||||
void _set_process(bool p_process, bool p_force = false);
|
void _set_process(bool p_process, bool p_force = false);
|
||||||
void _remove(Object *p_object, String p_key, bool first_only);
|
void _remove(Object *p_object, StringName p_key, bool first_only);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _set(const StringName &p_name, const Variant &p_value);
|
bool _set(const StringName &p_name, const Variant &p_value);
|
||||||
@ -156,34 +157,34 @@ public:
|
|||||||
float get_speed_scale() const;
|
float get_speed_scale() const;
|
||||||
|
|
||||||
bool start();
|
bool start();
|
||||||
bool reset(Object *p_object, String p_key);
|
bool reset(Object *p_object, StringName p_key);
|
||||||
bool reset_all();
|
bool reset_all();
|
||||||
bool stop(Object *p_object, String p_key);
|
bool stop(Object *p_object, StringName p_key);
|
||||||
bool stop_all();
|
bool stop_all();
|
||||||
bool resume(Object *p_object, String p_key);
|
bool resume(Object *p_object, StringName p_key);
|
||||||
bool resume_all();
|
bool resume_all();
|
||||||
bool remove(Object *p_object, String p_key);
|
bool remove(Object *p_object, StringName p_key);
|
||||||
bool remove_all();
|
bool remove_all();
|
||||||
|
|
||||||
bool seek(real_t p_time);
|
bool seek(real_t p_time);
|
||||||
real_t tell() const;
|
real_t tell() const;
|
||||||
real_t get_runtime() const;
|
real_t get_runtime() const;
|
||||||
|
|
||||||
bool interpolate_property(Object *p_object, String p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool interpolate_property(Object *p_object, NodePath p_property, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
bool interpolate_method(Object *p_object, String p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool interpolate_method(Object *p_object, StringName p_method, Variant p_initial_val, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
bool interpolate_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
|
bool interpolate_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
|
||||||
|
|
||||||
bool interpolate_deferred_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
|
bool interpolate_deferred_callback(Object *p_object, real_t p_duration, String p_callback, VARIANT_ARG_DECLARE);
|
||||||
|
|
||||||
bool follow_property(Object *p_object, String p_property, Variant p_initial_val, Object *p_target, String p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool follow_property(Object *p_object, NodePath p_property, Variant p_initial_val, Object *p_target, NodePath p_target_property, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
bool follow_method(Object *p_object, String p_method, Variant p_initial_val, Object *p_target, String p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool follow_method(Object *p_object, StringName p_method, Variant p_initial_val, Object *p_target, StringName p_target_method, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
bool targeting_property(Object *p_object, String p_property, Object *p_initial, String p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool targeting_property(Object *p_object, NodePath p_property, Object *p_initial, NodePath p_initial_property, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
bool targeting_method(Object *p_object, String p_method, Object *p_initial, String p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
bool targeting_method(Object *p_object, StringName p_method, Object *p_initial, StringName p_initial_method, Variant p_final_val, real_t p_duration, TransitionType p_trans_type, EaseType p_ease_type, real_t p_delay = 0);
|
||||||
|
|
||||||
Tween();
|
Tween();
|
||||||
~Tween();
|
~Tween();
|
||||||
|
@ -2466,24 +2466,19 @@ bool Node::has_node_and_resource(const NodePath &p_path) const {
|
|||||||
return false;
|
return false;
|
||||||
Node *node = get_node(p_path);
|
Node *node = get_node(p_path);
|
||||||
|
|
||||||
if (p_path.get_subname_count()) {
|
bool result = false;
|
||||||
|
|
||||||
RES r;
|
node->get_indexed(p_path.get_subnames(), &result);
|
||||||
for (int j = 0; j < p_path.get_subname_count(); j++) {
|
|
||||||
r = j == 0 ? node->get(p_path.get_subname(j)) : r->get(p_path.get_subname(j));
|
|
||||||
if (r.is_null())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array Node::_get_node_and_resource(const NodePath &p_path) {
|
Array Node::_get_node_and_resource(const NodePath &p_path) {
|
||||||
|
|
||||||
Node *node;
|
Node *node;
|
||||||
RES res;
|
RES res;
|
||||||
node = get_node_and_resource(p_path, res);
|
Vector<StringName> leftover_path;
|
||||||
|
node = get_node_and_resource(p_path, res, leftover_path);
|
||||||
Array result;
|
Array result;
|
||||||
|
|
||||||
if (node)
|
if (node)
|
||||||
@ -2496,21 +2491,35 @@ Array Node::_get_node_and_resource(const NodePath &p_path) {
|
|||||||
else
|
else
|
||||||
result.push_back(Variant());
|
result.push_back(Variant());
|
||||||
|
|
||||||
|
result.push_back(NodePath(Vector<StringName>(), leftover_path, false));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res) const {
|
Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property) const {
|
||||||
|
|
||||||
Node *node = get_node(p_path);
|
Node *node = get_node(p_path);
|
||||||
r_res = RES();
|
r_res = RES();
|
||||||
|
r_leftover_subpath = Vector<StringName>();
|
||||||
if (!node)
|
if (!node)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (p_path.get_subname_count()) {
|
if (p_path.get_subname_count()) {
|
||||||
|
|
||||||
for (int j = 0; j < p_path.get_subname_count(); j++) {
|
int j = 0;
|
||||||
r_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j));
|
// If not p_last_is_property, we shouldn't consider the last one as part of the resource
|
||||||
ERR_FAIL_COND_V(r_res.is_null(), node);
|
for (; j < p_path.get_subname_count() - p_last_is_property; j++) {
|
||||||
|
RES new_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j));
|
||||||
|
|
||||||
|
if (new_res.is_null()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_res = new_res;
|
||||||
|
}
|
||||||
|
for (; j < p_path.get_subname_count(); j++) {
|
||||||
|
// Put the rest of the subpath in the leftover path
|
||||||
|
r_leftover_subpath.push_back(p_path.get_subname(j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ public:
|
|||||||
Node *get_node(const NodePath &p_path) const;
|
Node *get_node(const NodePath &p_path) const;
|
||||||
Node *find_node(const String &p_mask, bool p_recursive = true, bool p_owned = true) const;
|
Node *find_node(const String &p_mask, bool p_recursive = true, bool p_owned = true) const;
|
||||||
bool has_node_and_resource(const NodePath &p_path) const;
|
bool has_node_and_resource(const NodePath &p_path) const;
|
||||||
Node *get_node_and_resource(const NodePath &p_path, RES &r_res) const;
|
Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const;
|
||||||
|
|
||||||
Node *get_parent() const;
|
Node *get_parent() const;
|
||||||
_FORCE_INLINE_ SceneTree *get_tree() const {
|
_FORCE_INLINE_ SceneTree *get_tree() const {
|
||||||
|
Loading…
Reference in New Issue
Block a user