/*************************************************************************/ /* skeleton_modification_stack_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "skeleton_modification_stack_3d.h" #include "scene/3d/skeleton.h" #include "skeleton_modification_3d.h" /////////////////////////////////////// // ModificationStack3D /////////////////////////////////////// void SkeletonModificationStack3D::_get_property_list(List *p_list) const { for (int i = 0; i < modifications.size(); i++) { p_list->push_back( PropertyInfo(Variant::OBJECT, "modifications/" + itos(i), PROPERTY_HINT_RESOURCE_TYPE, "SkeletonModification3D", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE)); } } bool SkeletonModificationStack3D::_set(const StringName &p_path, const Variant &p_value) { String path = p_path; if (path.begins_with("modifications/")) { int mod_idx = path.get_slicec('/', 1).to_int(); set_modification(mod_idx, p_value); return true; } return true; } bool SkeletonModificationStack3D::_get(const StringName &p_path, Variant &r_ret) const { String path = p_path; if (path.begins_with("modifications/")) { int mod_idx = path.get_slicec('/', 1).to_int(); r_ret = get_modification(mod_idx); return true; } return true; } void SkeletonModificationStack3D::setup() { if (is_setup) { return; } if (skeleton != nullptr) { is_setup = true; for (int i = 0; i < modifications.size(); i++) { if (!modifications[i].is_valid()) { continue; } modifications.write[i]->setup_modification(this); } } else { WARN_PRINT("Cannot setup SkeletonModificationStack3D: no skeleton set!"); } } void SkeletonModificationStack3D::execute(real_t p_delta, int p_execution_mode) { ERR_FAIL_COND_MSG(!is_setup || skeleton == nullptr || is_queued_for_deletion(), "Modification stack is not properly setup and therefore cannot execute!"); if (!skeleton->is_inside_tree()) { ERR_PRINT_ONCE("Skeleton is not inside SceneTree! Cannot execute modification!"); return; } if (!enabled) { return; } for (int i = 0; i < modifications.size(); i++) { if (!modifications[i].is_valid()) { continue; } if (modifications[i]->get_execution_mode() == p_execution_mode) { modifications.write[i]->execute(p_delta); } } } void SkeletonModificationStack3D::enable_all_modifications(bool p_enabled) { for (int i = 0; i < modifications.size(); i++) { if (!modifications[i].is_valid()) { continue; } modifications.write[i]->set_enabled(p_enabled); } } Ref SkeletonModificationStack3D::get_modification(int p_mod_idx) const { const int modifications_size = modifications.size(); ERR_FAIL_INDEX_V(p_mod_idx, modifications_size, nullptr); return modifications[p_mod_idx]; } void SkeletonModificationStack3D::add_modification(Ref p_mod) { ERR_FAIL_COND(p_mod.is_null()); p_mod->setup_modification(this); modifications.push_back(p_mod); } void SkeletonModificationStack3D::delete_modification(int p_mod_idx) { const int modifications_size = modifications.size(); ERR_FAIL_INDEX(p_mod_idx, modifications_size); modifications.remove(p_mod_idx); } void SkeletonModificationStack3D::set_modification(int p_mod_idx, Ref p_mod) { const int modifications_size = modifications.size(); ERR_FAIL_INDEX(p_mod_idx, modifications_size); if (p_mod == nullptr) { modifications.remove(p_mod_idx); } else { p_mod->setup_modification(this); modifications.write[p_mod_idx] = p_mod; } } void SkeletonModificationStack3D::set_modification_count(int p_count) { ERR_FAIL_COND_MSG(p_count < 0, "Modification count cannot be less than zero."); modifications.resize(p_count); property_list_changed_notify(); } int SkeletonModificationStack3D::get_modification_count() const { return modifications.size(); } void SkeletonModificationStack3D::set_skeleton(Skeleton *p_skeleton) { skeleton = p_skeleton; } Skeleton *SkeletonModificationStack3D::get_skeleton() const { return skeleton; } bool SkeletonModificationStack3D::get_is_setup() const { return is_setup; } void SkeletonModificationStack3D::set_enabled(bool p_enabled) { enabled = p_enabled; if (!enabled && is_setup && skeleton != nullptr) { skeleton->clear_bones_local_pose_override(); } } bool SkeletonModificationStack3D::get_enabled() const { return enabled; } void SkeletonModificationStack3D::set_strength(real_t p_strength) { ERR_FAIL_COND_MSG(p_strength < 0, "Strength cannot be less than zero!"); ERR_FAIL_COND_MSG(p_strength > 1, "Strength cannot be more than one!"); strength = p_strength; } real_t SkeletonModificationStack3D::get_strength() const { return strength; } void SkeletonModificationStack3D::_bind_methods() { ClassDB::bind_method(D_METHOD("setup"), &SkeletonModificationStack3D::setup); ClassDB::bind_method(D_METHOD("execute", "delta", "execution_mode"), &SkeletonModificationStack3D::execute); ClassDB::bind_method(D_METHOD("enable_all_modifications", "enabled"), &SkeletonModificationStack3D::enable_all_modifications); ClassDB::bind_method(D_METHOD("get_modification", "mod_idx"), &SkeletonModificationStack3D::get_modification); ClassDB::bind_method(D_METHOD("add_modification", "modification"), &SkeletonModificationStack3D::add_modification); ClassDB::bind_method(D_METHOD("delete_modification", "mod_idx"), &SkeletonModificationStack3D::delete_modification); ClassDB::bind_method(D_METHOD("set_modification", "mod_idx", "modification"), &SkeletonModificationStack3D::set_modification); ClassDB::bind_method(D_METHOD("set_modification_count", "count"), &SkeletonModificationStack3D::set_modification_count); ClassDB::bind_method(D_METHOD("get_modification_count"), &SkeletonModificationStack3D::get_modification_count); ClassDB::bind_method(D_METHOD("get_is_setup"), &SkeletonModificationStack3D::get_is_setup); ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &SkeletonModificationStack3D::set_enabled); ClassDB::bind_method(D_METHOD("get_enabled"), &SkeletonModificationStack3D::get_enabled); ClassDB::bind_method(D_METHOD("set_strength", "strength"), &SkeletonModificationStack3D::set_strength); ClassDB::bind_method(D_METHOD("get_strength"), &SkeletonModificationStack3D::get_strength); ClassDB::bind_method(D_METHOD("get_skeleton"), &SkeletonModificationStack3D::get_skeleton); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "get_enabled"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "strength", PROPERTY_HINT_RANGE, "0, 1, 0.001"), "set_strength", "get_strength"); ADD_PROPERTY(PropertyInfo(Variant::INT, "modification_count", PROPERTY_HINT_RANGE, "0, 100, 1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_modification_count", "get_modification_count"); } SkeletonModificationStack3D::SkeletonModificationStack3D() { } SkeletonModificationStack3D::~SkeletonModificationStack3D() { }