From d2f94e915b14e9ec70c0db1d3d3e5db93ede40a4 Mon Sep 17 00:00:00 2001 From: floralrainfall Date: Sat, 15 Jul 2023 20:47:37 -0400 Subject: [PATCH] DataModel loading --- .../RNR/textures/studio/icons/Instance.png | Bin 0 -> 836 bytes .../textures/studio/icons/PartInstance.png | Bin 0 -> 1244 bytes .../textures/studio/icons/SelectionBox.png | Bin 0 -> 1077 bytes .../RNR/textures/studio/icons/Workspace.png | Bin 0 -> 1169 bytes Content/win32_plugins.cfg | 2 +- Projects/Client/Common/Source/OgreWidget.cpp | 13 +-- Projects/Client/Studio/Header/MainWindow.hpp | 3 + Projects/Client/Studio/Source/MainWindow.cpp | 24 +++++ Projects/Engine/CMakeLists.txt | 19 ++-- Projects/Engine/Header/App/GUI/GuiBase3d.hpp | 1 + .../Header/App/GUI/InstanceAdornment.hpp | 1 + .../Engine/Header/App/GUI/SelectionBox.hpp | 1 + .../Header/App/V8/DataModel/ForceField.hpp | 1 + .../{BasePart.hpp => PartInstance.hpp} | 7 +- .../Header/App/V8/DataModel/Workspace.hpp | 6 +- .../Engine/Header/App/V8/Tree/Instance.hpp | 5 ++ .../V8/Tree/{Model.hpp => ModelInstance.hpp} | 5 +- .../Engine/Header/App/V8/Tree/PVInstance.hpp | 2 + Projects/Engine/Header/App/V8/World/World.hpp | 4 + Projects/Engine/Header/Helpers/XML.hpp | 15 ++++ .../Engine/Source/App/GUI/SelectionBox.cpp | 6 +- .../{BasePart.cpp => PartInstance.cpp} | 29 ++++-- .../Source/App/V8/DataModel/Workspace.cpp | 69 +++++++------- .../Engine/Source/App/V8/Tree/Instance.cpp | 9 ++ Projects/Engine/Source/App/V8/Tree/Model.cpp | 27 ------ .../Source/App/V8/Tree/ModelInstance.cpp | 30 +++++++ .../Engine/Source/App/V8/Tree/PVInstance.cpp | 9 ++ Projects/Engine/Source/App/V8/World/World.cpp | 85 +++++++++++++----- Projects/Engine/Source/Helpers/XML.cpp | 36 ++++++++ 29 files changed, 298 insertions(+), 111 deletions(-) create mode 100644 Content/RNR/textures/studio/icons/Instance.png create mode 100644 Content/RNR/textures/studio/icons/PartInstance.png create mode 100644 Content/RNR/textures/studio/icons/SelectionBox.png create mode 100644 Content/RNR/textures/studio/icons/Workspace.png rename Projects/Engine/Header/App/V8/DataModel/{BasePart.hpp => PartInstance.hpp} (78%) rename Projects/Engine/Header/App/V8/Tree/{Model.hpp => ModelInstance.hpp} (70%) create mode 100644 Projects/Engine/Header/Helpers/XML.hpp rename Projects/Engine/Source/App/V8/DataModel/{BasePart.cpp => PartInstance.cpp} (62%) delete mode 100644 Projects/Engine/Source/App/V8/Tree/Model.cpp create mode 100644 Projects/Engine/Source/App/V8/Tree/ModelInstance.cpp create mode 100644 Projects/Engine/Source/Helpers/XML.cpp diff --git a/Content/RNR/textures/studio/icons/Instance.png b/Content/RNR/textures/studio/icons/Instance.png new file mode 100644 index 0000000000000000000000000000000000000000..07e204deb5e3b100c70b1d0d0e864e41cf8267f7 GIT binary patch literal 836 zcmV-K1H1f*P)EX>4Tx04R}tkv&MmKpe$iQ>7yH1MMKf)s6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7vsG4P@ z6LB${TNMMZ2%sNBh+U4&e3JS*_Gq>z@3D!MwJz%ypV$NMI35NI`^*8p^1^LWEY06ccIMk9+t>9e;{kGP%lN zIZc;D~bidg4$2bt!1)6o+{yw(t<_X|`2ClTWzuEwzpQP8@ zTKEVU*aj}H+nT%wT$gU400006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=LZiLFD+wyoG}0Z02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00A6HL_t(I%hi)HP6II%M4z(>G%1jRqDT>(gpPvJC*TZ} z6kLT9a2JF)1`;#`mV~uuD7?F5fru6?S+-@r`J=H7|GtIo#q8qVG&Q6(qz$AEK?yq( zBv1mI$D8w>8x7>t@IIQdsSa3IGv3B?UMCCc$C9C~ormBfCUUtZMAdnjD3g-r; zge`)NF}A@FtN}6W3aGb!_9a9S)WU_p%0)=RQlCML@#wpQKpPmPvP78*EX>4Tx04R}tkv&MmKpe$iQ>7yH1MMKf)s6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7vsG4P@ z6LB${TNMMZ2%sNBh+U4&e3JS*_Gq>z@3D!MwJz%ypV$NMI35NI`^*8p^1^LWEY06ccIMk9+t>9e;{kGP%lN zIZc;D~bidg4$2bt!1)6o+{yw(t<_X|`2ClTWzuEwzpQP8@ zTKEVU*aj}H+nT%wT$gU400006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=LZiLFDHYkbuRz_02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00Oj0L_t(I%e9liOCxs_$3J5xsS_itCM3k9hR|8pg^2dj zEz-ZBrG(N$S?J#&^uBoW)PJD=K^0^{EWH#&icl~lqR`4(trL?OVq!AsB++#8o4j6h z$+^&Xd6)P3@E%_t{9h#^&qU?^Mx*h) zh&+3m(|62Zf^eSy6)=S+#EAAGpw(#e;Ncq7RX**T~V!8pKot(e+vw>3Be!0 zOMptHG8~V`{}c*^Xti1mw^}VSnGE@S9^d!b-`^jW%jLJVTJ10W5e@-=Kgl#rn+}CS z)3$AMeSHl;B9Q>VbzMx;)Z6X$tNHnPXG%n-f!Dythlht8A0J~`7O7Njen#OQAWOjCz<>h63->2DZVp$eJ5YX@U z@jQ?7^K&AR2!%oc9r$u_aZv+ErBdAA-{UwAmSv%oqTlbo-$>Im>h(J5bec>igXekZ zK&#j5VVWiY(P$LYH1U0(TCGN=VHhZ-5D|hPU~O#;9e9`!1dlxo&}cMRU0o#{4%6%PP)ea`8X`h07DLx{ zrb?yK&+T@*<~R-~CnwX7uo4l@&dwMN26Ve!lu}O-lT0SDZJQtntWdMrd=UhJIz2r# zqtWOGjYebY^73-(;^KnQXoTl^7>0p};QKy+DwoSaI-P!Zbab?%6^q5sfCTVKJRbid znM^)UBoan8nmOWAc literal 0 HcmV?d00001 diff --git a/Content/RNR/textures/studio/icons/SelectionBox.png b/Content/RNR/textures/studio/icons/SelectionBox.png new file mode 100644 index 0000000000000000000000000000000000000000..34ff5a010145afa1ffc4d33ad681ae3571a826c6 GIT binary patch literal 1077 zcmV-51j_q~P)EX>4Tx04R}tkv&MmKpe$iQ>7yH1MMKf)s6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7vsG4P@ z6LB${TNMMZ2%sNBh+U4&e3JS*_Gq>z@3D!MwJz%ypV$NMI35NI`^*8p^1^LWEY06ccIMk9+t>9e;{kGP%lN zIZc;D~bidg4$2bt!1)6o+{yw(t<_X|`2ClTWzuEwzpQP8@ zTKEVU*aj}H+nT%wT$gU400006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=LZiLFDr^4IRpRz02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00Iq3L_t(I%cYagY75Q7x)Iz9?p%ok6c-|S0Q&|C;=;u|fPc}Ys0$UfYMdrQqb4!UWRl6uTo*AR#a0Vm zxNy$7-}%0K?l~9!bBSrkDm(ju6(9{bfCm^r1XO{Czy|QPSt&V2LHgHTJacGL4m zLYdgJxPIS~YUl=9df)5(QWnSo1)!u`WhahOqim%}zQ0#b8Xs0|+rF`ttW|cd16K~U zUeHd>ot8ieA;g#zlCG9?SEsO7-8~b0(g8ZfHsYYl$-?`+Yro-4YS{nGHe?XuqMah;O~WNu@XX# zr6kbRfv*#Q)alJEwmZi0f>pkG=J!noKmu5feD@f7f=tjuM1cnsg;jR4!u$D5C1;NA zbp8vy8m8-X^WW~AmCZ`AEvirJ1Op@rGxW#=y+3w-@MC26Tlf*fOy~J+U|}?gzI#D_ zdh+<-u2^C6y|e^G0jL0!f}xAhQ-RigQ=3uMyPEJfY};ND(>=~>{Y!vhh+#UTcjqKg v+>heT5b33)_sY~;>w+)_zI% literal 0 HcmV?d00001 diff --git a/Content/RNR/textures/studio/icons/Workspace.png b/Content/RNR/textures/studio/icons/Workspace.png new file mode 100644 index 0000000000000000000000000000000000000000..3cdc792edc6b3239942059f3bb5a67e1fbaf30b3 GIT binary patch literal 1169 zcmV;C1aA9@P)EX>4Tx04R}tkv&MmKpe$iQ>7yH1MMKf)s6A|?JWDYS_3;J6>}?mh0_0Yam~RI@7vsG4P@ z6LB${TNMMZ2%sNBh+U4&e3JS*_Gq>z@3D!MwJz%ypV$NMI35NI`^*8p^1^LWEY06ccIMk9+t>9e;{kGP%lN zIZc;D~bidg4$2bt!1)6o+{yw(t<_X|`2ClTWzuEwzpQP8@ zTKEVU*aj}H+nT%wT$gU400006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=LZiLFDYaZSSSDh02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00L=AL_t(I%Z-ywNK{c2$A9;}H*aR1&-u_nX-X3MScEMq z!lH7Sl7Uv+GNMgXo4`f;HVL*A+GNxsC}L{FmJv<1Fq5c=NmMjb)bV4+7-yW1_ihUv znM$g&JLmq-|NPIn=LmkYvkxr;*bR(DI?{RmVfq%aW}pxF(%yUWb$ankGeSu#^mtrq z!yS>1^lUj;lvNG@w}7jF1jr5@AeFPPm`R?~0bJgx6a80u z26O<;$hIa%FIJV%)%AJh@r{Zy0tv7-(xMfT+gP>gaaZiU20a7oa+SDKLTW}9m-n;S zVz@c6U<;HDfL$<8H+IGXdShoSpqye|2^Fk+f#w=6xl2H`QnlEl$BiF>qZIJ1&nGcy zA)PJ>oOf(}^E*@1Ei6xU;}nkoRIgV%L}vb&C?!{}#1UEn_kpjy5_p18szgxCS!7c? zNX=X>g_PzR#&hsf(QPeJnTjK|9H!^xlDp#G2OS8Z#2-Cdp@Gd^5n>)gkLp$OBPv{j z@XjjY!TXVpbY22uq15w;W@pNhR?2VTk(n3>yDLV*l1y03PowfC zI0E6zZZ5rAbq}fue?M7i08f9p1%UPot^0v4YBMHt=3#7+LsM&boD@RE)Uq)_QLIFx j(YySwwY9aK`rG?Y^mym*tZaddResourceLocation("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 8dd13eb..6243866 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -1,16 +1,17 @@ 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/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 @@ -18,34 +19,38 @@ 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/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 917ee30..b78c8d7 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp @@ -1,20 +1,22 @@ #pragma once #include -#include +#include #include #include 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); 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 d92923d..84e988b 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -1,40 +1,44 @@ #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) @@ -42,17 +46,20 @@ 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); - delete child_ent; + 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; + } } } } \ 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