From 73ab158eec4a410d06bba2b5eca774f77a949d48 Mon Sep 17 00:00:00 2001 From: floralrainfall Date: Mon, 17 Jul 2023 19:03:49 -0400 Subject: [PATCH] ReflectionProperty --- Projects/Client/Studio/CMakeLists.txt | 2 + Projects/Client/Studio/Header/MainWindow.hpp | 2 + .../Client/Studio/Header/PropertyViewer.hpp | 16 +++++ Projects/Client/Studio/Source/MainWindow.cpp | 24 ++++--- .../Client/Studio/Source/PropertyViewer.cpp | 44 ++++++++++++ .../Header/App/Script/ReflectionProperty.hpp | 67 +++++++++++++------ Projects/Engine/Header/App/Script/Script.hpp | 9 +++ .../Header/App/V8/DataModel/PartInstance.hpp | 12 +--- .../Engine/Header/App/V8/Tree/Instance.hpp | 4 ++ .../Engine/Header/App/V8/Tree/PVInstance.hpp | 1 + Projects/Engine/Header/Helpers/Strings.hpp | 12 ++++ .../Source/App/Script/ReflectionProperty.cpp | 62 ++++++++++++++++- Projects/Engine/Source/App/Script/Script.cpp | 0 .../Source/App/V8/DataModel/PartInstance.cpp | 63 ++++------------- .../Source/App/V8/DataModel/Workspace.cpp | 12 ++-- .../Engine/Source/App/V8/Tree/Instance.cpp | 25 +++++++ .../Engine/Source/App/V8/Tree/PVInstance.cpp | 12 ++++ 17 files changed, 271 insertions(+), 96 deletions(-) create mode 100644 Projects/Client/Studio/Header/PropertyViewer.hpp create mode 100644 Projects/Client/Studio/Source/PropertyViewer.cpp create mode 100644 Projects/Engine/Header/App/Script/Script.hpp create mode 100644 Projects/Engine/Source/App/Script/Script.cpp diff --git a/Projects/Client/Studio/CMakeLists.txt b/Projects/Client/Studio/CMakeLists.txt index 6fddee1..6866b77 100644 --- a/Projects/Client/Studio/CMakeLists.txt +++ b/Projects/Client/Studio/CMakeLists.txt @@ -5,11 +5,13 @@ set(CMAKE_AUTOMOC ON) list(APPEND SOURCE Source/main.cpp Source/MainWindow.cpp + Source/PropertyViewer.cpp ) list(APPEND HEADER ${CMAKE_BINARY_DIR}/Resource/Studio.hpp Header/MainWindow.hpp + Header/PropertyViewer.hpp ) if(WIN32) diff --git a/Projects/Client/Studio/Header/MainWindow.hpp b/Projects/Client/Studio/Header/MainWindow.hpp index 0f16fe6..123987b 100644 --- a/Projects/Client/Studio/Header/MainWindow.hpp +++ b/Projects/Client/Studio/Header/MainWindow.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ class MainWindow : public QMainWindow QTreeWidget* explorer; QToolBar* toolbar; QMenuBar* menubar; + PropertyViewer* properties; void createToolbar(); void updateTree(RNR::Instance* root_instance); diff --git a/Projects/Client/Studio/Header/PropertyViewer.hpp b/Projects/Client/Studio/Header/PropertyViewer.hpp new file mode 100644 index 0000000..dce62a5 --- /dev/null +++ b/Projects/Client/Studio/Header/PropertyViewer.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include +#include + +class PropertyViewer : public QWidget +{ +private: + QTableWidget* prop_table; + 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 1d0128a..ec99918 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -16,22 +16,24 @@ MainWindow::MainWindow() ogreRoot->showConfigDialog(config); ogreRoot->initialise(false); - + menubar = new QMenuBar(); - grid->addWidget(menubar, 0, 0, 1, 2); - toolbar = new QToolBar(); - grid->addWidget(toolbar, 1, 0, 1, 2); - createToolbar(); + grid->addWidget(menubar, 0, 0, 1, 3); + grid->addWidget(toolbar, 1, 0, 1, 3); + this->ogreWidget = new RNR::OgreWidget(ogreRoot); - grid->addWidget(this->ogreWidget, 2, 0, 1, 2); + grid->addWidget(this->ogreWidget, 2, 0, 2, 2); explorer = new QTreeWidget(); connect(explorer, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(selectInstance(QTreeWidgetItem*, int))); grid->addWidget(explorer, 2, 2, 1, 1); + properties = new PropertyViewer(); + grid->addWidget(properties, 3, 2, 1, 1); + content_widget->setLayout(grid); grid->setContentsMargins(0, 0, 0, 0); @@ -39,6 +41,7 @@ MainWindow::MainWindow() setWindowTitle(QString("RNR Studio")); setWindowIcon(QIcon(pixmap)); setCentralWidget(content_widget); + } void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instance) @@ -58,10 +61,8 @@ void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instanc void MainWindow::selectInstance(QTreeWidgetItem *item, int column) { RNR::Instance* instance = item->data(0, Qt::UserRole).value(); - if(dynamic_cast(instance)) - { - ogreWidget->selectedInstance = instance; - } + ogreWidget->selectedInstance = instance; + properties->view(instance); } void MainWindow::recurseTreeAddInstance(QTreeWidgetItem* parent, RNR::Instance* instance) @@ -95,7 +96,7 @@ void MainWindow::updateTree(RNR::Instance* root_instance) void MainWindow::loadDatamodel() { - this->ogreWidget->world->load(QFileDialog::getOpenFileName(this, tr("Open RBXL"), tr(""), tr("RBXLs (*.rbxl)")).toLocal8Bit().data()); + this->ogreWidget->world->load(QFileDialog::getOpenFileName(this, tr("Open RBXL"), tr(""), tr("XML RBXLs (*.rbxl *.rbxlx)")).toLocal8Bit().data()); updateTree(ogreWidget->world->getDatamodel()); } @@ -117,5 +118,6 @@ void MainWindow::resizeEvent(QResizeEvent* event) { QSize new_size = event->size(); explorer->setMaximumWidth(new_size.width()/4); + properties->setMaximumWidth(new_size.width()/4); } \ No newline at end of file diff --git a/Projects/Client/Studio/Source/PropertyViewer.cpp b/Projects/Client/Studio/Source/PropertyViewer.cpp new file mode 100644 index 0000000..729269e --- /dev/null +++ b/Projects/Client/Studio/Source/PropertyViewer.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +PropertyViewer::PropertyViewer() : QWidget() +{ + prop_table = new QTableWidget(); + prop_table->verticalHeader()->setVisible(false); + prop_table->horizontalHeader()->setVisible(false); + prop_table->horizontalHeader()->setStretchLastSection(true); + prop_table->setColumnCount(2); + + prop_label = new QLabel(); + QVBoxLayout* layout = new QVBoxLayout(this); + layout->addWidget(prop_label); + layout->addWidget(prop_table); + + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + prop_label->setText("Properties"); +} + +void PropertyViewer::view(RNR::Instance* instance) +{ + prop_label->setText(QString::asprintf("%s Properties (%s)", instance->getName().c_str(), instance->getClassName().c_str())); + + std::vector properties = instance->getProperties(); + + prop_table->setRowCount(properties.size()); + + int property_count = 0; + 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()); + + prop_table->setItem(property_count, 0, new_property_item); + prop_table->setItem(property_count, 1, new_property_itemval); + property_count++; + } +} \ No newline at end of file diff --git a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp index 6bb63b4..e4ed259 100644 --- a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp +++ b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp @@ -2,6 +2,16 @@ #include #include +#include + +#define REFLECTION_GETTER(c) \ + [](const void* object) { c } +#define REFLECTION_NO_GETTER() \ + [](const void* object) { return (const void*)NULL; } +#define REFLECTION_SETTER(c) \ + [](void* object, const void* value) { c } +#define REFLECTION_NO_SETTER() \ + [](void* object, const void* value) { } namespace RNR { @@ -15,32 +25,51 @@ namespace RNR ACCESS_AUTHORIZED, }; - template + enum ReflectionPropertyOperation + { + OPERATION_READ, + OPERATION_READWRITE, + }; + + enum ReflectionPropertyType + { + PROPERTY_BOOL, + PROPERTY_STD_STRING, + PROPERTY_INTEGER, + PROPERTY_VECTOR2, + PROPERTY_VECTOR3, + PROPERTY_CFRAME, + PROPERTY_INSTANCE, + }; + class ReflectionProperty { private: + const void* m_object; std::string m_name; + std::string m_description; ReflectionPropertyAccess m_access; + ReflectionPropertyOperation m_op; + ReflectionPropertyType m_type; + std::function m_getter; + std::function m_setter; public: - ReflectionProperty(std::string name, ReflectionPropertyAccess access, T(*getter), T(*setter)) - { - this->m_name = name; - this->m_access = access; - this->getter = getter; - this->setter = setter; - } + // this == m_object + // getter returns an address to the value, + // setter sets the value to the contents of the address + ReflectionProperty(const void* m_object, + std::string name, + std::string description, + ReflectionPropertyAccess access, + ReflectionPropertyOperation op, + ReflectionPropertyType m_type, + std::function getter, + std::function setter); - bool access(ReflectionPropertyAccess accessor) - { - return this->m_access <= accessor; - } + bool access(ReflectionPropertyAccess accessor) { return this->m_access <= accessor; } + std::string name() { return m_name; } + std::string description() { return m_description; } - char* class_name() - { - return boost::typeindex::type_id().pretty_name(); - } - - T (*getter)(); - void (*setter)(T val); + std::string toString(); }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/Script/Script.hpp b/Projects/Engine/Header/App/Script/Script.hpp new file mode 100644 index 0000000..9e7aa2a --- /dev/null +++ b/Projects/Engine/Header/App/Script/Script.hpp @@ -0,0 +1,9 @@ +#pragma once + +namespace RNR +{ + class Script + { + + }; +} \ 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 8d87dd2..b760fca 100644 --- a/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp @@ -7,18 +7,17 @@ namespace RNR { - class PartInstance : public PVInstance, public Ogre::Renderable + class PartInstance : public PVInstance { protected: int m_brickColor; - Ogre::MaterialPtr m_material; Ogre::Matrix4 m_matrix; Ogre::Vector3 m_position; - Ogre::LightList m_nearbyLights; Ogre::Vector3 m_size; Ogre::Vector4 m_color; - static Ogre::MeshPtr m_partMesh; virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); + virtual void addProperties(std::vector& properties); + std::string mesh_id; public: PartInstance(); @@ -31,10 +30,5 @@ namespace RNR void setBrickColor(int brickcolor) { m_brickColor = brickcolor; } int getBrickColor() { return m_brickColor; } - virtual const Ogre::MaterialPtr& getMaterial() const; - virtual void getRenderOperation(Ogre::RenderOperation& op); - virtual Ogre::Real getSquaredViewDepth(const Ogre::Camera* cam) const; - virtual const Ogre::LightList& getLights() const; - virtual void getWorldTransforms(Ogre::Matrix4* xform) const; }; } \ 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 8c53f1e..361d617 100644 --- a/Projects/Engine/Header/App/V8/Tree/Instance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/Instance.hpp @@ -9,6 +9,8 @@ #include #include +#include + namespace RNR { class World; @@ -18,6 +20,7 @@ namespace RNR protected: static World* world; virtual void deserializeProperty(char* prop_name, pugi::xml_node prop) {}; + virtual void addProperties(std::vector& properties) {}; private: @@ -32,6 +35,7 @@ namespace RNR Instance(); ~Instance(); + virtual std::vector getProperties(); void deserializeXmlProperty(pugi::xml_node prop); bool contains(RNR::Instance* child); diff --git a/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp b/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp index da833f5..94508b1 100644 --- a/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp @@ -9,6 +9,7 @@ namespace RNR protected: CoordinateFrame m_cframe; virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); + virtual void addProperties(std::vector& properties); public: PVInstance(); diff --git a/Projects/Engine/Header/Helpers/Strings.hpp b/Projects/Engine/Header/Helpers/Strings.hpp index 61121a2..447dc8a 100644 --- a/Projects/Engine/Header/Helpers/Strings.hpp +++ b/Projects/Engine/Header/Helpers/Strings.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -13,5 +14,16 @@ namespace RNR public: static uint8_t random_char(); static std::string random_hex(const uint64_t length); + + template + static std::string string_format( const std::string& format, Args ... args ) + { + int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0' + if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); } + auto size = static_cast( size_s ); + std::unique_ptr buf( new char[ size ] ); + std::snprintf( buf.get(), size, format.c_str(), args ... ); + return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside + } }; } \ 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 351fac5..b528e27 100644 --- a/Projects/Engine/Source/App/Script/ReflectionProperty.cpp +++ b/Projects/Engine/Source/App/Script/ReflectionProperty.cpp @@ -1,6 +1,66 @@ #include +#include +#include +#include +#include namespace RNR { - + ReflectionProperty::ReflectionProperty(const void* object, + std::string name, + std::string description, + ReflectionPropertyAccess access, + ReflectionPropertyOperation op, + ReflectionPropertyType type, + std::function getter, + std::function setter) + { + this->m_object = object; + this->m_name = name; + this->m_access = access; + this->m_op = op; + this->m_type = type; + this->m_getter = getter; + this->m_setter = setter; + } + + std::string ReflectionProperty::toString() + { + switch(m_type) + { + case PROPERTY_STD_STRING: + return *(std::string*)m_getter(m_object); + case PROPERTY_BOOL: + return std::string((*(bool*)m_getter(m_object))?"true":"false"); + case PROPERTY_INSTANCE: + { + Instance* instance = (Instance*)m_getter(m_object); + return instance->getName(); + } + case PROPERTY_VECTOR3: + { + Ogre::Vector3 vector = *(Ogre::Vector3*)m_getter(m_object); + return Strings::string_format("(%f,%f,%f)", + vector.x, + vector.y, + vector.z); + } + 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)", + cframe_position.x, + cframe_position.y, + cframe_position.z, + cframe_rotation.x, + cframe_rotation.y, + cframe_rotation.z, + cframe_rotation.w); + } + default: + return std::string("???"); + } + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/Script/Script.cpp b/Projects/Engine/Source/App/Script/Script.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp index bbe3f3f..bb69135 100644 --- a/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp @@ -4,20 +4,12 @@ namespace RNR { - Ogre::MeshPtr PartInstance::m_partMesh = 0; - - PartInstance::PartInstance() : m_matrix(), PVInstance(), Ogre::Renderable(), m_size(2.f, STUD_HEIGHT, 4.f) + PartInstance::PartInstance() : m_matrix(), PVInstance(), m_size(2.f, STUD_HEIGHT, 4.f) { setName("Part"); updateMatrix(); - m_nearbyLights = Ogre::LightList(); - m_nearbyLights.insert(m_nearbyLights.begin(), world->getOgreSceneManager()->getLight("SunLight")); m_color = Ogre::Vector4(0.63, 0.64, 0.63, 1.0); - - if(m_partMesh == 0) - m_partMesh = Ogre::Root::getSingletonPtr()->getMeshManager()->load("fonts/Cube.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); - m_material = m_partMesh->getSubMesh(0)->getMaterial(); } void PartInstance::updateMatrix() @@ -26,46 +18,6 @@ namespace RNR m_position = m_cframe.getPosition(); } - const Ogre::MaterialPtr& PartInstance::getMaterial() const - { - return m_material; - } - - void PartInstance::getRenderOperation(Ogre::RenderOperation& op) - { - Ogre::SubMesh* submesh = m_partMesh->getSubMesh(0); - if(submesh) - { - op.operationType = op.OT_TRIANGLE_LIST; - if(submesh->useSharedVertices == false) - op.vertexData = submesh->vertexData; - else - op.vertexData = m_partMesh->sharedVertexData; - op.indexData = submesh->indexData; - op.numberOfInstances = 1; - op.srcRenderable = this; - op.useIndexes = true; - } - else - printf("BasePart::getRenderOperation: couldnt get submesh\n"); - } - - Ogre::Real PartInstance::getSquaredViewDepth(const Ogre::Camera* cam) const - { - Ogre::Vector3 diff = m_position - cam->getDerivedPosition(); - return diff.squaredLength(); - } - - const Ogre::LightList& PartInstance::getLights() const - { - return m_nearbyLights; - } - - void PartInstance::getWorldTransforms(Ogre::Matrix4* xform) const - { - *xform = m_matrix; - } - void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node) { if(prop_name == std::string("size")) @@ -83,4 +35,17 @@ namespace RNR else PVInstance::deserializeProperty(prop_name, node); } + + void PartInstance::addProperties(std::vector& properties) + { + ReflectionProperty _properties[] = { + { this, std::string("Size"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3, + REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_size; ), + REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setSize(*(Ogre::Vector3*)value); ) }, + }; + + PVInstance::addProperties(properties); + properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp index de65c9e..c21b85d 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -34,11 +34,10 @@ namespace RNR Ogre::Vector3 part_size = child_part->getSize(); for(int i = 0; i < m_partEntity->getNumSubEntities(); i++) { - Ogre::SubEntity* surface = m_partEntity->getSubEntity(i); + Ogre::SubMesh* surface = m_partEntity->getMesh()->getSubMesh(i); Ogre::TextureUnitState* texture = surface->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0); Ogre::Vector2 uvs; - std::string surf_name = std::string(surface->getMaterialName().c_str()); if(surf_name == "TopMaterial") uvs = Ogre::Vector2(part_size.x, part_size.z); @@ -53,13 +52,12 @@ namespace RNR else if(surf_name == "FrontMaterial") uvs = Ogre::Vector2(-part_size.x, part_size.z); - texture->setTextureScale(uvs.x,uvs.y); + } m_geom->addEntity(m_partEntity, - child_part->getCFrame().getPosition(), - Ogre::Quaternion(child_part->getCFrame().getRotation()), - child_part->getSize()); - + child_part->getCFrame().getPosition(), + Ogre::Quaternion(child_part->getCFrame().getRotation()), + child_part->getSize()); } for(auto& child : *instance->getChildren()) buildGeomInstance(child); diff --git a/Projects/Engine/Source/App/V8/Tree/Instance.cpp b/Projects/Engine/Source/App/V8/Tree/Instance.cpp index c07d7f5..06adae0 100644 --- a/Projects/Engine/Source/App/V8/Tree/Instance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/Instance.cpp @@ -17,6 +17,31 @@ namespace RNR setParent(NULL); } + std::vector Instance::getProperties() + { + ReflectionProperty properties[] = { + { this, std::string("Name"), std::string(""), + 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(""), + 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(""), + 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; ) }, + }; + + std::vector _properties(properties, properties+(sizeof(properties)/sizeof(ReflectionProperty))); + addProperties(_properties); + + return _properties; + } + void Instance::deserializeXmlProperty(pugi::xml_node prop) { pugi::xml_attribute prop_name = prop.attribute("name"); diff --git a/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp b/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp index f9e5e45..6029dd5 100644 --- a/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/PVInstance.cpp @@ -15,4 +15,16 @@ namespace RNR setCFrame(XML::getCFrame(node)); } } + + void PVInstance::addProperties(std::vector& properties) + { + ReflectionProperty _properties[] = { + { this, std::string("CFrame"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_CFRAME, + REFLECTION_GETTER(PVInstance* instance = (PVInstance*)object; return &instance->m_cframe; ), + REFLECTION_SETTER(PVInstance* instance = (PVInstance*)object; instance->setCFrame(*(CoordinateFrame*)value); ) }, + }; + + properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); + } } \ No newline at end of file