diff --git a/Content/RNR/fonts/comic.ttf b/Content/RNR/fonts/comic.ttf new file mode 100644 index 0000000..c4bd6c1 Binary files /dev/null and b/Content/RNR/fonts/comic.ttf differ diff --git a/Content/RNR/textures/placeholder.png b/Content/RNR/textures/placeholder.png new file mode 100644 index 0000000..fd79f3a Binary files /dev/null and b/Content/RNR/textures/placeholder.png differ diff --git a/Projects/Client/Common/Source/OgreWidget.cpp b/Projects/Client/Common/Source/OgreWidget.cpp index 4cc9472..8bbec03 100644 --- a/Projects/Client/Common/Source/OgreWidget.cpp +++ b/Projects/Client/Common/Source/OgreWidget.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #ifdef __unix__ #include @@ -31,11 +34,14 @@ namespace RNR Ogre::NameValuePairList options = this->getRenderOptions(); printf("OgreWidget::initializeOgre: initializing render window\n"); + Ogre::OverlaySystem* ogreOverlay = new Ogre::OverlaySystem(); + ogreWindow = ogreRoot->createRenderWindow("GLWidget-RenderWindow", width(), height(), false, &options); ogreWindow->setActive(true); ogreWindow->setVisible(true); ogreWindow->setAutoUpdated(true); + Ogre::ResourceGroupManager::getSingletonPtr()->addResourceLocation("shaders", "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); //Ogre::ResourceGroupManager::getSingletonPtr()->addResourceLocation("../Content/OgrePrivate/RTShaderLib/GLSL/", "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // rtshader path @@ -43,6 +49,7 @@ namespace RNR ogreSceneManager = ogreRoot->createSceneManager(); ogreSceneManager->setAmbientLight(Ogre::ColourValue(0.2f,0.2f,0.2f)); + ogreSceneManager->addRenderQueueListener(ogreOverlay); Ogre::SceneNode* camNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode(); camNode->setPosition(0, 0, 5); @@ -74,6 +81,12 @@ namespace RNR Ogre::ResourceGroupManager::getSingletonPtr()->addResourceLocation("content", "FileSystem", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); Ogre::ResourceGroupManager::getSingletonPtr()->initialiseAllResourceGroups(); + Ogre::FontPtr pFont = Ogre::FontManager::getSingletonPtr()->create("ComicSans", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); + pFont->setType(Ogre::FT_TRUETYPE); + pFont->setSource("fonts/comic.ttf"); + pFont->setTrueTypeSize(16); + pFont->load(); + ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE); ogreSceneManager->setShadowFarDistance(500.f); @@ -104,15 +117,11 @@ namespace RNR this->render_time += ogreRoot->getTimer()->getMilliseconds() / 1000.0; ogreRoot->getTimer()->reset(); - RNR::ModelInstance* sel_model = dynamic_cast(selectedInstance); - if(sel_model) + if(world->getWorkspace()->getCurrentCamera()) { - Ogre::AxisAlignedBox boundingBox = sel_model->getBoundingBox(); - if(!boundingBox.isNull() && !boundingBox.isInfinite()) - { - ogreCamera->getParentSceneNode()->setPosition(boundingBox.getCorner(Ogre::AxisAlignedBox::CornerEnum::NEAR_LEFT_TOP) * 1.1); - ogreCamera->getParentSceneNode()->lookAt(boundingBox.getCenter(), Ogre::Node::TS_WORLD); - } + Camera* cam = world->getWorkspace()->getCurrentCamera(); + ogreCamera->getParentSceneNode()->setPosition(cam->getCFrame().getPosition()); + ogreCamera->getParentSceneNode()->setOrientation(Ogre::Quaternion(cam->getCFrame().getRotation())); } ogreRoot->renderOneFrame(this->delta); diff --git a/Projects/Client/Studio/Source/MainWindow.cpp b/Projects/Client/Studio/Source/MainWindow.cpp index 86d1e2b..1d0128a 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -69,6 +69,7 @@ void MainWindow::recurseTreeAddInstance(QTreeWidgetItem* parent, RNR::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)); diff --git a/Projects/Engine/CMakeLists.txt b/Projects/Engine/CMakeLists.txt index b59614f..476af75 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -6,6 +6,7 @@ add_library(Engine STATIC Header/App/GUI/GuiBase3d.hpp Header/App/GUI/InstanceAdornment.hpp Header/App/GUI/SelectionBox.hpp + Header/App/GUI/TopMenuBar.hpp Header/App/Humanoid/Humanoid.hpp Header/App/V8/DataModel/Camera.hpp Header/App/V8/DataModel/ForceField.hpp @@ -27,6 +28,7 @@ add_library(Engine STATIC Source/App/GUI/GuiBase3d.cpp Source/App/GUI/InstanceAdornment.cpp Source/App/GUI/SelectionBox.cpp + Source/App/GUI/TopMenuBar.cpp Source/App/Humanoid/Humanoid.cpp Source/App/V8/DataModel/Camera.cpp Source/App/V8/DataModel/ForceField.cpp diff --git a/Projects/Engine/Header/App/GUI/TopMenuBar.hpp b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp new file mode 100644 index 0000000..8f3f10c --- /dev/null +++ b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace RNR +{ + class TopMenuBar + { + public: + TopMenuBar(); + }; +} \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/Camera.hpp b/Projects/Engine/Header/App/V8/DataModel/Camera.hpp index 671d0ec..3c741f9 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Camera.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Camera.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace RNR @@ -9,9 +10,15 @@ namespace RNR class Camera : public Instance { + private: + CoordinateFrame m_cframe; + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); public: Camera(); ~Camera(); + CoordinateFrame& getCFrame() { return m_cframe; }; + void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; }; + bool zoom(float distance); }; } \ No newline at end of file diff --git a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp index d22a507..0780ebb 100644 --- a/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/Workspace.hpp @@ -25,6 +25,7 @@ namespace RNR Camera* getCurrentCamera() const; void setCurrentCamera(Camera *value); private: + virtual void deserializeProperty(char* prop_name, pugi::xml_node prop); void buildGeomInstance(Instance* instance); bool m_geomDirty; diff --git a/Projects/Engine/Header/App/V8/World/World.hpp b/Projects/Engine/Header/App/V8/World/World.hpp index 28d9652..a778d25 100644 --- a/Projects/Engine/Header/App/V8/World/World.hpp +++ b/Projects/Engine/Header/App/V8/World/World.hpp @@ -2,21 +2,35 @@ #include #include +#include +#include #include #include +#include namespace RNR { + struct WorldUndeserialized + { + Instance* instance; + pugi::xml_node node; + }; + class World { private: + std::map m_refs; + std::stack m_undeserialized; Instance* m_datamodel; Workspace* m_workspace; Ogre::Root* m_ogreRoot; Ogre::SceneManager* m_ogreSceneManager; + TopMenuBar* m_tmb; void xmlAddItem(pugi::xml_node node, Instance* parent); public: + Instance* getRef(std::string ref) { return m_refs[ref]; } + World(Ogre::Root* ogre, Ogre::SceneManager* ogreScene); ~World(); @@ -26,6 +40,8 @@ namespace RNR double step(float timestep); void update(); + + Instance* getDatamodel() { return m_datamodel; } void setDatamodel(Instance* instance) { m_datamodel = instance; } Workspace* getWorkspace() { return m_workspace; } diff --git a/Projects/Engine/Source/App/GUI/TopMenuBar.cpp b/Projects/Engine/Source/App/GUI/TopMenuBar.cpp new file mode 100644 index 0000000..daf8853 --- /dev/null +++ b/Projects/Engine/Source/App/GUI/TopMenuBar.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +namespace RNR +{ + TopMenuBar::TopMenuBar() + { + Ogre::OverlayManager* overlayManager = Ogre::OverlayManager::getSingletonPtr(); + Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Background", "General"); + material->getTechnique(0)->getPass(0)->createTextureUnitState("placeholder.png"); + material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, 0.5f); + material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue(1.0, 1.0, 1.0)); + material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); + material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); + material->getTechnique(0)->getPass(0)->setLightingEnabled(false); + + Ogre::OverlayContainer* panel = static_cast(overlayManager->createOverlayElement("Panel", "PanelName")); + panel->setMetricsMode(Ogre::GMM_PIXELS); + panel->setPosition(0,0); + panel->setDimensions(320, 24); + panel->setMaterial(material); + + Ogre::TextAreaOverlayElement* textArea = static_cast(overlayManager->createOverlayElement("TextArea", "TextAreaName")); + textArea->setMetricsMode(Ogre::GMM_PIXELS); + textArea->setPosition(0, 0); + textArea->setDimensions(320, 24); + textArea->setCaption("Hello, World!"); + textArea->setCharHeight(24); + textArea->setFontName("ComicSans"); + textArea->setColour(Ogre::ColourValue(0.f,0.f,0.f)); + + Ogre::Overlay* overlay = overlayManager->create("OverlayName"); + overlay->add2D(panel); + overlay->setZOrder(500); + + panel->addChild(textArea); + + overlay->show(); + } +} \ No newline at end of file diff --git a/Projects/Engine/Source/App/V8/DataModel/Camera.cpp b/Projects/Engine/Source/App/V8/DataModel/Camera.cpp index f11c422..9e95c03 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Camera.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Camera.cpp @@ -1,4 +1,5 @@ #include +#include namespace RNR { @@ -11,4 +12,12 @@ namespace RNR { // } + + void Camera::deserializeProperty(char* prop_name, pugi::xml_node node) + { + if(prop_name == std::string("CoordinateFrame")) + { + setCFrame(XML::getCFrame(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 2bbfdb0..334b6b1 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -25,7 +25,10 @@ namespace RNR PartInstance* child_part = dynamic_cast(instance); if(child_part) { +#define DONT_USE_BRICKCOLOR_MATERIAL +#ifndef DONT_USE_BRICKCOLOR_MATERIAL m_partEntity->setMaterial(BrickColor::material(child_part->getBrickColor())); +#endif m_geom->addEntity(m_partEntity, child_part->getCFrame().getPosition(), Ogre::Quaternion(child_part->getCFrame().getRotation()), @@ -66,4 +69,16 @@ namespace RNR // TODO: raise propertyChanged and currentCameraChangedSignal } } + + void Workspace::deserializeProperty(char* prop_name, pugi::xml_node node) + { + if(prop_name == std::string("CurrentCamera")) + { + Instance* new_cam = world->getRef(node.text().as_string()); + if(new_cam) + setCurrentCamera((Camera*)new_cam); + else + printf("Workspace::deserializeProperty: camera ref invalid (%s)\n", node.text().as_string()); + } + } } \ 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 35fec24..85f5195 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -16,6 +16,8 @@ namespace RNR m_workspace = new Workspace(); m_workspace->setParent(m_datamodel); + m_tmb = new TopMenuBar(); + load("/home/caesium/Downloads/Telegram Desktop/Destroy-History-1.rbxl"); } @@ -38,21 +40,28 @@ namespace RNR { instance = m_workspace; } + else if(class_attr.as_string() == std::string("Camera")) + { + instance = new Camera(); + } else if(class_attr.as_string() == std::string("Model")) { instance = new ModelInstance(); } 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); + pugi::xml_attribute referent = node.attribute("referent"); + if(!referent.empty()) + m_refs[referent.as_string()] = instance; + WorldUndeserialized s; + s.instance = instance; + s.node = node; + m_undeserialized.push(s); instance->setParent(parent); } @@ -69,6 +78,8 @@ namespace RNR void World::load(char* path) { + m_refs.clear(); + pugi::xml_document rbxl_doc; pugi::xml_parse_result result = rbxl_doc.load_file(path); if(result) @@ -80,6 +91,23 @@ namespace RNR { xmlAddItem(item, m_datamodel); } + while(!m_undeserialized.empty()) + { + WorldUndeserialized s = m_undeserialized.top(); + m_undeserialized.pop(); + + pugi::xml_node props = s.node.child("Properties"); + for(pugi::xml_node prop : props.children()) + { + s.instance->deserializeXmlProperty(prop); + } + + if(s.instance->getClassName() == "Model") + { + ModelInstance* m = (ModelInstance*)s.instance; + m->build(); + } + } } else {