diff --git a/Content/RNR/textures/studio/icons/PartInstance.png b/Content/RNR/textures/studio/icons/Part.png similarity index 100% rename from Content/RNR/textures/studio/icons/PartInstance.png rename to Content/RNR/textures/studio/icons/Part.png diff --git a/Projects/Client/Studio/Header/PropertyViewer.hpp b/Projects/Client/Studio/Header/PropertyViewer.hpp index dce62a5..b7ad755 100644 --- a/Projects/Client/Studio/Header/PropertyViewer.hpp +++ b/Projects/Client/Studio/Header/PropertyViewer.hpp @@ -11,6 +11,6 @@ private: QLabel* prop_label; public: PropertyViewer(); - + void view(RNR::Instance* instance); }; \ No newline at end of file diff --git a/Projects/Client/Studio/Source/MainWindow.cpp b/Projects/Client/Studio/Source/MainWindow.cpp index ec99918..c763386 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -82,6 +82,7 @@ void MainWindow::recurseTreeAddInstance(QTreeWidgetItem* parent, RNR::Instance* void MainWindow::updateTree(RNR::Instance* root_instance) { + explorer->clear(); for(auto& child : *root_instance->getChildren()) { QTreeWidgetItem* parent = new QTreeWidgetItem(); diff --git a/Projects/Client/Studio/Source/PropertyViewer.cpp b/Projects/Client/Studio/Source/PropertyViewer.cpp index 729269e..f548ad4 100644 --- a/Projects/Client/Studio/Source/PropertyViewer.cpp +++ b/Projects/Client/Studio/Source/PropertyViewer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include PropertyViewer::PropertyViewer() : QWidget() { @@ -9,6 +10,8 @@ PropertyViewer::PropertyViewer() : QWidget() prop_table->horizontalHeader()->setVisible(false); prop_table->horizontalHeader()->setStretchLastSection(true); prop_table->setColumnCount(2); + prop_table->setMouseTracking(true); + prop_table->viewport()->setMouseTracking(true); prop_label = new QLabel(); QVBoxLayout* layout = new QVBoxLayout(this); @@ -33,12 +36,55 @@ void PropertyViewer::view(RNR::Instance* instance) for(auto& property : properties) { QTableWidgetItem* new_property_item = new QTableWidgetItem(tr("%1").arg(property.name().c_str())); - QTableWidgetItem* new_property_itemval = new QTableWidgetItem(tr("%1").arg(property.toString().c_str())); - new_property_item->setStatusTip(property.description().c_str()); + Qt::ItemFlags cell_flags = new_property_item->flags(); + cell_flags.setFlag(Qt::ItemFlag::ItemIsEditable, false); + new_property_item->setFlags(cell_flags); + new_property_item->setToolTip(QString(property.description().c_str())); + + QTableWidgetItem* new_property_itemval = new QTableWidgetItem(tr("%1").arg(property.toString().c_str())); + new_property_itemval->setToolTip(QString(property.description().c_str())); + + switch(property.type()) + { + case RNR::PROPERTY_BOOL: + { + bool check_state = *(bool*)property.rawGetter(); + new_property_itemval->setCheckState(check_state ? Qt::Checked : Qt::Unchecked); + new_property_itemval->setText(""); + + cell_flags = new_property_itemval->flags(); + cell_flags.setFlag(Qt::ItemFlag::ItemIsEditable, false); + new_property_itemval->setFlags(cell_flags); + } + break; + case RNR::PROPERTY_INSTANCE: + { + cell_flags = new_property_itemval->flags(); + cell_flags.setFlag(Qt::ItemFlag::ItemIsEditable, false); + new_property_itemval->setFlags(cell_flags); + + RNR::Instance* instance_ref = (RNR::Instance*)property.rawGetter(); + if(!instance_ref) + break; + QImage image; + QString icon_path; + icon_path = "content/textures/studio/icons/"; + icon_path += instance_ref->getClassName(); + icon_path += ".png"; + if(QFile::exists(icon_path)) + image = QImage(icon_path); + else + image = QImage("content/textures/studio/icons/Instance.png"); + new_property_itemval->setData(Qt::DecorationRole, QPixmap::fromImage(image)); + } + break; + } prop_table->setItem(property_count, 0, new_property_item); prop_table->setItem(property_count, 1, new_property_itemval); property_count++; } + + prop_table->resizeRowsToContents(); } \ No newline at end of file diff --git a/Projects/Engine/CMakeLists.txt b/Projects/Engine/CMakeLists.txt index 644915a..0abd61d 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -10,11 +10,13 @@ add_library(Engine STATIC Header/App/GUI/TopMenuBar.hpp Header/App/Humanoid/Humanoid.hpp Header/App/V8/DataModel/Camera.hpp + Header/App/V8/DataModel/DataModel.hpp Header/App/V8/DataModel/ForceField.hpp Header/App/V8/DataModel/PartInstance.hpp Header/App/V8/DataModel/FaceInstance.hpp Header/App/V8/DataModel/Workspace.hpp Header/App/V8/Tree/Instance.hpp + Header/App/V8/Tree/InstanceFactory.hpp Header/App/V8/Tree/PVInstance.hpp Header/App/V8/Tree/ModelInstance.hpp Header/App/V8/World/World.hpp @@ -34,11 +36,13 @@ add_library(Engine STATIC Source/App/GUI/TopMenuBar.cpp Source/App/Humanoid/Humanoid.cpp Source/App/V8/DataModel/Camera.cpp + Source/App/V8/DataModel/DataModel.cpp Source/App/V8/DataModel/ForceField.cpp Source/App/V8/DataModel/PartInstance.cpp Source/App/V8/DataModel/FaceInstance.cpp Source/App/V8/DataModel/Workspace.cpp Source/App/V8/Tree/Instance.cpp + Source/App/V8/Tree/InstanceFactory.cpp Source/App/V8/Tree/PVInstance.cpp Source/App/V8/Tree/ModelInstance.cpp Source/App/CoordinateFrame.cpp diff --git a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp index e3c6942..f2ee8d1 100644 --- a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp +++ b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp @@ -70,6 +70,10 @@ namespace RNR bool access(ReflectionPropertyAccess accessor) { return this->m_access <= accessor; } std::string name() { return m_name; } std::string description() { return m_description; } + ReflectionPropertyType type() { return m_type; } + + const void* rawGetter() { return m_getter(m_object); } + void rawSetter(const void* value) { return m_setter((void*)m_object, value); } std::string toString(); }; diff --git a/Projects/Engine/Header/App/V8/DataModel/DataModel.hpp b/Projects/Engine/Header/App/V8/DataModel/DataModel.hpp new file mode 100644 index 0000000..1f0a85c --- /dev/null +++ b/Projects/Engine/Header/App/V8/DataModel/DataModel.hpp @@ -0,0 +1,14 @@ +#pragma once +#include + +namespace RNR +{ + class DataModel : public Instance + { + public: + DataModel(); + + private: + + }; +} \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp index b760fca..c88c466 100644 --- a/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp @@ -23,7 +23,7 @@ namespace RNR void updateMatrix(); - virtual std::string getClassName() { return "PartInstance"; } + virtual std::string getClassName() { return "Part"; } void setSize(Ogre::Vector3 size) { m_size = size; } Ogre::Vector3 getSize() { return m_size; } Ogre::Vector4 getColor() { return m_color; } diff --git a/Projects/Engine/Header/App/V8/Tree/InstanceFactory.hpp b/Projects/Engine/Header/App/V8/Tree/InstanceFactory.hpp new file mode 100644 index 0000000..fcce646 --- /dev/null +++ b/Projects/Engine/Header/App/V8/Tree/InstanceFactory.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include + +namespace RNR +{ + class InstanceFactory + { + public: + typedef std::function InstanceBuilder; + InstanceFactory(); + + bool registerInstance(std::string key, InstanceBuilder builder); + Instance* build(std::string key); + + static InstanceFactory* singleton() { return m_singleton; }; + + // default builder + template + static Instance* instanceBuilder() { return new Derived(); } + private: + static InstanceFactory* m_singleton; + std::map m_builders; + }; + +} diff --git a/Projects/Engine/Source/App/V8/DataModel/DataModel.cpp b/Projects/Engine/Source/App/V8/DataModel/DataModel.cpp new file mode 100644 index 0000000..2f89d72 --- /dev/null +++ b/Projects/Engine/Source/App/V8/DataModel/DataModel.cpp @@ -0,0 +1,9 @@ +#include + +namespace RNR +{ + DataModel::DataModel() + { + + } +} diff --git a/Projects/Engine/Source/App/V8/Tree/Instance.cpp b/Projects/Engine/Source/App/V8/Tree/Instance.cpp index 5f1816f..a10e6ed 100644 --- a/Projects/Engine/Source/App/V8/Tree/Instance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/Instance.cpp @@ -20,17 +20,17 @@ namespace RNR std::vector Instance::getProperties() { ReflectionProperty properties[] = { - { this, std::string("Name"), std::string(""), + { this, std::string("Name"), std::string("This is the name of this Instance."), ACCESS_NONE, OPERATION_READWRITE, PROPERTY_STD_STRING, REFLECTION_GETTER(Instance* instance = (Instance*)object; return &instance->m_name; ), REFLECTION_SETTER(Instance* instance = (Instance*)object; instance->setName(*(std::string*)value); ) }, - { this, std::string("Parent"), std::string(""), + { this, std::string("Parent"), std::string("This is the parent of this Instance."), ACCESS_NONE, OPERATION_READ, PROPERTY_INSTANCE, REFLECTION_GETTER(Instance* instance = (Instance*)object; return instance->m_parent; ), REFLECTION_NO_SETTER() }, - { this, std::string("Archivable"), std::string(""), + { this, std::string("Archivable"), std::string("This determines whether this Instance may be saved or replicated."), ACCESS_NONE, OPERATION_READWRITE, PROPERTY_BOOL, REFLECTION_GETTER(Instance* instance = (Instance*)object; return &instance->m_archivable; ), REFLECTION_SETTER(Instance* instance = (Instance*)object; instance->m_archivable = *(bool*)value; ) }, diff --git a/Projects/Engine/Source/App/V8/Tree/InstanceFactory.cpp b/Projects/Engine/Source/App/V8/Tree/InstanceFactory.cpp new file mode 100644 index 0000000..919e983 --- /dev/null +++ b/Projects/Engine/Source/App/V8/Tree/InstanceFactory.cpp @@ -0,0 +1,28 @@ +#include + +namespace RNR +{ + InstanceFactory* InstanceFactory::m_singleton = 0; + + InstanceFactory::InstanceFactory() : m_builders() + { + m_singleton = this; + } + + bool InstanceFactory::registerInstance(std::string key, InstanceFactory::InstanceBuilder builder) + { + printf("InstanceFactory::registerInstance: registering %s\n", key.c_str()); + bool ok = m_builders.insert(std::make_pair(key, builder)).second; + if(!ok) + printf("InstanceFactory::registerInstance: could not register\n"); + return ok; + } + + Instance* InstanceFactory::build(std::string key) + { + auto it = m_builders.find(key); + if(it == m_builders.end()) + throw std::runtime_error("Invalid instance " + key); + return it->second(); + } +} \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/World/World.cpp b/Projects/Engine/Source/App/V8/World/World.cpp index f23405c..df8e70b 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include namespace RNR @@ -17,6 +19,15 @@ namespace RNR m_workspace = new Workspace(); m_workspace->setParent(m_datamodel); + InstanceFactory(); + + InstanceFactory::singleton()->registerInstance("Camera", InstanceFactory::instanceBuilder); + InstanceFactory::singleton()->registerInstance("Model", InstanceFactory::instanceBuilder); + InstanceFactory::singleton()->registerInstance("SelectionBox", InstanceFactory::instanceBuilder); + InstanceFactory::singleton()->registerInstance("Part", InstanceFactory::instanceBuilder); + InstanceFactory::singleton()->registerInstance("Workspace", InstanceFactory::instanceBuilder); + InstanceFactory::singleton()->registerInstance("Humanoid", InstanceFactory::instanceBuilder); + m_tmb = new TopMenuBar(); } @@ -27,10 +38,20 @@ namespace RNR void World::xmlAddItem(pugi::xml_node node, Instance* parent) { - bool skip = false; - Instance* instance; pugi::xml_attribute class_attr = node.attribute("class"); + Instance* instance; + + /* + try{ + instance = InstanceFactory::singleton()->build(class_attr.as_string()); + } + catch(std::runtime_error e) + { + printf("World::xmlAddItem: InstanceFactory::build failed '%s'\n", e.what()); + return; + }*/ + if(class_attr.as_string() == std::string("Part")) { instance = new PartInstance(); @@ -56,22 +77,17 @@ namespace RNR instance = new Instance(); } - if(!skip) - { - pugi::xml_attribute referent = node.attribute("referent"); - if(!referent.empty()) - m_refs[referent.as_string()] = instance; - WorldUndeserialized s; - s.instance = instance; - s.node = node; - m_undeserialized.push(s); - instance->setParent(parent); - } + pugi::xml_attribute referent = node.attribute("referent"); + if(!referent.empty()) + m_refs[referent.as_string()] = instance; + WorldUndeserialized s; + s.instance = instance; + s.node = node; + m_undeserialized.push(s); + instance->setParent(parent); for(pugi::xml_node item = node.child("Item"); item; item = item.next_sibling("Item")) - { xmlAddItem(item, instance); - } } void World::load(char* path)