InstanceFactory, make PropertyViewer better, DataModel

This commit is contained in:
floralrainfall 2023-07-18 18:46:04 -04:00
parent d976800f38
commit a1cea61ce2
13 changed files with 170 additions and 22 deletions

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -11,6 +11,6 @@ private:
QLabel* prop_label;
public:
PropertyViewer();
void view(RNR::Instance* instance);
};

View File

@ -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();

View File

@ -1,6 +1,7 @@
#include <PropertyViewer.hpp>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QFile>
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();
}

View File

@ -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

View File

@ -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();
};

View File

@ -0,0 +1,14 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
namespace RNR
{
class DataModel : public Instance
{
public:
DataModel();
private:
};
}

View File

@ -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; }

View File

@ -0,0 +1,26 @@
#pragma once
#include <functional>
#include <App/V8/Tree/Instance.hpp>
namespace RNR
{
class InstanceFactory
{
public:
typedef std::function<Instance*()> InstanceBuilder;
InstanceFactory();
bool registerInstance(std::string key, InstanceBuilder builder);
Instance* build(std::string key);
static InstanceFactory* singleton() { return m_singleton; };
// default builder
template <typename Derived>
static Instance* instanceBuilder() { return new Derived(); }
private:
static InstanceFactory* m_singleton;
std::map<std::string, InstanceBuilder> m_builders;
};
}

View File

@ -0,0 +1,9 @@
#include <App/V8/DataModel/DataModel.hpp>
namespace RNR
{
DataModel::DataModel()
{
}
}

View File

@ -20,17 +20,17 @@ namespace RNR
std::vector<ReflectionProperty> 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; ) },

View File

@ -0,0 +1,28 @@
#include <App/V8/Tree/InstanceFactory.hpp>
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();
}
}

View File

@ -1,7 +1,9 @@
#include <App/V8/World/World.hpp>
#include <App/V8/Tree/InstanceFactory.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/GUI/SelectionBox.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <stdexcept>
#include <pugixml.hpp>
namespace RNR
@ -17,6 +19,15 @@ namespace RNR
m_workspace = new Workspace();
m_workspace->setParent(m_datamodel);
InstanceFactory();
InstanceFactory::singleton()->registerInstance("Camera", InstanceFactory::instanceBuilder<Camera>);
InstanceFactory::singleton()->registerInstance("Model", InstanceFactory::instanceBuilder<ModelInstance>);
InstanceFactory::singleton()->registerInstance("SelectionBox", InstanceFactory::instanceBuilder<SelectionBox>);
InstanceFactory::singleton()->registerInstance("Part", InstanceFactory::instanceBuilder<PartInstance>);
InstanceFactory::singleton()->registerInstance("Workspace", InstanceFactory::instanceBuilder<Workspace>);
InstanceFactory::singleton()->registerInstance("Humanoid", InstanceFactory::instanceBuilder<Humanoid>);
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)