diff --git a/Content/RNR/textures/studio/icons/Instance.png b/Content/RNR/textures/studio/icons/Instance.png new file mode 100644 index 0000000..07e204d Binary files /dev/null and b/Content/RNR/textures/studio/icons/Instance.png differ diff --git a/Content/RNR/textures/studio/icons/PartInstance.png b/Content/RNR/textures/studio/icons/PartInstance.png new file mode 100644 index 0000000..ad2d9c6 Binary files /dev/null and b/Content/RNR/textures/studio/icons/PartInstance.png differ diff --git a/Content/RNR/textures/studio/icons/SelectionBox.png b/Content/RNR/textures/studio/icons/SelectionBox.png new file mode 100644 index 0000000..34ff5a0 Binary files /dev/null and b/Content/RNR/textures/studio/icons/SelectionBox.png differ diff --git a/Content/RNR/textures/studio/icons/Workspace.png b/Content/RNR/textures/studio/icons/Workspace.png new file mode 100644 index 0000000..3cdc792 Binary files /dev/null and b/Content/RNR/textures/studio/icons/Workspace.png differ diff --git a/Content/win32_plugins.cfg b/Content/win32_plugins.cfg index 5ee47a6..20178ba 100644 --- a/Content/win32_plugins.cfg +++ b/Content/win32_plugins.cfg @@ -1,7 +1,7 @@ # Defines plugins to load # Define plugin folder -PluginFolder=. +PluginFolder=plugins # Define plugins Plugin=RenderSystem_Direct3D9 diff --git a/Projects/Client/Common/Source/OgreWidget.cpp b/Projects/Client/Common/Source/OgreWidget.cpp index d4efec9..43f5ea7 100644 --- a/Projects/Client/Common/Source/OgreWidget.cpp +++ b/Projects/Client/Common/Source/OgreWidget.cpp @@ -73,6 +73,9 @@ namespace RNR Ogre::ResourceGroupManager::getSingletonPtr()->addResourceLocation("content", "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups(); + ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE); + ogreSceneManager->setShadowFarDistance(500.f); + Ogre::Light* light = ogreSceneManager->createLight("SunLight"); Ogre::SceneNode* lightNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode(); lightNode->setPosition(0, 10, 15); @@ -84,9 +87,6 @@ namespace RNR light->setSpecularColour(1.0, 1.0, 1.0); light->setType(Ogre::Light::LT_DIRECTIONAL); - ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE); - ogreSceneManager->setShadowFarDistance(500.f); - Ogre::MaterialManager::getSingletonPtr()->reloadAll(); Ogre::MaterialManager::getSingletonPtr()->load("sky/null_plainsky512", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); ogreSceneManager->setSkyBox(true, "sky/null_plainsky512"); @@ -103,8 +103,11 @@ namespace RNR this->render_time += ogreRoot->getTimer()->getMilliseconds() / 1000.0; ogreRoot->getTimer()->reset(); - ogreCamera->getParentSceneNode()->setPosition(world->getWorkspace()->getBoundingBox().getCorner(Ogre::AxisAlignedBox::FAR_LEFT_TOP)*2); - ogreCamera->getParentSceneNode()->lookAt(world->getWorkspace()->getBoundingBox().getCenter(), Ogre::Node::TS_WORLD, Ogre::Vector3::NEGATIVE_UNIT_Z); + if(!world->getWorkspace()->getBoundingBox().isInfinite()) + { + ogreCamera->getParentSceneNode()->setPosition(world->getWorkspace()->getBoundingBox().getCorner(Ogre::AxisAlignedBox::CornerEnum::NEAR_LEFT_TOP)); + ogreCamera->getParentSceneNode()->lookAt(world->getWorkspace()->getBoundingBox().getCenter(), Ogre::Node::TS_WORLD); + } ogreRoot->renderOneFrame(this->delta); } diff --git a/Projects/Client/Studio/Header/MainWindow.hpp b/Projects/Client/Studio/Header/MainWindow.hpp index e118989..455e03c 100644 --- a/Projects/Client/Studio/Header/MainWindow.hpp +++ b/Projects/Client/Studio/Header/MainWindow.hpp @@ -32,7 +32,10 @@ class MainWindow : public QMainWindow void createToolbar(); void updateTree(RNR::Instance* root_instance); + public slots: + void loadDatamodel(); protected: + void widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instance); void recurseTreeAddInstance(QTreeWidgetItem* parent, RNR::Instance* instance); void closeEvent(QCloseEvent* event); void resizeEvent(QResizeEvent* event); diff --git a/Projects/Client/Studio/Source/MainWindow.cpp b/Projects/Client/Studio/Source/MainWindow.cpp index 06d6920..8a3b115 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -1,4 +1,6 @@ #include +#include +#include MainWindow::MainWindow() { @@ -37,11 +39,26 @@ MainWindow::MainWindow() setCentralWidget(content_widget); } +void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instance) +{ + QString icon_path; + icon_path = "content/textures/studio/icons/"; + icon_path += instance->getClassName(); + icon_path += ".png"; + QIcon icon; + if(QFile::exists(icon_path)) + icon = QIcon(icon_path); + else + icon = QIcon("content/textures/studio/icons/Instance.png"); + item->setIcon(0, icon); +} + void MainWindow::recurseTreeAddInstance(QTreeWidgetItem* parent, RNR::Instance* instance) { for(auto& child : *instance->getChildren()) { QTreeWidgetItem* instance_w = new QTreeWidgetItem(); + widgetItemPrepare(instance_w, child); instance_w->setText(0, QString(child->getName().c_str())); instance_w->setData(0, Qt::UserRole, QVariant::fromValue(child)); recurseTreeAddInstance(instance_w, child); @@ -57,14 +74,21 @@ void MainWindow::updateTree(RNR::Instance* root_instance) parent->setData(0, Qt::UserRole, QVariant::fromValue(child)); parent->setText(0, QString(child->getName().c_str())); + widgetItemPrepare(parent, child); recurseTreeAddInstance(parent, child); explorer->addTopLevelItem(parent); } } +void MainWindow::loadDatamodel() +{ + this->ogreWidget->world->load(QFileDialog::getOpenFileName(this, tr("Open RBXL"), tr(""), tr("RBXLs (*.rbxl)")).toLocal8Bit().data()); +} + void MainWindow::createToolbar() { QMenu* file_menu = menubar->addMenu("File"); + QAction* load_action = file_menu->addAction("Load", this, SLOT(loadDatamodel())); QMenu* help_menu = menubar->addMenu("Help"); help_menu->addAction("About..."); } diff --git a/Projects/Engine/CMakeLists.txt b/Projects/Engine/CMakeLists.txt index 749980d..11b8d28 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -1,17 +1,18 @@ add_library(Engine STATIC Header/Helpers/Name.hpp Header/Helpers/Strings.hpp + Header/Helpers/XML.hpp Header/App/GUI/GuiBase3d.hpp Header/App/GUI/InstanceAdornment.hpp Header/App/GUI/SelectionBox.hpp Header/App/Humanoid/Humanoid.hpp Header/App/V8/DataModel/Camera.hpp Header/App/V8/DataModel/ForceField.hpp - Header/App/V8/DataModel/BasePart.hpp + Header/App/V8/DataModel/PartInstance.hpp Header/App/V8/DataModel/Workspace.hpp Header/App/V8/Tree/Instance.hpp Header/App/V8/Tree/PVInstance.hpp - Header/App/V8/Tree/Model.hpp + Header/App/V8/Tree/ModelInstance.hpp Header/App/V8/World/World.hpp Header/App/CoordinateFrame.hpp Header/Network/GUID.hpp @@ -19,35 +20,39 @@ add_library(Engine STATIC Source/Helpers/Name.cpp Source/Helpers/Strings.cpp + Source/Helpers/XML.cpp Source/App/GUI/GuiBase3d.cpp Source/App/GUI/InstanceAdornment.cpp Source/App/GUI/SelectionBox.cpp Source/App/Humanoid/Humanoid.cpp Source/App/V8/DataModel/Camera.cpp Source/App/V8/DataModel/ForceField.cpp - Source/App/V8/DataModel/BasePart.cpp + Source/App/V8/DataModel/PartInstance.cpp Source/App/V8/DataModel/Workspace.cpp Source/App/V8/Tree/Instance.cpp Source/App/V8/Tree/PVInstance.cpp - Source/App/V8/Tree/Model.cpp + Source/App/V8/Tree/ModelInstance.cpp Source/App/CoordinateFrame.cpp Source/App/V8/World/World.cpp Source/Network/GUID.cpp Source/Rendering/Adorn.cpp ) +find_package(pugixml REQUIRED) + target_include_directories(Engine PUBLIC ${BOOST_INCLUDE_DIRS} Header/) -target_link_libraries(Engine PUBLIC ${BOOST_LIBRARIES} OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM) +target_link_libraries(Engine PUBLIC ${BOOST_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM) if(WIN32 OR MINGW) file(COPY ${CMAKE_SOURCE_DIR}/Content/win32_plugins.cfg DESTINATION ${CMAKE_BINARY_DIR}) file(RENAME ${CMAKE_BINARY_DIR}/win32_plugins.cfg ${CMAKE_BINARY_DIR}/plugins.cfg) + file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins) elseif(UNIX) file(COPY ${CMAKE_SOURCE_DIR}/Content/linux_plugins.cfg DESTINATION ${CMAKE_BINARY_DIR}) file(RENAME ${CMAKE_BINARY_DIR}/linux_plugins.cfg ${CMAKE_BINARY_DIR}/plugins.cfg) + file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins) endif() file(COPY ${CMAKE_SOURCE_DIR}/Content/RNR/ DESTINATION ${CMAKE_BINARY_DIR}/content) file(COPY ${OGRE_MEDIA_DIR}/Main/ DESTINATION ${CMAKE_BINARY_DIR}/shaders) -file(COPY ${OGRE_MEDIA_DIR}/RTShaderLib/ DESTINATION ${CMAKE_BINARY_DIR}/shaders) -file(COPY ${OGRE_PLUGIN_DIR}/ DESTINATION ${CMAKE_BINARY_DIR}/plugins) \ No newline at end of file +file(COPY ${OGRE_MEDIA_DIR}/RTShaderLib/ DESTINATION ${CMAKE_BINARY_DIR}/shaders) \ No newline at end of file diff --git a/Projects/Engine/Header/App/GUI/GuiBase3d.hpp b/Projects/Engine/Header/App/GUI/GuiBase3d.hpp index 1d47f0f..4628204 100644 --- a/Projects/Engine/Header/App/GUI/GuiBase3d.hpp +++ b/Projects/Engine/Header/App/GUI/GuiBase3d.hpp @@ -21,5 +21,6 @@ namespace RNR Ogre::Vector3 getColor() { return m_color; } void setTransparency(float transparency) { m_transparency = transparency; } float getTransparency() { return m_transparency; } + virtual std::string getClassName() { return "GuiBase3d"; } }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/GUI/InstanceAdornment.hpp b/Projects/Engine/Header/App/GUI/InstanceAdornment.hpp index 243ade6..0d7104b 100644 --- a/Projects/Engine/Header/App/GUI/InstanceAdornment.hpp +++ b/Projects/Engine/Header/App/GUI/InstanceAdornment.hpp @@ -13,5 +13,6 @@ namespace RNR InstanceAdornment(); void setAdornee(Instance* adornee) { setAdorneeEvent(adornee); m_adornee = adornee; } Instance* getAdornee() { return m_adornee; } + virtual std::string getClassName() { return "InstanceAdornment"; } }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/GUI/SelectionBox.hpp b/Projects/Engine/Header/App/GUI/SelectionBox.hpp index 17c1835..3136ce4 100644 --- a/Projects/Engine/Header/App/GUI/SelectionBox.hpp +++ b/Projects/Engine/Header/App/GUI/SelectionBox.hpp @@ -10,5 +10,6 @@ namespace RNR public: SelectionBox(); ~SelectionBox(); + virtual std::string getClassName() { return "SelectionBox"; } }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/ForceField.hpp b/Projects/Engine/Header/App/V8/DataModel/ForceField.hpp index 45237bb..353d491 100644 --- a/Projects/Engine/Header/App/V8/DataModel/ForceField.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/ForceField.hpp @@ -14,5 +14,6 @@ namespace RNR ~ForceField(); void renderForceField(boost::shared_ptr* descendant, RNR::Adorn* adorn, int cycle); + virtual std::string getClassName() { return "ForceField"; } }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/BasePart.hpp b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp similarity index 78% rename from Projects/Engine/Header/App/V8/DataModel/BasePart.hpp rename to Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp index 107bdcf..7960332 100644 --- a/Projects/Engine/Header/App/V8/DataModel/BasePart.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp @@ -6,8 +6,9 @@ namespace RNR { - class BasePart : public PVInstance, public Ogre::Renderable + class PartInstance : public PVInstance, public Ogre::Renderable { + protected: Ogre::MaterialPtr m_material; Ogre::Matrix4 m_matrix; Ogre::Vector3 m_position; @@ -15,11 +16,13 @@ namespace RNR Ogre::Vector3 m_size; Ogre::Vector4 m_color; static Ogre::MeshPtr m_partMesh; + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); public: - BasePart(); + PartInstance(); void updateMatrix(); + virtual std::string getClassName() { return "PartInstance"; } 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/DataModel/Workspace.hpp b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp index f290049..957c5e5 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -10,17 +10,19 @@ namespace RNR { - class Workspace : public Model + class Workspace : public ModelInstance { public: Workspace(); + virtual std::string getClassName() { return "Workspace"; } virtual void onChildAdded(RNR::Instance* childAdded); virtual void onChildRemoved(RNR::Instance* childRemoved); Camera* getCurrentCamera() const; void setCurrentCamera(Camera *value); private: + bool m_instancingEnabled; std::vector m_objects; Ogre::InstanceManager* m_instMan; Ogre::SceneNode* m_worldspawn; diff --git a/Projects/Engine/Header/App/V8/Tree/Instance.hpp b/Projects/Engine/Header/App/V8/Tree/Instance.hpp index 0e287f3..5d909e9 100644 --- a/Projects/Engine/Header/App/V8/Tree/Instance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/Instance.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace RNR { @@ -16,6 +17,7 @@ namespace RNR { protected: static World* world; + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop) {}; private: @@ -30,6 +32,8 @@ namespace RNR Instance(); ~Instance(); + void deserializeXmlProperty(pugi::xml_node prop); + bool contains(RNR::Instance* child); bool isAncestorOf(RNR::Instance* instance); @@ -44,6 +48,7 @@ namespace RNR RNR::Instance* getParent() { return this->m_parent; }; std::string getName() { return this->m_name; }; + virtual std::string getClassName() { return "Instance"; } void setParent(RNR::Instance* newParent); void setName(std::string name); diff --git a/Projects/Engine/Header/App/V8/Tree/Model.hpp b/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp similarity index 70% rename from Projects/Engine/Header/App/V8/Tree/Model.hpp rename to Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp index 81ac461..1bc14ad 100644 --- a/Projects/Engine/Header/App/V8/Tree/Model.hpp +++ b/Projects/Engine/Header/App/V8/Tree/ModelInstance.hpp @@ -3,13 +3,14 @@ namespace RNR { - class Model : public PVInstance + class ModelInstance : public PVInstance { public: - Model(); + ModelInstance(); virtual void build(); Ogre::AxisAlignedBox getBoundingBox() { return m_boundingbox; } + virtual std::string getClassName() { return "Model"; } private: Ogre::AxisAlignedBox m_boundingbox; diff --git a/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp b/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp index aaaccb4..da833f5 100644 --- a/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/PVInstance.hpp @@ -8,11 +8,13 @@ namespace RNR { protected: CoordinateFrame m_cframe; + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); public: PVInstance(); CoordinateFrame& getCFrame() { return m_cframe; }; void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; }; + virtual std::string getClassName() { return "PVInstance"; } Ogre::Vector3 getPosition() { return m_cframe.getPosition(); } Ogre::Matrix3 getRotation() { return m_cframe.getRotation(); } diff --git a/Projects/Engine/Header/App/V8/World/World.hpp b/Projects/Engine/Header/App/V8/World/World.hpp index 80cdf41..28d9652 100644 --- a/Projects/Engine/Header/App/V8/World/World.hpp +++ b/Projects/Engine/Header/App/V8/World/World.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace RNR { @@ -14,10 +15,13 @@ namespace RNR Ogre::Root* m_ogreRoot; Ogre::SceneManager* m_ogreSceneManager; + void xmlAddItem(pugi::xml_node node, Instance* parent); public: World(Ogre::Root* ogre, Ogre::SceneManager* ogreScene); ~World(); + void load(char* path); + void preStep(); double step(float timestep); void update(); diff --git a/Projects/Engine/Header/Helpers/XML.hpp b/Projects/Engine/Header/Helpers/XML.hpp new file mode 100644 index 0000000..3ac0607 --- /dev/null +++ b/Projects/Engine/Header/Helpers/XML.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +namespace RNR +{ + class XML + { + public: + static Ogre::Vector3 getVector3(pugi::xml_node node); + static CoordinateFrame getCFrame(pugi::xml_node node); + }; +} \ No newline at end of file diff --git a/Projects/Engine/Source/App/GUI/SelectionBox.cpp b/Projects/Engine/Source/App/GUI/SelectionBox.cpp index 7ab366d..4fbee5b 100644 --- a/Projects/Engine/Source/App/GUI/SelectionBox.cpp +++ b/Projects/Engine/Source/App/GUI/SelectionBox.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include namespace RNR @@ -11,14 +11,14 @@ namespace RNR Instance* old_adornee = getAdornee(); if(instance) { - BasePart* adornee_basepart = dynamic_cast(instance); + PartInstance* adornee_basepart = dynamic_cast(instance); if(adornee_basepart) { getNode()->setScale(adornee_basepart->getSize()); getNode()->setPosition(adornee_basepart->getPosition()); getNode()->setVisible(true); } - Model* adornee_model = dynamic_cast(instance); + ModelInstance* adornee_model = dynamic_cast(instance); if(adornee_model) { getNode()->setScale(adornee_model->getBoundingBox().getSize()); diff --git a/Projects/Engine/Source/App/V8/DataModel/BasePart.cpp b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp similarity index 62% rename from Projects/Engine/Source/App/V8/DataModel/BasePart.cpp rename to Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp index 0dc40c6..acec41b 100644 --- a/Projects/Engine/Source/App/V8/DataModel/BasePart.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp @@ -1,11 +1,12 @@ -#include +#include #include +#include namespace RNR { - Ogre::MeshPtr BasePart::m_partMesh = 0; + Ogre::MeshPtr PartInstance::m_partMesh = 0; - BasePart::BasePart() : m_matrix(), PVInstance(), Ogre::Renderable(), m_size(2.f, STUD_HEIGHT, 4.f) + PartInstance::PartInstance() : m_matrix(), PVInstance(), Ogre::Renderable(), m_size(2.f, STUD_HEIGHT, 4.f) { setName("Part"); @@ -19,18 +20,18 @@ namespace RNR m_material = m_partMesh->getSubMesh(0)->getMaterial(); } - void BasePart::updateMatrix() + void PartInstance::updateMatrix() { m_matrix = m_cframe.getMatrix(); m_position = m_cframe.getPosition(); } - const Ogre::MaterialPtr& BasePart::getMaterial() const + const Ogre::MaterialPtr& PartInstance::getMaterial() const { return m_material; } - void BasePart::getRenderOperation(Ogre::RenderOperation& op) + void PartInstance::getRenderOperation(Ogre::RenderOperation& op) { Ogre::SubMesh* submesh = m_partMesh->getSubMesh(0); if(submesh) @@ -49,19 +50,29 @@ namespace RNR printf("BasePart::getRenderOperation: couldnt get submesh\n"); } - Ogre::Real BasePart::getSquaredViewDepth(const Ogre::Camera* cam) const + Ogre::Real PartInstance::getSquaredViewDepth(const Ogre::Camera* cam) const { Ogre::Vector3 diff = m_position - cam->getDerivedPosition(); return diff.squaredLength(); } - const Ogre::LightList& BasePart::getLights() const + const Ogre::LightList& PartInstance::getLights() const { return m_nearbyLights; } - void BasePart::getWorldTransforms(Ogre::Matrix4* xform) const + 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")) + { + setSize(XML::getVector3(node)); + } + else + PVInstance::deserializeProperty(prop_name, node); + } } \ 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 1009dd3..5c4cd6b 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -1,41 +1,45 @@ #include #include -#include +#include #include namespace RNR { - Workspace::Workspace() : Model() + Workspace::Workspace() : ModelInstance() { + m_instancingEnabled = true; setName("Workspace"); m_instMan = world->getOgreSceneManager()->createInstanceManager("workspacePartInstanceManager", "fonts/Cube.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::InstancingTechnique::HWInstancingBasic, 255); m_instMan->setNumCustomParams(2); - m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode(); + m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode(); } void Workspace::onChildAdded(Instance* childAdded) { - BasePart* child_part = (BasePart*)childAdded; - Ogre::InstancedEntity* child_ent = (Ogre::InstancedEntity*)childAdded->getObject(); - if(!child_ent) + PartInstance* child_part = dynamic_cast(childAdded); + if(child_part) { - child_ent = m_instMan->createInstancedEntity("materials/partinstanced"); - assert(child_ent != NULL); - childAdded->setObject(child_ent); - m_objects.push_back(child_ent); + Ogre::InstancedEntity* child_ent = (Ogre::InstancedEntity*)childAdded->getObject(); + if(!child_ent) + { + child_ent = m_instMan->createInstancedEntity("materials/partinstanced"); + assert(child_ent != NULL); + childAdded->setObject(child_ent); + m_objects.push_back(child_ent); + } + child_ent->setPosition(child_part->getCFrame().getPosition()); + child_ent->setOrientation(Ogre::Quaternion(child_part->getCFrame().getRotation())); + Ogre::Vector3 size = child_part->getSize(); + child_ent->setScale(size); + child_ent->setCustomParam(0, Ogre::Vector4( + size.x, + size.y, + size.z, + 0.0f + )); + child_ent->setCustomParam(1, child_part->getColor()); + child_ent->setCastShadows(true); } - child_ent->setPosition(child_part->getCFrame().getPosition()); - child_ent->setOrientation(Ogre::Quaternion(child_part->getCFrame().getRotation())); - Ogre::Vector3 size = child_part->getSize(); - child_ent->setScale(size); - child_ent->setCustomParam(0, Ogre::Vector4( - size.x, - size.y, - size.z, - 0.0f - )); - child_ent->setCustomParam(1, child_part->getColor()); - child_ent->setCastShadows(true); } void Workspace::onChildRemoved(Instance* childRemoved) @@ -43,32 +47,19 @@ namespace RNR Ogre::InstancedEntity* child_ent = (Ogre::InstancedEntity*)childRemoved->getObject(); if(child_ent) { - BasePart* child_part = (BasePart*)childRemoved; - child_ent->_getOwner()->removeInstancedEntity(child_ent); - child_part->setObject(NULL); - - auto child_it = std::find(m_objects.begin(), m_objects.end(), child_ent); - if (child_it != m_objects.end()) + PartInstance* child_part = dynamic_cast(childRemoved); + if(child_part) { - m_objects.erase(child_it); - } + child_ent->_getOwner()->removeInstancedEntity(child_ent); + child_part->setObject(NULL); + + auto child_it = std::find(m_objects.begin(), m_objects.end(), child_ent); + if (child_it != m_objects.end()) + { + m_objects.erase(child_it); + } delete child_ent; } } - - Camera* Workspace::getCurrentCamera() const - { - return currentCamera.get(); - } - - void Workspace::setCurrentCamera(Camera *newCamera) - { - if (newCamera != currentCamera.get()) - { - currentCamera = boost::shared_ptr(newCamera); - - // TODO: raise propertyChanged and currentCameraChangedSignal - } - } } \ 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 ccac0dd..c07d7f5 100644 --- a/Projects/Engine/Source/App/V8/Tree/Instance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/Instance.cpp @@ -17,6 +17,15 @@ namespace RNR setParent(NULL); } + void Instance::deserializeXmlProperty(pugi::xml_node prop) + { + pugi::xml_attribute prop_name = prop.attribute("name"); + if(prop_name.as_string() == std::string("Name")) + setName(prop.text().as_string()); + else + deserializeProperty((char*)prop_name.as_string(), prop); + } + bool Instance::contains(Instance* child) { auto child_it = std::find(m_children.begin(), m_children.end(), child); diff --git a/Projects/Engine/Source/App/V8/Tree/Model.cpp b/Projects/Engine/Source/App/V8/Tree/Model.cpp deleted file mode 100644 index f1e8526..0000000 --- a/Projects/Engine/Source/App/V8/Tree/Model.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include - -namespace RNR -{ - Model::Model() : PVInstance() - { - - } - - void Model::build() - { - m_boundingbox.setNull(); - for(auto& child : *getChildren()) - childAddBoundingBox(child); - } - - void Model::childAddBoundingBox(Instance* child) - { - for(auto& child2 : *child->getChildren()) - childAddBoundingBox(child2); - BasePart* child_pv = (BasePart*)child; - Ogre::Vector3 size = child_pv->getSize() / 2.0; - m_boundingbox.merge(child_pv->getPosition() + size); - m_boundingbox.merge(child_pv->getPosition() - size); - } -} \ 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 new file mode 100644 index 0000000..4eb6253 --- /dev/null +++ b/Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp @@ -0,0 +1,30 @@ +#include +#include + +namespace RNR +{ + ModelInstance::ModelInstance() : PVInstance() + { + + } + + void ModelInstance::build() + { + m_boundingbox.setNull(); + for(auto& child : *getChildren()) + childAddBoundingBox(child); + } + + void ModelInstance::childAddBoundingBox(Instance* child) + { + for(auto& child2 : *child->getChildren()) + childAddBoundingBox(child2); + PartInstance* child_pv = dynamic_cast(child); + if(child_pv) + { + Ogre::Vector3 size = child_pv->getSize() / 2.0; + m_boundingbox.merge(child_pv->getPosition() + size); + m_boundingbox.merge(child_pv->getPosition() - size); + } + } +} \ 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 f4cac8e..f9e5e45 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 namespace RNR { @@ -6,4 +7,12 @@ namespace RNR { } + + void PVInstance::deserializeProperty(char* prop_name, pugi::xml_node node) + { + if(prop_name == std::string("CFrame")) + { + setCFrame(XML::getCFrame(node)); + } + } } \ 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 3b51b9d..b7e69d0 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 { @@ -14,27 +15,6 @@ namespace RNR m_datamodel->setName("DataModel"); m_workspace = new Workspace(); m_workspace->setParent(m_datamodel); - - Instance* test = new Instance(); - BasePart* test2 = new BasePart(); - SelectionBox* test3 = new SelectionBox(); - test->setParent(m_datamodel); - test2->setSize(Ogre::Vector3(64,STUD_HEIGHT,64)); - test2->setName("Baseplate"); - test2->setParent(m_workspace); - - for(int i = 1; i < 36; i++) - { - test2 = new BasePart(); - test2->getCFrame().setPosition(Ogre::Vector3(i*2,i*STUD_HEIGHT,i*2)); - test2->setSize(Ogre::Vector3(4,STUD_HEIGHT,4)); - test2->setParent(m_workspace); - } - - m_workspace->build(); - - test3->setAdornee(m_workspace); - test3->setParent(m_workspace); } World::~World() @@ -42,6 +22,67 @@ namespace RNR // } + void World::xmlAddItem(pugi::xml_node node, Instance* parent) + { + bool skip = false; + Instance* instance; + pugi::xml_attribute class_attr = node.attribute("class"); + printf("World::xmlAddItem: adding class %s\n", class_attr.as_string()); + + if(class_attr.as_string() == std::string("Part")) + { + instance = new PartInstance(); + } + else if(class_attr.as_string() == std::string("Workspace")) + { + instance = m_workspace; + } + else if(class_attr.as_string() == std::string("Model")) // FIXME: Workspace has onChildAdded but not onDescendantAdded so adding parts to models wont let them render. Eventually this must be fixed + { + instance = parent; + skip = true; + } + else + { + printf("World::xmlAddItem: adding unknown class\n"); + instance = new Instance(); + } + + if(!skip) + { + pugi::xml_node props = node.child("Properties"); + for(pugi::xml_node prop : props.children()) + instance->deserializeXmlProperty(prop); + 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) + { + pugi::xml_document rbxl_doc; + pugi::xml_parse_result result = rbxl_doc.load_file(path); + if(result) + { + printf("World::load: XML parsed without errors\n"); + + pugi::xml_node root = rbxl_doc.child("roblox"); + for(pugi::xml_node item = root.child("Item"); item; item = item.next_sibling("Item")) + { + xmlAddItem(item, m_datamodel); + } + } + else + { + printf("World::load: XML parsed with errors, description '%s', offset %i\n", result.description(), result.offset); + } + m_workspace->build(); + } + void World::preStep() { // diff --git a/Projects/Engine/Source/Helpers/XML.cpp b/Projects/Engine/Source/Helpers/XML.cpp new file mode 100644 index 0000000..cde148b --- /dev/null +++ b/Projects/Engine/Source/Helpers/XML.cpp @@ -0,0 +1,36 @@ +#include + +namespace RNR +{ + Ogre::Vector3 XML::getVector3(pugi::xml_node node) + { + return Ogre::Vector3( + node.child("X").text().as_float(), + node.child("Y").text().as_float(), + node.child("Z").text().as_float() + ); + } + + CoordinateFrame XML::getCFrame(pugi::xml_node node) + { + CoordinateFrame cframe; + + cframe.setPosition( + Ogre::Vector3( + node.child("X").text().as_float(), + node.child("Y").text().as_float(), + node.child("Z").text().as_float() + ) + ); + + cframe.setRotation( + Ogre::Matrix3( + node.child("R00").text().as_float(), node.child("R01").text().as_float(), node.child("R02").text().as_float(), + node.child("R10").text().as_float(), node.child("R11").text().as_float(), node.child("R12").text().as_float(), + node.child("R20").text().as_float(), node.child("R21").text().as_float(), node.child("R22").text().as_float() + ) + ); + + return cframe; + } +} \ No newline at end of file