#ifndef CHARACTER_BASE_H #define CHARACTER_BASE_H #include "character_slot.h" #include "config_data.h" #include #include #include #include #include #include #include /* modifier data classes */ class ModifierDataBase : public Reference { protected: friend class CharacterModifiers; int type; String gender; public: static const int TYPE_BLEND = 1; static const int TYPE_BLEND_SYM = 2; static const int TYPE_BONE = 3; static const int TYPE_SYMMETRY = 4; static const int TYPE_PAIR = 5; static const int TYPE_GROUP = 6; protected: String mod_name; bool empty; ModifierDataBase() : empty(true), gender("common") { } }; class BlendModifierData : public ModifierDataBase { protected: friend class BlendModifierSymData; friend class CharacterModifiers; float minp[3]; float maxp[3]; float cd[3]; float minn[3]; float maxn[3]; float cdn[3]; PoolVector mod_indices; PoolVector mod_data; public: BlendModifierData() { type = TYPE_BLEND; } }; class BlendModifierSymData : public ModifierDataBase { friend class CharacterModifiers; BlendModifierData plus; BlendModifierData minus; public: BlendModifierSymData() { type = TYPE_BLEND_SYM; } }; class BoneModifierData : public ModifierDataBase { friend class CharacterModifiers; String bone_name; Transform xform; int bone_id; public: BoneModifierData(): bone_id(-1) { type = TYPE_BONE; } }; class BoneGroupModifierData : public ModifierDataBase { friend class CharacterModifiers; static const int MAX_BONES = 32; int bones[MAX_BONES]; Transform xforms[MAX_BONES]; String bone_names[MAX_BONES]; int bone_count; public: BoneGroupModifierData(): bone_count(0) { type = TYPE_GROUP; } ~BoneGroupModifierData() { } }; class CharacterSlotInstance; class Skeleton; class CharacterModifiers : public Reference { HashMap > modifiers; template void create(const String &name, const String &gender) { Ref mod = memnew(T); mod->mod_name = name; mod->gender = gender; modifiers[name] = mod; } protected: bool mods_created; void init_blend_modifier(const String &name, BlendModifierData *bm); void init_bone_modifier(const String &name, BoneModifierData *bm, const Array ¶meters); void init_bone_group_modifier(const String &name, BoneGroupModifierData *bm, const Array ¶meters); Transform parse_transform(const Dictionary &xformdata); void create_mod(int type, const String &name, const String &gender, const Array ¶meters = Array()); public: CharacterModifiers() : mods_created(false) { } PoolVector get_modifier_list() const; PoolVector get_base_modifier_list() const; void create_modifiers(); void modify_bones(CharacterInstance *ci); void modify(CharacterSlotInstance *si, ModifierDataBase *mod, float value); void modify(Skeleton *skel, ModifierDataBase *mod, float value); void modify(CharacterInstance *ci, CharacterSlotInstance *si, const HashMap &values); static CharacterModifiers *get_singleton(); ~CharacterModifiers() { } }; class CharacterGender { friend class CharacterGenderList; friend class CharacterInstanceList; friend class CharacterInstance; String name; Ref scene; HashMap slot_list; String left_foot; String right_foot; String pelvis; }; class CharacterGenderList : public Reference { friend class CharacterInstanceList; GDCLASS(CharacterGenderList, Reference) CharacterGenderList(); protected: HashMap genders; static void _bind_methods(); Node *instance(const String &gender) { const CharacterGender &g = genders[gender]; Node *ret = g.scene->instance(); return ret; } public: void config(); void create_gender(const String &name, Ref base); void remove_gender(const String &name); static CharacterGenderList *get_singleton() { static CharacterGenderList *gl = NULL; if (!gl) gl = memnew(CharacterGenderList); return gl; } }; class CharacterInstance : public Reference { GDCLASS(CharacterInstance, Reference) friend class CharacterInstanceList; friend class CharacterModifiers; NodePath scene_root; HashMap slots; HashMap mod_values; int left_foot_id; int right_foot_id; int pelvis_id; bool mod_updated; CharacterGender *gender; CharacterInstance(): mod_updated(false), gender(NULL) { } Node *get_scene_root() const; Skeleton *get_skeleton() const; const String &get_gender_name() const { assert(gender); return gender->name; } }; class CharacterInstanceList : public Reference { GDCLASS(CharacterInstanceList, Reference) List > instance_list; protected: HashMap > > same_verts; static void _bind_methods(); protected: void init_slot(CharacterInstance *ci, CharacterSlotInstance *si); void update_slot(CharacterInstance *ci, CharacterSlotInstance *si); public: CharacterInstanceList() { } void remove(Node *scene); Node *create(const String &gender, const Transform &xform, const Dictionary &slot_conf); Ref get_instance(Node *scene); void set_mod_value(Node *scene, const String &mod, float value); Node *get_scene(CharacterInstance *ci); PoolVector get_modifier_list() { return CharacterModifiers::get_singleton()->get_modifier_list(); } PoolVector get_base_modifier_list() { return CharacterModifiers::get_singleton()->get_base_modifier_list(); } Dictionary get_instance_modifier_values(Node *scene) { Dictionary ret; Ref ci = get_instance(scene); for (const String *key = ci->mod_values.next(NULL); key; key = ci->mod_values.next(key)) ret[*key] = ci->mod_values[*key]; return ret; } float get_mod_value(Node *scene, const String &mod); Skeleton *get_skeleton(Node *scene) const; static CharacterInstanceList *get_singleton(); void update(); }; #endif