diff options
author | Bojidar Marinov <bojidar.marinov.bg@gmail.com> | 2017-05-30 23:20:15 +0300 |
---|---|---|
committer | Bojidar Marinov <bojidar.marinov.bg@gmail.com> | 2017-11-21 20:58:21 +0200 |
commit | 0cf9597758f3af3afc951d0bf02dee1aeb9a6daf (patch) | |
tree | 2a5fe6f1ba36a79ccc0091d0235ec48e4d92012e /scene | |
parent | 7bbde636e802f85c4ed9ee95b9ef19abc1aa249d (diff) |
Allow for getting/setting indexed properties of objects using get/set_indexed
Performance is around the same as using pure set() through GDScript.
Diffstat (limited to 'scene')
-rw-r--r-- | scene/animation/animation_cache.cpp | 95 | ||||
-rw-r--r-- | scene/animation/animation_cache.h | 2 | ||||
-rw-r--r-- | scene/animation/animation_player.cpp | 30 | ||||
-rw-r--r-- | scene/animation/animation_player.h | 2 | ||||
-rw-r--r-- | scene/animation/animation_tree_player.cpp | 20 | ||||
-rw-r--r-- | scene/animation/animation_tree_player.h | 6 | ||||
-rw-r--r-- | scene/animation/tween.cpp | 128 | ||||
-rw-r--r-- | scene/animation/tween.h | 27 | ||||
-rwxr-xr-x | scene/main/node.cpp | 37 | ||||
-rw-r--r-- | scene/main/node.h | 2 |
10 files changed, 187 insertions, 162 deletions
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp index b35b2568d1..fbe2593362 100644 --- a/scene/animation/animation_cache.cpp +++ b/scene/animation/animation_cache.cpp @@ -87,95 +87,90 @@ void AnimationCache::_update_cache() { 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()); ERR_EXPLAIN("Transform tracks can't have a subpath: " + np); 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; - } + Spatial *sp = Object::cast_to<Spatial>(node); - if (res.is_null()) { + if (!sp) { path_cache.push_back(Path()); - ERR_EXPLAIN("Invalid Track SubPath in Animation: " + np); - ERR_CONTINUE(res.is_null()); + ERR_EXPLAIN("Transform track not of type Spatial: " + np); + ERR_CONTINUE(!sp); } - path.resource = res; - path.object = res.ptr(); - - } else { - - if (animation->track_get_type(i) == Animation::TYPE_TRANSFORM) { - StringName property = np.get_property(); + if (np.get_subname_count() == 1) { + StringName property = np.get_subname(0); String ps = property; - Spatial *sp = Object::cast_to<Spatial>(node); + Skeleton *sk = Object::cast_to<Skeleton>(node); + if (!sk) { - if (!sp) { + path_cache.push_back(Path()); + ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton!: " + np); + ERR_CONTINUE(!sk); + } + int idx = sk->find_bone(ps); + if (idx == -1) { path_cache.push_back(Path()); - ERR_EXPLAIN("Transform track not of type Spatial: " + np); - ERR_CONTINUE(!sp); + ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton Bone!: " + np); + ERR_CONTINUE(idx == -1); } - if (ps != "") { + path.bone_idx = idx; + path.skeleton = sk; + } - Skeleton *sk = Object::cast_to<Skeleton>(node); - if (!sk) { + path.spatial = sp; - path_cache.push_back(Path()); - ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton!: " + np); - ERR_CONTINUE(!sk); - } + } else { + if (np.get_subname_count() > 0) { - int idx = sk->find_bone(ps); - if (idx == -1) { + RES res; + Vector<StringName> leftover_subpath; - path_cache.push_back(Path()); - ERR_EXPLAIN("Property defined in Transform track, but not a Skeleton Bone!: " + np); - ERR_CONTINUE(idx == -1); - } + // 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); - path.bone_idx = idx; - path.skeleton = sk; + if (res.is_valid()) { + path.resource = res; + } else { + path.node = node; } + path.object = res.is_valid() ? res.ptr() : (Object *)node; + path.subpath = leftover_subpath; - path.spatial = sp; - } + } else { - path.node = node; - path.object = node; + path.node = node; + path.object = node; + path.subpath = np.get_subnames(); + } } 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()); 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) { - 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()); 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; 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) { diff --git a/scene/animation/animation_cache.h b/scene/animation/animation_cache.h index e593668df6..481de59730 100644 --- a/scene/animation/animation_cache.h +++ b/scene/animation/animation_cache.h @@ -46,7 +46,7 @@ class AnimationCache : public Object { Spatial *spatial; int bone_idx; - StringName property; + Vector<StringName> subpath; bool valid; Path() { object = NULL; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 80b7748078..a0a554b3aa 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -242,7 +242,8 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) { p_anim->node_cache[i] = NULL; 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) { 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(); 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) { continue; @@ -289,8 +290,8 @@ void AnimationPlayer::_generate_node_caches(AnimationData *p_anim) { p_anim->node_cache[i]->skeleton = Object::cast_to<Skeleton>(child); if (p_anim->node_cache[i]->skeleton) { - StringName bone_name = a->track_get_path(i).get_property(); - if (bone_name.operator String() != "") { + if (a->track_get_path(i).get_subname_count() == 1) { + 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); 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) { - StringName property = a->track_get_path(i).get_property(); - if (!p_anim->node_cache[i]->property_anim.has(property)) { + if (!p_anim->node_cache[i]->property_anim.has(a->track_get_path(i).get_concatenated_subnames())) { TrackNodeCache::PropertyAnim pa; - pa.prop = property; + pa.subpath = leftover_path; pa.object = resource.is_valid() ? (Object *)resource.ptr() : (Object *)child; pa.special = SP_NONE; pa.owner = p_anim->node_cache[i]; 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; - 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; - 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; } - 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(); - 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? TrackNodeCache::PropertyAnim *pa = &E->get(); @@ -434,7 +434,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float case SP_NONE: { 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 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() + "'."); @@ -615,7 +615,7 @@ void AnimationPlayer::_animation_update_transforms() { case SP_NONE: { 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 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"); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 83da3b2e5c..e4e021c7fe 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -83,7 +83,7 @@ private: TrackNodeCache *owner; SpecialProperty special; //small optimization - StringName prop; + Vector<StringName> subpath; Object *object; Variant value_accum; uint64_t accum_pass; diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index ad5329c94b..23eccec82f 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -811,7 +811,7 @@ void AnimationTreePlayer::_process_animation(float p_delta) { t.scale.y = 0; t.scale.z = 0; - t.value = t.object->get(t.property); + t.value = t.object->get_indexed(t.subpath); t.value.zero(); t.skip = false; @@ -890,8 +890,8 @@ void AnimationTreePlayer::_process_animation(float p_delta) { if (t.skip || !t.object) continue; - if (t.property) { // value track - t.object->set(t.property, t.value); + if (t.subpath.size()) { // value track + t.object->set_indexed(t.subpath, t.value); continue; } @@ -1475,7 +1475,8 @@ AnimationTreePlayer::Track *AnimationTreePlayer::_find_track(const NodePath &p_p ERR_FAIL_COND_V(!parent, NULL); 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) { String err = "Animation track references unknown Node: '" + String(p_path) + "'."; 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(); - StringName property; int bone_idx = -1; - if (p_path.get_property()) { + if (p_path.get_subname_count()) { if (Object::cast_to<Skeleton>(child)) - bone_idx = Object::cast_to<Skeleton>(child)->find_bone(p_path.get_property()); - if (bone_idx == -1) - property = p_path.get_property(); + bone_idx = Object::cast_to<Skeleton>(child)->find_bone(p_path.get_subname(0)); } TrackKey key; key.id = id; key.bone_idx = bone_idx; - key.property = property; + key.subpath_concatenated = p_path.get_concatenated_subnames(); 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.spatial = Object::cast_to<Spatial>(child); tr.bone_idx = bone_idx; - tr.property = property; + if (bone_idx == -1) tr.subpath = leftover_path; track_map[key] = tr; } diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 3e2bb88198..c49b0c4d1b 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -78,14 +78,14 @@ private: struct TrackKey { uint32_t id; - StringName property; + StringName subpath_concatenated; int bone_idx; inline bool operator<(const TrackKey &p_right) const { if (id == p_right.id) { if (bone_idx == p_right.bone_idx) { - return property < p_right.property; + return subpath_concatenated < p_right.subpath_concatenated; } else return bone_idx < p_right.bone_idx; } else @@ -99,7 +99,7 @@ private: Spatial *spatial; Skeleton *skeleton; int bone_idx; - StringName property; + Vector<StringName> subpath; Vector3 loc; Quat rot; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index b5e6fc79db..2f0e32d084 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -264,12 +264,12 @@ Variant &Tween::_get_initial_val(InterpolateData &p_data) { if (p_data.type == TARGETING_PROPERTY) { 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); } else { 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); } return initial_val; @@ -296,12 +296,12 @@ Variant &Tween::_get_delta_val(InterpolateData &p_data) { if (p_data.type == FOLLOW_PROPERTY) { 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); } else { 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); } @@ -462,6 +462,9 @@ Variant Tween::_run_equation(InterpolateData &p_data) { result = r; } break; + default: { + result = initial_val; + } break; }; #undef APPLY_EQUATION @@ -479,7 +482,7 @@ bool Tween::_apply_tween_value(InterpolateData &p_data, Variant &value) { case FOLLOW_PROPERTY: case TARGETING_PROPERTY: { bool valid = false; - object->set(p_data.key, value, &valid); + object->set_indexed(p_data.key, value, &valid); return valid; } @@ -489,9 +492,9 @@ bool Tween::_apply_tween_value(InterpolateData &p_data, Variant &value) { Variant::CallError error; if (value.get_type() != Variant::NIL) { 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 { - object->call(p_data.key, NULL, 0, error); + object->call(p_data.key[0], NULL, 0, error); } if (error.error == Variant::CallError::CALL_OK) @@ -548,7 +551,7 @@ void Tween::_tween_process(float p_delta) { continue; 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); } @@ -562,7 +565,7 @@ void Tween::_tween_process(float p_delta) { case INTER_PROPERTY: case INTER_METHOD: { 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); if (data.finish) _apply_tween_value(data, data.final_val); @@ -574,22 +577,22 @@ void Tween::_tween_process(float p_delta) { switch (data.args) { case 0: - object->call_deferred(data.key); + object->call_deferred(data.key[0]); break; case 1: - object->call_deferred(data.key, data.arg[0]); + object->call_deferred(data.key[0], data.arg[0]); break; 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; 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; 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; 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; } } else { @@ -601,17 +604,18 @@ void Tween::_tween_process(float p_delta) { &data.arg[3], &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; + default: {} } 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 if (!repeat) - call_deferred("_remove", object, data.key, true); + call_deferred("_remove", object, NodePath(Vector<StringName>(), data.key, false), true); } } pending_update--; @@ -690,7 +694,7 @@ bool Tween::start() { return true; } -bool Tween::reset(Object *p_object, String p_key) { +bool Tween::reset(Object *p_object, StringName p_key) { pending_update++; 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) 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.finish = false; @@ -727,7 +731,7 @@ bool Tween::reset_all() { return true; } -bool Tween::stop(Object *p_object, String p_key) { +bool Tween::stop(Object *p_object, StringName p_key) { pending_update++; 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); if (object == NULL) 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; } pending_update--; @@ -758,7 +762,7 @@ bool Tween::stop_all() { return true; } -bool Tween::resume(Object *p_object, String p_key) { +bool Tween::resume(Object *p_object, StringName p_key) { set_active(true); _set_process(true); @@ -770,7 +774,7 @@ bool Tween::resume(Object *p_object, String p_key) { Object *object = ObjectDB::get_instance(data.id); if (object == NULL) 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; } pending_update--; @@ -792,12 +796,12 @@ bool Tween::resume_all() { 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); 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) { 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); if (object == NULL) 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); if (first_only) { break; @@ -850,8 +854,9 @@ bool Tween::seek(real_t p_time) { data.finish = true; data.elapsed = (data.delay + data.duration); - } else + } else { data.finish = false; + } switch (data.type) { case INTER_PROPERTY: @@ -993,12 +998,14 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final 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) { _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; } - 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 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); 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); InterpolateData data; @@ -1023,7 +1030,8 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_ data.elapsed = 0; 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.final_val = p_final_val; data.duration = p_duration; @@ -1038,7 +1046,7 @@ bool Tween::interpolate_property(Object *p_object, String p_property, Variant p_ 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) { _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; @@ -1065,7 +1073,8 @@ bool Tween::interpolate_method(Object *p_object, String p_method, Variant p_init data.elapsed = 0; 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.final_val = p_final_val; 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.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.delay = 0; @@ -1154,7 +1164,8 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S data.elapsed = 0; 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.delay = 0; @@ -1185,12 +1196,15 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S 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) { _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; } - 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 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); 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); 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); // 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.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.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.trans_type = p_trans_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; } -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) { _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; @@ -1273,10 +1288,11 @@ bool Tween::follow_method(Object *p_object, String p_method, Variant p_initial_v data.elapsed = 0; 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.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.trans_type = p_trans_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; } -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) { _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; } + 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 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); 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); 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); // 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.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_key = p_initial_property; + data.target_key = p_initial_property.get_subnames(); data.initial_val = initial_val; data.final_val = p_final_val; data.duration = p_duration; @@ -1339,7 +1360,7 @@ bool Tween::targeting_property(Object *p_object, String p_property, Object *p_in 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) { _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; @@ -1376,9 +1397,10 @@ bool Tween::targeting_method(Object *p_object, String p_method, Object *p_initia data.elapsed = 0; 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_key = p_initial_method; + data.target_key.push_back(p_initial_method); data.initial_val = initial_val; data.final_val = p_final_val; data.duration = p_duration; diff --git a/scene/animation/tween.h b/scene/animation/tween.h index fac1d346b4..44710b25f9 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -86,12 +86,13 @@ private: bool call_deferred; real_t elapsed; ObjectID id; - StringName key; + Vector<StringName> key; + StringName concatenated_key; Variant initial_val; Variant delta_val; Variant final_val; ObjectID target_id; - StringName target_key; + Vector<StringName> target_key; real_t duration; TransitionType trans_type; EaseType ease_type; @@ -132,7 +133,7 @@ private: void _tween_process(float p_delta); 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: bool _set(const StringName &p_name, const Variant &p_value); @@ -156,34 +157,34 @@ public: float get_speed_scale() const; bool start(); - bool reset(Object *p_object, String p_key); + bool reset(Object *p_object, StringName p_key); bool reset_all(); - bool stop(Object *p_object, String p_key); + bool stop(Object *p_object, StringName p_key); bool stop_all(); - bool resume(Object *p_object, String p_key); + bool resume(Object *p_object, StringName p_key); bool resume_all(); - bool remove(Object *p_object, String p_key); + bool remove(Object *p_object, StringName p_key); bool remove_all(); bool seek(real_t p_time); real_t tell() 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_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(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index e6e11de177..7a1bdb7425 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2466,24 +2466,19 @@ bool Node::has_node_and_resource(const NodePath &p_path) const { return false; Node *node = get_node(p_path); - if (p_path.get_subname_count()) { + bool result = false; - RES r; - 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; - } - } + node->get_indexed(p_path.get_subnames(), &result); - return true; + return result; } Array Node::_get_node_and_resource(const NodePath &p_path) { Node *node; 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; if (node) @@ -2496,21 +2491,35 @@ Array Node::_get_node_and_resource(const NodePath &p_path) { else result.push_back(Variant()); + result.push_back(NodePath(Vector<StringName>(), leftover_path, false)); + 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); r_res = RES(); + r_leftover_subpath = Vector<StringName>(); if (!node) return NULL; if (p_path.get_subname_count()) { - for (int j = 0; j < p_path.get_subname_count(); j++) { - r_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j)); - ERR_FAIL_COND_V(r_res.is_null(), node); + int j = 0; + // If not p_last_is_property, we shouldn't consider the last one as part of the resource + 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)); } } diff --git a/scene/main/node.h b/scene/main/node.h index c43e96063f..8fd1a386dd 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -242,7 +242,7 @@ public: Node *get_node(const NodePath &p_path) 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; - 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; _FORCE_INLINE_ SceneTree *get_tree() const { |