From ad9376f7e04884251804c4ddd8139a63ec91d531 Mon Sep 17 00:00:00 2001 From: floralrainfall Date: Wed, 19 Jul 2023 07:23:26 -0400 Subject: [PATCH] readd instancing alongside static geometry --- Content/RNR/materials/partinstanced.material | 1 + Projects/Client/Common/Source/OgreWidget.cpp | 3 +- Projects/Client/Studio/Source/MainWindow.cpp | 20 +++- .../Client/Studio/Source/PropertyViewer.cpp | 13 +++ Projects/Engine/Header/App/BrickColor.hpp | 1 + Projects/Engine/Header/App/GUI/TopMenuBar.hpp | 13 ++- .../Header/App/Script/ReflectionProperty.hpp | 1 + .../Engine/Header/App/V8/DataModel/Light.hpp | 11 +++ .../Header/App/V8/DataModel/PartInstance.hpp | 2 + .../Header/App/V8/DataModel/Workspace.hpp | 16 +++- .../Engine/Header/App/V8/Tree/Instance.hpp | 6 ++ Projects/Engine/Header/App/V8/World/World.hpp | 1 + Projects/Engine/Source/App/BrickColor.cpp | 12 +++ Projects/Engine/Source/App/GUI/TopMenuBar.cpp | 41 ++++++-- .../Source/App/Script/ReflectionProperty.cpp | 3 + .../Engine/Source/App/V8/DataModel/Light.cpp | 41 +++++++- .../Source/App/V8/DataModel/PartInstance.cpp | 19 ++++ .../Source/App/V8/DataModel/Workspace.cpp | 94 ++++++++----------- .../Engine/Source/App/V8/Tree/Instance.cpp | 40 +++++++- Projects/Engine/Source/App/V8/World/World.cpp | 6 +- 20 files changed, 275 insertions(+), 69 deletions(-) diff --git a/Content/RNR/materials/partinstanced.material b/Content/RNR/materials/partinstanced.material index c74c162..7ec2dcb 100644 --- a/Content/RNR/materials/partinstanced.material +++ b/Content/RNR/materials/partinstanced.material @@ -16,6 +16,7 @@ material materials/partinstanced rtshader_system { + transform_stage instanced lighting_stage per_pixel } } diff --git a/Projects/Client/Common/Source/OgreWidget.cpp b/Projects/Client/Common/Source/OgreWidget.cpp index 680bf72..911fa75 100644 --- a/Projects/Client/Common/Source/OgreWidget.cpp +++ b/Projects/Client/Common/Source/OgreWidget.cpp @@ -59,9 +59,10 @@ namespace RNR ogreCamera = ogreSceneManager->createCamera("myCam"); ogreCamera->setNearClipDistance(0.1); // specific to this sample - ogreCamera->setFarClipDistance(5000.f); + ogreCamera->setFarClipDistance(1000.f); ogreCamera->setAutoAspectRatio(true); ogreCamera->setFOVy(Ogre::Degree(70.f)); + ogreCamera->setUseRenderingDistance(true); camNode->attachObject(ogreCamera); ogreViewport = ogreWindow->addViewport(ogreCamera); diff --git a/Projects/Client/Studio/Source/MainWindow.cpp b/Projects/Client/Studio/Source/MainWindow.cpp index 83aad9d..c92d1b0 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -1,7 +1,10 @@ #include #include #include +#include +#include #include +#include MainWindow::MainWindow() { @@ -130,7 +133,22 @@ void MainWindow::pause() void MainWindow::dbg_pointlight() { - + if(!ogreWidget->selectedInstance) + { + QMessageBox::about(this, "selectedInstance = NULL", "Please select an instance in the explorer"); + return; + } + + printf("MainWindow::dbg_pointlight: inserting Light\n"); + RNR::Light* dbg_light = new RNR::Light(); + dbg_light->setParent(ogreWidget->selectedInstance); + + double r = QInputDialog::getDouble(this, "Red", "Set red component [0.0-1.0]", 1.0, 0.0, 1.0, 2); + double g = QInputDialog::getDouble(this, "Blue", "Set blue component [0.0-1.0]", 1.0, 0.0, 1.0, 2); + double b = QInputDialog::getDouble(this, "Green", "Set green component [0.0-1.0]", 1.0, 0.0, 1.0, 2); + dbg_light->setColor(Ogre::Vector3(r,g,b)); + + updateTree(ogreWidget->world->getDatamodel()); } void MainWindow::closeEvent(QCloseEvent* event) diff --git a/Projects/Client/Studio/Source/PropertyViewer.cpp b/Projects/Client/Studio/Source/PropertyViewer.cpp index 2f09d6d..691da6a 100644 --- a/Projects/Client/Studio/Source/PropertyViewer.cpp +++ b/Projects/Client/Studio/Source/PropertyViewer.cpp @@ -3,6 +3,8 @@ #include #include +#include + PropertyViewer::PropertyViewer() : QWidget() { prop_table = new QTableWidget(); @@ -88,6 +90,17 @@ void PropertyViewer::view(RNR::Instance* instance) new_property_itemval->setData(Qt::DecorationRole, QPixmap::fromImage(image)); } break; + case RNR::PROPERTY_BRICKCOLOR: + { + int brickcolor = *(int*)property.rawGetter(); + Ogre::Vector3 color = RNR::BrickColor::color(brickcolor); + new_property_itemval->setBackground(QBrush(QColor( + (int)floorf(color.x * 255), + (int)floorf(color.y * 255), + (int)floorf(color.z * 255) + ))); + } + break; } prop_table->setItem(property_count, 0, new_property_item); diff --git a/Projects/Engine/Header/App/BrickColor.hpp b/Projects/Engine/Header/App/BrickColor.hpp index 2dfe81e..d7ae92b 100644 --- a/Projects/Engine/Header/App/BrickColor.hpp +++ b/Projects/Engine/Header/App/BrickColor.hpp @@ -18,6 +18,7 @@ namespace RNR BrickColor(int color_id, std::string name, Ogre::Vector3 color); static Ogre::Vector3 color(int brickcolor); static bool valid(int brickcolor); + static std::string name(int brickcolor); static Ogre::MaterialPtr material(int brickcolor); }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/GUI/TopMenuBar.hpp b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp index 8f3f10c..98f6360 100644 --- a/Projects/Engine/Header/App/GUI/TopMenuBar.hpp +++ b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp @@ -1,12 +1,23 @@ #pragma once #include +#include +#include +#include +#include +#include namespace RNR { + class World; + class TopMenuBar { + Ogre::TextAreaOverlayElement* m_debugText; + World* m_world; public: - TopMenuBar(); + TopMenuBar(World* world); + + void frame(); }; } \ 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 56d2231..1f5fbb9 100644 --- a/Projects/Engine/Header/App/Script/ReflectionProperty.hpp +++ b/Projects/Engine/Header/App/Script/ReflectionProperty.hpp @@ -41,6 +41,7 @@ namespace RNR PROPERTY_CFRAME, PROPERTY_INSTANCE, PROPERTY_FLOAT, + PROPERTY_BRICKCOLOR, }; class ReflectionProperty diff --git a/Projects/Engine/Header/App/V8/DataModel/Light.hpp b/Projects/Engine/Header/App/V8/DataModel/Light.hpp index f85bfb2..e4c591b 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Light.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Light.hpp @@ -12,5 +12,16 @@ namespace RNR bool m_shadows; public: Light(); + + virtual void setupLight(Ogre::Light* light); + virtual void onSetParent(RNR::Instance* newParent); + virtual std::string getClassName() { return std::string("Light"); } + + void setColor(Ogre::Vector3 color) { m_color = color; setupLight((Ogre::Light*)getObject()); } + Ogre::Vector3 getColor() { return m_color; } + void setEnabled(bool enabled) { m_enabled = enabled; setupLight((Ogre::Light*)getObject()); } + bool getEnabled() { return m_enabled; } + void setShadows(bool shadows) { m_shadows = shadows; setupLight((Ogre::Light*)getObject()); } + bool getShadows() { return m_shadows; } }; } \ 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 c88c466..9314c72 100644 --- a/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp @@ -28,6 +28,8 @@ namespace RNR Ogre::Vector3 getSize() { return m_size; } Ogre::Vector4 getColor() { return m_color; } + Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); } + void setBrickColor(int brickcolor) { m_brickColor = brickcolor; } int getBrickColor() { return m_brickColor; } }; diff --git a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp index bc19c8d..792e7ab 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp @@ -11,26 +11,38 @@ namespace RNR { class Camera; + enum WorkspaceBatchingMode + { + BATCH_INSTANCED, + BATCH_STATIC_GEOMETRY, + }; + class Workspace : public ModelInstance { + friend class TopMenuBar; public: Workspace(); virtual std::string getClassName() { return "Workspace"; } - virtual void onChildAdded(RNR::Instance* childAdded); - virtual void onChildRemoved(RNR::Instance* childRemoved); + virtual void onDescendantAdded(RNR::Instance* childAdded); + virtual void onDescendantRemoved(RNR::Instance* childRemoved); void buildGeom(); Camera* getCurrentCamera() const; void setCurrentCamera(Camera *value); + void setDirty() { m_geomDirty = true; } private: + enum WorkspaceBatchingMode m_batchMode; + virtual void addProperties(std::vector& properties); virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); + void buildGeomInstance(Instance* instance); bool m_geomDirty; Ogre::StaticGeometry* m_geom; + Ogre::InstanceManager* m_instanceManager; Ogre::SceneNode* m_worldspawn; Ogre::Entity* m_partEntity; diff --git a/Projects/Engine/Header/App/V8/Tree/Instance.hpp b/Projects/Engine/Header/App/V8/Tree/Instance.hpp index e1cb17f..23f10c6 100644 --- a/Projects/Engine/Header/App/V8/Tree/Instance.hpp +++ b/Projects/Engine/Header/App/V8/Tree/Instance.hpp @@ -30,6 +30,9 @@ namespace RNR RNR::Instance* m_parent; std::vector m_children; bool m_archivable; + + void descendantAddedChildren(Instance* p, Instance* c); + void descendantRemovedChildren(Instance* p, Instance* c); public: Instance(); @@ -69,6 +72,9 @@ namespace RNR int numChildren() { return this->m_children.size(); }; virtual void onChildAdded(RNR::Instance* childAdded); + virtual void onDescendantAdded(RNR::Instance* descendantAdded); // make sure this is called in any derived versions of this virtual void onChildRemoved(RNR::Instance* childRemoved); + virtual void onDescendantRemoved(RNR::Instance* descendantRemoved); // make sure this is called in any derived versions of this + virtual void onSetParent(RNR::Instance* newParent); }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/World/World.hpp b/Projects/Engine/Header/App/V8/World/World.hpp index 4c2da01..7595e06 100644 --- a/Projects/Engine/Header/App/V8/World/World.hpp +++ b/Projects/Engine/Header/App/V8/World/World.hpp @@ -18,6 +18,7 @@ namespace RNR struct WorldUndeserialized { Instance* instance; + Instance* parent; pugi::xml_node node; }; diff --git a/Projects/Engine/Source/App/BrickColor.cpp b/Projects/Engine/Source/App/BrickColor.cpp index 870422a..b8b3b4f 100644 --- a/Projects/Engine/Source/App/BrickColor.cpp +++ b/Projects/Engine/Source/App/BrickColor.cpp @@ -151,4 +151,16 @@ namespace RNR } return false; } + + std::string BrickColor::name(int brickcolor) + { + for(int i = 0; i < sizeof(brickcolors) / sizeof(BrickColor); i++) + { + if(brickcolors[i].color_id == brickcolor) + { + return brickcolors[i].color_name; + } + } + return brickcolors[0].color_name; + } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/GUI/TopMenuBar.cpp b/Projects/Engine/Source/App/GUI/TopMenuBar.cpp index daf8853..0a87dfc 100644 --- a/Projects/Engine/Source/App/GUI/TopMenuBar.cpp +++ b/Projects/Engine/Source/App/GUI/TopMenuBar.cpp @@ -1,14 +1,12 @@ #include -#include -#include -#include -#include -#include +#include namespace RNR { - TopMenuBar::TopMenuBar() + TopMenuBar::TopMenuBar(World* world) { + m_world = world; + Ogre::OverlayManager* overlayManager = Ogre::OverlayManager::getSingletonPtr(); Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Background", "General"); material->getTechnique(0)->getPass(0)->createTextureUnitState("placeholder.png"); @@ -33,12 +31,43 @@ namespace RNR textArea->setFontName("ComicSans"); textArea->setColour(Ogre::ColourValue(0.f,0.f,0.f)); + m_debugText = static_cast(overlayManager->createOverlayElement("TextArea", "DebugTextArea")); + m_debugText->setMetricsMode(Ogre::GMM_PIXELS); + m_debugText->setPosition(0, 300); + m_debugText->setDimensions(420, 500); + m_debugText->setCaption("Debug text!"); + m_debugText->setCharHeight(24); + m_debugText->setFontName("ComicSans"); + m_debugText->setColour(Ogre::ColourValue(0.5f,0.f,0.5f)); + + Ogre::Overlay* overlay = overlayManager->create("OverlayName"); overlay->add2D(panel); overlay->setZOrder(500); panel->addChild(textArea); + panel->addChild(m_debugText); + overlay->show(); } + + void TopMenuBar::frame() + { + Workspace* workspace = m_world->getWorkspace(); + + char debugtext[512]; + char render_debugtext[255]; + switch(workspace->m_batchMode) + { + case BATCH_INSTANCED: + snprintf(render_debugtext, 255, "using BATCH_INSTANCED"); + break; + case BATCH_STATIC_GEOMETRY: + snprintf(render_debugtext, 255, "using BATCH_STATIC_GEOMETRY\nGeom Regions: %i", workspace->m_geom->getRegions().size()); + break; + } + snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n",m_world->getLastDelta(),render_debugtext,m_world->getOgreSceneManager()); + m_debugText->setCaption(debugtext); + } } \ 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 77dfa92..6342ee6 100644 --- a/Projects/Engine/Source/App/Script/ReflectionProperty.cpp +++ b/Projects/Engine/Source/App/Script/ReflectionProperty.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,8 @@ namespace RNR cframe_rotation.z, cframe_rotation.w); } + case PROPERTY_BRICKCOLOR: + return std::string(BrickColor::name(*(int*)m_getter(m_object))); default: return std::string("???"); } diff --git a/Projects/Engine/Source/App/V8/DataModel/Light.cpp b/Projects/Engine/Source/App/V8/DataModel/Light.cpp index 49133ca..9d51261 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Light.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Light.cpp @@ -1,4 +1,6 @@ #include +#include +#include namespace RNR { @@ -7,6 +9,43 @@ namespace RNR m_brightness = 1.f; m_enabled = true; m_shadows = true; - m_color = Ogre::Vector3(1.f,1.f,1.f); + m_color = Ogre::Vector3(75.f/255.f,151.f/255.f,75.f/255.f); + + setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); + setObject(world->getOgreSceneManager()->createLight(Ogre::Light::LT_POINT)); + getNode()->attachObject(getObject()); + + Ogre::Light* light_object = (Ogre::Light*)getObject(); + } + + void Light::onSetParent(Instance* newParent) + { + Ogre::Light* light_object = (Ogre::Light*)getObject(); + + if(!newParent) + { + light_object->setVisible(false); + return; + } + + PartInstance* part = dynamic_cast(newParent); + if(!part) + { + light_object->setVisible(false); + return; + } + + getNode()->setPosition(part->getPosition()); + setupLight(light_object); + } + + void Light::setupLight(Ogre::Light* light) + { + light->setVisible(m_enabled); + light->setCastShadows(m_shadows); + light->setDiffuseColour(Ogre::ColourValue(m_color.x, m_color.y, m_color.z)); + //light->setAttenuation(100, 1.0, 0.045, 0.0075); + light->setRenderingDistance(500.f); + light->setShadowFarDistance(100); } } \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp index 8ef18f8..a971852 100644 --- a/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp @@ -10,6 +10,10 @@ namespace RNR m_color = Ogre::Vector4(0.63, 0.64, 0.63, 1.0); + setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); + setObject(world->getOgreSceneManager()->createEntity("fonts/Cube.mesh")); + getNode()->attachObject(getObject()); + updateMatrix(); } @@ -17,6 +21,16 @@ namespace RNR { m_matrix = m_cframe.getMatrix(); m_position = m_cframe.getPosition(); + + getNode()->setOrientation(Ogre::Quaternion(m_cframe.getRotation())); + getNode()->setPosition(m_position); + getNode()->setScale(m_size); + + Ogre::Entity* entity = (Ogre::Entity*)getObject(); + for(auto& subentity : entity->getSubEntities()) + { + subentity->getMaterial()->setManualCullingMode(Ogre::ManualCullingMode::MANUAL_CULL_BACK); + } } void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node) @@ -35,6 +49,7 @@ namespace RNR } else PVInstance::deserializeProperty(prop_name, node); + updateMatrix(); } void PartInstance::addProperties(std::vector& properties) @@ -44,6 +59,10 @@ namespace RNR 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); ) }, + { this, std::string("BrickColor"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_BRICKCOLOR, + REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_brickColor; ), + REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setBrickColor(*(int*)value); ) }, }; PVInstance::addProperties(properties); diff --git a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp index 8c76c52..ed31561 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -8,81 +8,67 @@ namespace RNR Workspace::Workspace() : ModelInstance() { setName("Workspace"); + m_batchMode = BATCH_STATIC_GEOMETRY; + m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode(); - m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom"); - m_geom->setCastShadows(true); - m_partEntity = world->getOgreSceneManager()->createEntity("fonts/Cube.mesh"); - m_partEntity->setCastShadows(true); - - for(int i = 0; i < m_partEntity->getNumSubEntities(); i++) + + switch(m_batchMode) { - Ogre::SubEntity* surface = m_partEntity->getSubEntity(i); - Ogre::TextureUnitState* texture = surface->getMaterial()->getTechnique(0)->getPass(0)->createTextureUnitState("textures/stud_top.png"); - - surface->getMaterial()->setShininess(1.0); + case BATCH_INSTANCED: + m_instanceManager = world->getOgreSceneManager()->createInstanceManager("workspaceInstanceManager", "fonts/Cube.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::InstancingTechnique::HWInstancingBasic, 255); + break; + case BATCH_STATIC_GEOMETRY: + m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom"); + m_geom->setRegionDimensions(Ogre::Vector3(255,255,255)); + m_geom->setCastShadows(true); + break; } } - void Workspace::onChildAdded(Instance* childAdded) + void Workspace::onDescendantAdded(Instance* childAdded) { - m_geomDirty = true; + PartInstance* part = dynamic_cast(childAdded); + if(part) + { + Ogre::SceneNode* child_node = childAdded->getNode(); + switch(m_batchMode) + { + case BATCH_INSTANCED: + { + Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity("materials/partinstanced"); + replica->setPosition(part->getPosition()); + replica->setOrientation(part->getCFrame().getRotation()); + replica->setScale(part->getSize()); + } + break; + case BATCH_STATIC_GEOMETRY: + m_geom->addEntity((Ogre::Entity*)childAdded->getObject(), + part->getPosition(), + part->getCFrame().getRotation(), + part->getSize()); + break; + } + child_node->setVisible(false); + m_geomDirty = true; + } } void Workspace::buildGeomInstance(Instance* instance) { - PartInstance* child_part = dynamic_cast(instance); - if(child_part) - { - Ogre::Vector3 part_size = child_part->getSize(); - for(int i = 0; i < m_partEntity->getNumSubEntities(); i++) - { - m_partEntity->setMaterial(BrickColor::material(child_part->getBrickColor())); - /* - Ogre::SubMesh* surface = m_partEntity->getMesh()->getSubMesh(i); - surface->setMaterial(); - 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); - else if(surf_name == "BottomMaterial") - uvs = Ogre::Vector2(-part_size.x, part_size.z); - else if(surf_name == "LeftMaterial") - uvs = Ogre::Vector2(part_size.y, part_size.z); - else if(surf_name == "RightMaterial") - uvs = Ogre::Vector2(-part_size.y, part_size.z); - else if(surf_name == "BackMaterial") - uvs = Ogre::Vector2(part_size.x, part_size.z); - else if(surf_name == "FrontMaterial") - uvs = Ogre::Vector2(-part_size.x, part_size.z);*/ - - - } - m_geom->addEntity(m_partEntity, - child_part->getCFrame().getPosition(), - Ogre::Quaternion(child_part->getCFrame().getRotation()), - child_part->getSize()); - } - for(auto& child : *instance->getChildren()) - buildGeomInstance(child); } void Workspace::buildGeom() { - if(!m_geomDirty) + if(!m_geomDirty || m_batchMode != BATCH_STATIC_GEOMETRY) return; - m_geom->reset(); - for(auto& child : *getChildren()) - buildGeomInstance(child); m_geom->build(); m_geomDirty = false; } - void Workspace::onChildRemoved(Instance* childRemoved) + void Workspace::onDescendantRemoved(Instance* childRemoved) { - m_geomDirty = true; + m_geomDirty = true; } Camera* Workspace::getCurrentCamera() const diff --git a/Projects/Engine/Source/App/V8/Tree/Instance.cpp b/Projects/Engine/Source/App/V8/Tree/Instance.cpp index 21e757a..c3680ca 100644 --- a/Projects/Engine/Source/App/V8/Tree/Instance.cpp +++ b/Projects/Engine/Source/App/V8/Tree/Instance.cpp @@ -132,6 +132,9 @@ namespace RNR { children->erase(child_it); m_parent->onChildRemoved(this); + m_parent->onDescendantRemoved(this); + for(auto& child : m_children) + descendantRemovedChildren(m_parent, child); if (m_parent->numChildren() == 0) { @@ -140,24 +143,59 @@ namespace RNR } } + onSetParent(newParent); m_parent = newParent; + if(m_parent) { m_parent->m_children.push_back(this); newParent->onChildAdded(this); + newParent->onDescendantAdded(this); + for(auto& child : m_children) + descendantAddedChildren(m_parent, child); } } } + void Instance::descendantAddedChildren(Instance* p, Instance* c) + { + for(auto& child : *c->getChildren()) + descendantAddedChildren(p, child); + p->onDescendantAdded(c); + } + + void Instance::descendantRemovedChildren(Instance* p, Instance* c) + { + for(auto& child : *c->getChildren()) + descendantRemovedChildren(p, child); + p->onDescendantRemoved(c); + } + void Instance::onChildAdded(Instance* childAdded) { // } + void Instance::onDescendantAdded(Instance* descendantAdded) + { + if(m_parent) + m_parent->onDescendantAdded(descendantAdded); + } void Instance::onChildRemoved(RNR::Instance* childRemoved) { - + + } + + void Instance::onDescendantRemoved(Instance* descendantRemoved) + { + if(m_parent) + m_parent->onDescendantRemoved(descendantRemoved); + } + + void Instance::onSetParent(Instance* newParent) + { + } bool Instance::isA(std::string type) diff --git a/Projects/Engine/Source/App/V8/World/World.cpp b/Projects/Engine/Source/App/V8/World/World.cpp index 2da69ed..5228445 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -32,7 +32,7 @@ namespace RNR m_workspace = (Workspace*)m_datamodel->getService("Workspace"); m_runService = (RunService*)m_datamodel->getService("RunService"); - m_tmb = new TopMenuBar(); + m_tmb = new TopMenuBar(this); Camera* start_cam = new Camera(); start_cam->setParent(m_workspace); @@ -70,9 +70,9 @@ namespace RNR m_refs[referent.as_string()] = instance; WorldUndeserialized s; s.instance = instance; + s.parent = parent; 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); @@ -111,6 +111,7 @@ namespace RNR s.instance->deserializeXmlProperty(prop); } + s.instance->setParent(s.parent); if(s.instance->getClassName() == "Model") { ModelInstance* m = (ModelInstance*)s.instance; @@ -129,6 +130,7 @@ namespace RNR { if(m_inputManager) m_inputManager->frame(); + m_tmb->frame(); } double World::step(float timestep)