diff --git a/Content/RNR/textures/studio/icons/Humanoid.png b/Content/RNR/textures/studio/icons/Humanoid.png new file mode 100644 index 0000000..62775f8 Binary files /dev/null and b/Content/RNR/textures/studio/icons/Humanoid.png differ diff --git a/Projects/Engine/Header/App/Humanoid/Humanoid.hpp b/Projects/Engine/Header/App/Humanoid/Humanoid.hpp index 81769a2..197acff 100644 --- a/Projects/Engine/Header/App/Humanoid/Humanoid.hpp +++ b/Projects/Engine/Header/App/Humanoid/Humanoid.hpp @@ -1,23 +1,34 @@ #pragma once #include +#include namespace RNR { - class Humanoid : Instance + class Humanoid : public Instance { public: Humanoid(); ~Humanoid(); + + virtual std::string getClassName() { return "Humanoid"; } bool canSit(); void buildJoints(); void checkForJointDeath(); void computeForce(float force, bool throttling); - void getTorso(); - void getHead(); - + PartInstance* getTorso(); + PartInstance* getHead(); + + void createHealthBar(); + + float getHealth() { return m_health; }; + void setHealth(float health) { m_health = health; } + float getMaxHealth() { return m_maxHealth; } + void setMaxHealth(float maxHealth) { m_maxHealth = maxHealth; } private: + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); + virtual void addProperties(std::vector& properties); float m_health; float m_maxHealth; float m_walkRotationalVelocity; diff --git a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp index e4ed259..e3c6942 100644 --- a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp +++ b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp @@ -40,6 +40,7 @@ namespace RNR PROPERTY_VECTOR3, PROPERTY_CFRAME, PROPERTY_INSTANCE, + PROPERTY_FLOAT, }; class ReflectionProperty diff --git a/Projects/Engine/Header/App/V8/DataModel/FaceInstance.hpp b/Projects/Engine/Header/App/V8/DataModel/FaceInstance.hpp index 823e166..531f5e1 100644 --- a/Projects/Engine/Header/App/V8/DataModel/FaceInstance.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/FaceInstance.hpp @@ -11,6 +11,8 @@ namespace RNR NormalId m_face; public: - + FaceInstance(); + + virtual void build() = 0; }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/Tree/Instance.hpp b/Projects/Engine/Header/App/V8/Tree/Instance.hpp index 361d617..a0a7a60 100644 --- a/Projects/Engine/Header/App/V8/Tree/Instance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/Instance.hpp @@ -40,7 +40,11 @@ namespace RNR bool contains(RNR::Instance* child); bool isAncestorOf(RNR::Instance* instance); + bool isA(std::string type); + Instance* findFirstChild(std::string name); + Instance* findFirstChildOfType(std::string type); + static World* getWorld() { return Instance::world; } static void setWorld(World* world) { Instance::world = world; } diff --git a/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp b/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp index 1bc14ad..74f3ab2 100644 --- a/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp @@ -11,6 +11,7 @@ namespace RNR virtual void build(); Ogre::AxisAlignedBox getBoundingBox() { return m_boundingbox; } virtual std::string getClassName() { return "Model"; } + virtual void onChildAdded(Instance* instance); private: Ogre::AxisAlignedBox m_boundingbox; diff --git a/Projects/Engine/Source/App/Humanoid/Humanoid.cpp b/Projects/Engine/Source/App/Humanoid/Humanoid.cpp index 13862e5..cf7c50d 100644 --- a/Projects/Engine/Source/App/Humanoid/Humanoid.cpp +++ b/Projects/Engine/Source/App/Humanoid/Humanoid.cpp @@ -1,4 +1,5 @@ #include +#include namespace RNR { @@ -32,13 +33,59 @@ namespace RNR // } - void Humanoid::getTorso() + void Humanoid::createHealthBar() { - // + if(!getHead()) + { + printf("Humanoid::createHealthBar: no head\n"); + return; + } + if(getNode()) + world->getOgreSceneManager()->destroySceneNode(getNode()); + setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); + Ogre::BillboardSet* healthBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidHealth" + getParent()->getName()); + Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(100, 0, 200)); + getNode()->attachObject(healthBarSet); + getNode()->setPosition(getHead()->getPosition()); + + printf("Humanoid::createHealthBar: WIP"); } - void Humanoid::getHead() + void Humanoid::deserializeProperty(char* prop_name, pugi::xml_node prop) { - // + if(prop_name == std::string("Health")) + { + setHealth(prop.text().as_float()); + } + else if(prop_name == std::string("MaxHealth")) + { + setMaxHealth(prop.text().as_float()); + } + } + + void Humanoid::addProperties(std::vector& properties) + { + ReflectionProperty _properties[] = { + { this, std::string("Health"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_FLOAT, + REFLECTION_GETTER(Humanoid* instance = (Humanoid*)object; return &instance->m_health; ), + REFLECTION_SETTER(Humanoid* instance = (Humanoid*)object; instance->setHealth(*(float*)value); ) }, + { this, std::string("MaxHealth"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_FLOAT, + REFLECTION_GETTER(Humanoid* instance = (Humanoid*)object; return &instance->m_maxHealth; ), + REFLECTION_SETTER(Humanoid* instance = (Humanoid*)object; instance->setMaxHealth(*(float*)value); ) }, + }; + + properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); + } + + PartInstance* Humanoid::getTorso() + { + return (PartInstance*)getParent()->findFirstChild("Torso"); + } + + PartInstance* Humanoid::getHead() + { + return (PartInstance*)getParent()->findFirstChild("Head"); } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/Script/ReflectionProperty.cpp b/Projects/Engine/Source/App/Script/ReflectionProperty.cpp index ca3bbb7..77dfa92 100644 --- a/Projects/Engine/Source/App/Script/ReflectionProperty.cpp +++ b/Projects/Engine/Source/App/Script/ReflectionProperty.cpp @@ -47,12 +47,15 @@ namespace RNR vector.y, vector.z); } + case PROPERTY_FLOAT: + return Strings::string_format("%f", + *(float*)m_getter(m_object)); case PROPERTY_CFRAME: { CoordinateFrame cframe = *(CoordinateFrame*)m_getter(m_object); Ogre::Vector3 cframe_position = cframe.getPosition(); Ogre::Quaternion cframe_rotation = Ogre::Quaternion(cframe.getRotation()); - return Strings::string_format("(%f,%f,%f)), (%f,%f,%f,%f)", + return Strings::string_format("(%f,%f,%f), (%f,%f,%f,%f)", cframe_position.x, cframe_position.y, cframe_position.z, diff --git a/Projects/Engine/Source/App/V8/DataModel/FaceInstance.cpp b/Projects/Engine/Source/App/V8/DataModel/FaceInstance.cpp index c64a5c2..228dbcd 100644 --- a/Projects/Engine/Source/App/V8/DataModel/FaceInstance.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/FaceInstance.cpp @@ -1,7 +1,15 @@ #include +#include +#include #include +#include namespace RNR { - + FaceInstance::FaceInstance() : Ogre::ManualObject(Strings::random_hex(8)) + { + setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); + getNode()->attachObject(this); + build(); + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/Tree/Instance.cpp b/Projects/Engine/Source/App/V8/Tree/Instance.cpp index 3796bdc..5f1816f 100644 --- a/Projects/Engine/Source/App/V8/Tree/Instance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/Instance.cpp @@ -159,4 +159,29 @@ namespace RNR { } + + bool Instance::isA(std::string type) + { + if (type == getClassName()); // TODO: check if type is any of parent types + } + + Instance* Instance::findFirstChild(std::string name) + { + for(auto& child : m_children) + { + if(child->getName() == name) + return child; + } + return NULL; + } + + Instance* Instance::findFirstChildOfType(std::string type) + { + for(auto& child : m_children) + { + if(child->isA(type)) + return child; + } + return NULL; + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp b/Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp index 4eb6253..833732a 100644 --- a/Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace RNR { @@ -27,4 +28,13 @@ namespace RNR m_boundingbox.merge(child_pv->getPosition() - size); } } + + void ModelInstance::onChildAdded(Instance* instance) + { + if(instance->getClassName() == "Humanoid") + { + Humanoid* instance_humanoid = (Humanoid*)instance; + instance_humanoid->createHealthBar(); + } + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp b/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp index 6029dd5..f9502f2 100644 --- a/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace RNR diff --git a/Projects/Engine/Source/App/V8/World/World.cpp b/Projects/Engine/Source/App/V8/World/World.cpp index dad12b7..f23405c 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include namespace RNR @@ -46,6 +47,10 @@ namespace RNR { instance = new ModelInstance(); } + else if(class_attr.as_string() == std::string("Humanoid")) + { + instance = new Humanoid(); + } else { instance = new Instance(); @@ -67,11 +72,6 @@ namespace RNR { xmlAddItem(item, instance); } - - if(class_attr.as_string() == std::string("Model")) - { - ((ModelInstance*)instance)->build(); - } } void World::load(char* path)