From 56a333bef50c7cf3e8e3c37c9d8c85258094d36f Mon Sep 17 00:00:00 2001 From: Relintai Date: Sat, 26 Oct 2019 03:38:09 +0200 Subject: [PATCH] More work on ItemVisuals. --- skeleton/character_skeleton.cpp | 22 +++ skeleton/character_skeleton.h | 20 +-- skeleton/character_skeleton_3d.cpp | 226 +++++++++++++++++++++++++---- skeleton/character_skeleton_3d.h | 49 +++++-- skeleton/skeleton_model_entry.cpp | 20 ++- skeleton/skeleton_model_entry.h | 12 +- 6 files changed, 294 insertions(+), 55 deletions(-) diff --git a/skeleton/character_skeleton.cpp b/skeleton/character_skeleton.cpp index 4072851..05a5c73 100644 --- a/skeleton/character_skeleton.cpp +++ b/skeleton/character_skeleton.cpp @@ -1,9 +1,31 @@ #include "character_skeleton.h" +void CharacterSkeleton::add_item_visual(Ref vis) { +} +void CharacterSkeleton::remove_item_visual(Ref vis) { +} +void CharacterSkeleton::remove_item_visual_index(int index) { +} +Ref CharacterSkeleton::get_item_visual(int index) { + return Ref(); +} +int CharacterSkeleton::get_item_visual_count() { + return 0; +} +void CharacterSkeleton::clear_item_visuals() { +} CharacterSkeleton::CharacterSkeleton() { +} +CharacterSkeleton::~CharacterSkeleton() { } void CharacterSkeleton::_bind_methods() { + ClassDB::bind_method(D_METHOD("add_item_visual", "vis"), &CharacterSkeleton::add_item_visual); + ClassDB::bind_method(D_METHOD("remove_item_visual", "vis"), &CharacterSkeleton::remove_item_visual); + ClassDB::bind_method(D_METHOD("remove_item_visual_index", "index"), &CharacterSkeleton::remove_item_visual_index); + ClassDB::bind_method(D_METHOD("get_item_visual", "index"), &CharacterSkeleton::get_item_visual); + ClassDB::bind_method(D_METHOD("get_item_visual_count"), &CharacterSkeleton::get_item_visual_count); + ClassDB::bind_method(D_METHOD("clear_item_visuals"), &CharacterSkeleton::clear_item_visuals); } diff --git a/skeleton/character_skeleton.h b/skeleton/character_skeleton.h index 115f054..910dd63 100644 --- a/skeleton/character_skeleton.h +++ b/skeleton/character_skeleton.h @@ -9,34 +9,30 @@ #include "core/node_path.h" #include "core/ustring.h" -#include "scene/animation/animation_player.h" -#include "scene/animation/animation_tree.h" +#include "core/vector.h" -#include "../data/character_skeleton_visual_entry.h" #include "../entity_enums.h" #include "../data/item_visual.h" #ifdef ENTITIES_2D - class CharacterSkeleton : public Node2D { GDCLASS(CharacterSkeleton, Node2D); - #else - class CharacterSkeleton : public Spatial { GDCLASS(CharacterSkeleton, Spatial); - #endif public: - //virtual void add_item_visual(Ref vis); - //virtual void remove_item_visual(Ref vis); - //virtual Ref get_item_visual(); - //virtual int get_item_visual_count(); - //virtual void clear_item_visuals(); + virtual void add_item_visual(Ref vis); + virtual void remove_item_visual(Ref vis); + virtual void remove_item_visual_index(int index); + virtual Ref get_item_visual(int index); + virtual int get_item_visual_count(); + virtual void clear_item_visuals(); CharacterSkeleton(); + ~CharacterSkeleton(); protected: static void _bind_methods(); diff --git a/skeleton/character_skeleton_3d.cpp b/skeleton/character_skeleton_3d.cpp index b9c5f64..e3ad513 100644 --- a/skeleton/character_skeleton_3d.cpp +++ b/skeleton/character_skeleton_3d.cpp @@ -2,14 +2,21 @@ #include "../data/item_visual.h" +bool CharacterSkeleton3D::get_model_dirty() const { + return _model_dirty; +} +void CharacterSkeleton3D::set_model_dirty(bool value) { + _model_dirty = value; +} + NodePath CharacterSkeleton3D::get_bone_path(int index) { - ERR_FAIL_INDEX_V(index, EntityEnums::SKELETON_POINTS_MAX, NodePath()); - + ERR_FAIL_INDEX_V(index, EntityEnums::SKELETON_POINTS_MAX, NodePath()); + return _bone_paths[index]; } void CharacterSkeleton3D::set_bone_path(int index, NodePath path) { - ERR_FAIL_INDEX(index, EntityEnums::SKELETON_POINTS_MAX); - + ERR_FAIL_INDEX(index, EntityEnums::SKELETON_POINTS_MAX); + _bone_paths[index] = path; _bone_nodes[index] = get_node_or_null(path); @@ -72,14 +79,151 @@ AnimationTree *CharacterSkeleton3D::get_animation_tree() { void CharacterSkeleton3D::update_nodes() { for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { - _bone_nodes[i] = get_node_or_null(_bone_paths[i]); - } + _bone_nodes[i] = get_node_or_null(_bone_paths[i]); + } set_animation_player_path(_animation_player_path); set_animation_tree_path(_animation_tree_path); } +void CharacterSkeleton3D::add_item_visual(Ref vis) { + ERR_FAIL_COND(!vis.is_valid()); + + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { + Ref e = vis->get_visual(i); + + if (e.is_valid()) + add_item_visual_entry(vis, e); + } + + _item_visuals.push_back(vis); +} +void CharacterSkeleton3D::remove_item_visual(Ref vis) { + ERR_FAIL_COND(!vis.is_valid()); + + int index = _item_visuals.find(vis); + + if (index == -1) + return; + + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { + Ref e = vis->get_visual(i); + + if (e.is_valid()) + remove_item_visual_entry(vis, e); + } + + _item_visuals.remove(index); +} +void CharacterSkeleton3D::remove_item_visual_index(int index) { + ERR_FAIL_INDEX(index, _item_visuals.size()); + + _item_visuals.remove(index); +} +Ref CharacterSkeleton3D::get_item_visual(int index) { + ERR_FAIL_INDEX_V(index, _item_visuals.size(), Ref()); + + return _item_visuals.get(index); +} +int CharacterSkeleton3D::get_item_visual_count() { + return _item_visuals.size(); +} +void CharacterSkeleton3D::clear_item_visuals() { + _item_visuals.clear(); + + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { + _entries[i].clear(); + } + + _model_dirty = true; + set_process(true); +} + +void CharacterSkeleton3D::add_item_visual_entry(Ref vis, Ref ive) { + ERR_FAIL_COND(!vis.is_valid()); + ERR_FAIL_COND(!ive.is_valid()); + + int target_bone_idx = static_cast(ive->get_target_bone()); + + Vector > &entries = _entries[target_bone_idx]; + + for (int i = 0; i < entries.size(); ++i) { + Ref e = entries.get(i); + + if (e->get_entry() == ive) { + e->set_count(e->get_count() + 1); + return; + } + } + + Ref e; + e.instance(); + + e->set_priority(static_cast(vis->get_layer())); + e->set_color(ive->get_color()); + e->set_entry(ive); + + entries.push_back(e); + _model_dirty = true; + set_process(true); +} +void CharacterSkeleton3D::remove_item_visual_entry(Ref vis, Ref ive) { + ERR_FAIL_COND(!vis.is_valid()); + ERR_FAIL_COND(!ive.is_valid()); + + int target_bone_idx = static_cast(ive->get_target_bone()); + + Vector > &entries = _entries[target_bone_idx]; + + for (int i = 0; i < entries.size(); ++i) { + Ref e = entries.get(i); + + if (e->get_entry() == ive) { + e->set_count(e->get_count() - 1); + + if (e->get_count() <= 0) { + entries.remove(i); + + _model_dirty = true; + set_process(true); + } + + return; + } + } +} + +Ref CharacterSkeleton3D::get_model_entry(const int bone_index, const int index) { + ERR_FAIL_INDEX_V(bone_index, EntityEnums::SKELETON_POINTS_MAX, Ref()); + ERR_FAIL_INDEX_V(index, _entries[bone_index].size(), Ref()); + + return _entries[bone_index].get(index); +} +int CharacterSkeleton3D::get_model_entry_count(const int bone_index) { + ERR_FAIL_INDEX_V(bone_index, EntityEnums::SKELETON_POINTS_MAX, 0); + + return _entries[bone_index].size(); +} + +void CharacterSkeleton3D::sort_layers() { + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { + Vector > &entries = _entries[i]; + + entries.sort_custom<_ModelEntryComparator>(); + } +} + +void CharacterSkeleton3D::build_model() { + call("_build_model"); +} + +void CharacterSkeleton3D::_build_model() { + set_process(false); +} + CharacterSkeleton3D::CharacterSkeleton3D() { + _model_dirty = false; + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { _bone_nodes[i] = NULL; } @@ -87,12 +231,24 @@ CharacterSkeleton3D::CharacterSkeleton3D() { _animation_player = NULL; } +CharacterSkeleton3D::~CharacterSkeleton3D() { + for (int i = 0; i < EntityEnums::SKELETON_POINTS_MAX; ++i) { + _entries[i].clear(); + + _visuals[i].unref(); + } + + _item_visuals.clear(); +} + void CharacterSkeleton3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { update_nodes(); } break; case NOTIFICATION_PROCESS: { + if (_model_dirty) + build_model(); } break; case NOTIFICATION_EXIT_TREE: { @@ -101,13 +257,49 @@ void CharacterSkeleton3D::_notification(int p_what) { } void CharacterSkeleton3D::_bind_methods() { + BIND_VMETHOD(MethodInfo("_build_model")); + + ClassDB::bind_method(D_METHOD("get_model_dirty"), &CharacterSkeleton3D::get_model_dirty); + ClassDB::bind_method(D_METHOD("set_model_dirty", "value"), &CharacterSkeleton3D::set_model_dirty); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "model_dirty"), "set_model_dirty", "get_model_dirty"); + + ClassDB::bind_method(D_METHOD("get_animation_player_path"), &CharacterSkeleton3D::get_animation_player_path); + ClassDB::bind_method(D_METHOD("set_animation_player_path", "path"), &CharacterSkeleton3D::set_animation_player_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_player_path"), "set_animation_player_path", "get_animation_player_path"); + + ClassDB::bind_method(D_METHOD("get_animation_tree_path"), &CharacterSkeleton3D::get_animation_tree_path); + ClassDB::bind_method(D_METHOD("set_animation_tree_path", "path"), &CharacterSkeleton3D::set_animation_tree_path); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_tree_path"), "set_animation_tree_path", "get_animation_tree_path"); + + ClassDB::bind_method(D_METHOD("add_item_visual_entry", "vis", "ive"), &CharacterSkeleton3D::add_item_visual_entry); + ClassDB::bind_method(D_METHOD("remove_item_visual_entry", "vis", "ive"), &CharacterSkeleton3D::remove_item_visual_entry); + ClassDB::bind_method(D_METHOD("get_model_entry", "bone_index", "index"), &CharacterSkeleton3D::get_model_entry); + ClassDB::bind_method(D_METHOD("get_model_entry_count", "bone_index"), &CharacterSkeleton3D::get_model_entry_count); + + ClassDB::bind_method(D_METHOD("sort_layers"), &CharacterSkeleton3D::sort_layers); + + ClassDB::bind_method(D_METHOD("build_model"), &CharacterSkeleton3D::build_model); + ClassDB::bind_method(D_METHOD("_build_model"), &CharacterSkeleton3D::_build_model); + + //Bone Paths ClassDB::bind_method(D_METHOD("get_bone_path", "index"), &CharacterSkeleton3D::get_bone_path); ClassDB::bind_method(D_METHOD("set_bone_path", "index", "path"), &CharacterSkeleton3D::set_bone_path); + ADD_GROUP("Bone Paths", "bone_path_"); + ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "bone_path_root"), "set_bone_path", "get_bone_path", EntityEnums::SKELETON_POINT_ROOT); + + ClassDB::bind_method(D_METHOD("get_bone_node", "bone_idx"), &CharacterSkeleton3D::get_bone_node); + + ClassDB::bind_method(D_METHOD("get_animation_player"), &CharacterSkeleton3D::get_animation_player); + ClassDB::bind_method(D_METHOD("get_animation_tree"), &CharacterSkeleton3D::get_animation_tree); + + ClassDB::bind_method(D_METHOD("update_nodes"), &CharacterSkeleton3D::update_nodes); + + //Visuals ClassDB::bind_method(D_METHOD("get_visual", "index"), &CharacterSkeleton3D::get_visual); ClassDB::bind_method(D_METHOD("set_visual", "index", "entry"), &CharacterSkeleton3D::set_visual); - - ADD_GROUP("Visuals", "visual_"); + + ADD_GROUP("Visuals", "visual_"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_root", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_ROOT); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_pelvis", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_PELVIS); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_spine", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_SPINE); @@ -141,22 +333,4 @@ void CharacterSkeleton3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_right_thigh", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_RIGHT_THIGH); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_right_calf", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_RIGHT_CALF); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "visual_right_foot", PROPERTY_HINT_RESOURCE_TYPE, "CharacterSkeletonVisualEntry"), "set_visual", "get_visual", EntityEnums::SKELETON_POINT_RIGHT_FOOT); - - ADD_GROUP("Bone Paths", "bone_path_"); - ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "bone_path_root"), "set_bone_path", "get_bone_path", EntityEnums::SKELETON_POINT_ROOT); - - ClassDB::bind_method(D_METHOD("get_bone_node", "bone_idx"), &CharacterSkeleton3D::get_bone_node); - - ClassDB::bind_method(D_METHOD("get_animation_player_path"), &CharacterSkeleton3D::get_animation_player_path); - ClassDB::bind_method(D_METHOD("set_animation_player_path", "path"), &CharacterSkeleton3D::set_animation_player_path); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_player_path"), "set_animation_player_path", "get_animation_player_path"); - - ClassDB::bind_method(D_METHOD("get_animation_tree_path"), &CharacterSkeleton3D::get_animation_tree_path); - ClassDB::bind_method(D_METHOD("set_animation_tree_path", "path"), &CharacterSkeleton3D::set_animation_tree_path); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "animation_tree_path"), "set_animation_tree_path", "get_animation_tree_path"); - - ClassDB::bind_method(D_METHOD("get_animation_player"), &CharacterSkeleton3D::get_animation_player); - ClassDB::bind_method(D_METHOD("get_animation_tree"), &CharacterSkeleton3D::get_animation_tree); - - ClassDB::bind_method(D_METHOD("update_nodes"), &CharacterSkeleton3D::update_nodes); } diff --git a/skeleton/character_skeleton_3d.h b/skeleton/character_skeleton_3d.h index 608fde9..2d89b1f 100644 --- a/skeleton/character_skeleton_3d.h +++ b/skeleton/character_skeleton_3d.h @@ -12,13 +12,20 @@ #include "../data/character_skeleton_visual_entry.h" #include "../entity_enums.h" +#include "skeleton_model_entry.h" + +#include "../data/item_visual_entry.h" class ItemVisual; +//Rename to HumanoidCharSkeleton class CharacterSkeleton3D : public CharacterSkeleton { GDCLASS(CharacterSkeleton3D, CharacterSkeleton); public: + bool get_model_dirty() const; + void set_model_dirty(bool value); + NodePath get_bone_path(int index); void set_bone_path(int index, NodePath path); @@ -37,20 +44,44 @@ public: AnimationTree *get_animation_tree(); - //void add_item_visual(Ref vis); - //void remove_item_visual(Ref vis); - //Ref get_item_visual(); - //int get_item_visual_count(); - //void clear_item_visuals(); - void update_nodes(); + void add_item_visual(Ref vis); + void remove_item_visual(Ref vis); + void remove_item_visual_index(int index); + Ref get_item_visual(int index); + int get_item_visual_count(); + void clear_item_visuals(); + + void add_item_visual_entry(Ref vis, Ref ive); + void remove_item_visual_entry(Ref vis, Ref ive); + + Ref get_model_entry(const int bone_index, const int index); + int get_model_entry_count(const int bone_index); + + void sort_layers(); + + void build_model(); + void _build_model(); + CharacterSkeleton3D(); + ~CharacterSkeleton3D(); protected: static void _bind_methods(); virtual void _notification(int p_notification); +protected: + struct _ModelEntryComparator { + _FORCE_INLINE_ bool operator()(const Ref &a, const Ref &b) const { + if (!a.is_valid() || !b.is_valid()) { + return false; + } + + return (a->get_priority() < b->get_priority()); + } + }; + private: NodePath _animation_player_path; NodePath _animation_tree_path; @@ -62,11 +93,11 @@ private: Node *_bone_nodes[EntityEnums::SKELETON_POINTS_MAX]; - Vector > _item_visuals; - Ref _visuals[EntityEnums::SKELETON_POINTS_MAX]; - Vector > _entries[EntityEnums::SKELETON_POINTS_MAX]; + bool _model_dirty; + Vector > _item_visuals; + Vector > _entries[EntityEnums::SKELETON_POINTS_MAX]; }; diff --git a/skeleton/skeleton_model_entry.cpp b/skeleton/skeleton_model_entry.cpp index bdf197d..369b240 100644 --- a/skeleton/skeleton_model_entry.cpp +++ b/skeleton/skeleton_model_entry.cpp @@ -1,16 +1,23 @@ #include "skeleton_model_entry.h" -int SkeletonModelEntry::get_priority() { +int SkeletonModelEntry::get_count() const { + return _count; +} +void SkeletonModelEntry::set_count(const int value) { + _count = value; +} + +int SkeletonModelEntry::get_priority() const { return _priority; } -void SkeletonModelEntry::set_priority(int value) { +void SkeletonModelEntry::set_priority(const int value) { _priority = value; } -Color SkeletonModelEntry::get_color() { +Color SkeletonModelEntry::get_color() const { return _color; } -void SkeletonModelEntry::set_color(Color value) { +void SkeletonModelEntry::set_color(const Color value) { _color = value; } @@ -22,6 +29,7 @@ void SkeletonModelEntry::set_entry(Ref entry) { } SkeletonModelEntry::SkeletonModelEntry() { + _count = 1; _priority = 0; _color = Color(1, 1, 1, 1); } @@ -31,6 +39,10 @@ SkeletonModelEntry::~SkeletonModelEntry() { } void SkeletonModelEntry::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_count"), &SkeletonModelEntry::get_count); + ClassDB::bind_method(D_METHOD("set_count", "value"), &SkeletonModelEntry::set_count); + ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); + ClassDB::bind_method(D_METHOD("get_priority"), &SkeletonModelEntry::get_priority); ClassDB::bind_method(D_METHOD("set_priority", "value"), &SkeletonModelEntry::set_priority); ADD_PROPERTY(PropertyInfo(Variant::INT, "priority"), "set_priority", "get_priority"); diff --git a/skeleton/skeleton_model_entry.h b/skeleton/skeleton_model_entry.h index 69a91fa..d35a449 100644 --- a/skeleton/skeleton_model_entry.h +++ b/skeleton/skeleton_model_entry.h @@ -8,11 +8,14 @@ class SkeletonModelEntry : public Reference { GDCLASS(SkeletonModelEntry, Reference); public: - int get_priority(); - void set_priority(int value); + int get_count() const; + void set_count(const int value); - Color get_color(); - void set_color(Color value); + int get_priority() const; + void set_priority(const int value); + + Color get_color() const; + void set_color(const Color value); Ref get_entry(); void set_entry(Ref entry); @@ -24,6 +27,7 @@ protected: static void _bind_methods(); private: + int _count; int _priority; Color _color; Ref _entry;