diff --git a/Content/RNR/textures/studio/icons/Player.png b/Content/RNR/textures/studio/icons/Player.png new file mode 100644 index 0000000..f3ae274 Binary files /dev/null and b/Content/RNR/textures/studio/icons/Player.png differ diff --git a/Content/RNR/textures/studio/icons/Players.png b/Content/RNR/textures/studio/icons/Players.png new file mode 100644 index 0000000..d22f336 Binary files /dev/null and b/Content/RNR/textures/studio/icons/Players.png differ diff --git a/Content/RNR/textures/studio/icons/play.png b/Content/RNR/textures/studio/icons/play.png new file mode 100644 index 0000000..66fd4b7 Binary files /dev/null and b/Content/RNR/textures/studio/icons/play.png differ diff --git a/Projects/Client/Studio/Header/MainWindow.hpp b/Projects/Client/Studio/Header/MainWindow.hpp index e437512..abaf421 100644 --- a/Projects/Client/Studio/Header/MainWindow.hpp +++ b/Projects/Client/Studio/Header/MainWindow.hpp @@ -39,6 +39,7 @@ class MainWindow : public QMainWindow void selectInstance(QTreeWidgetItem *item, int column); void run(); void pause(); + void playSolo(); void dbg_pointlight(); protected: diff --git a/Projects/Client/Studio/Source/MainWindow.cpp b/Projects/Client/Studio/Source/MainWindow.cpp index c92d1b0..41163b6 100644 --- a/Projects/Client/Studio/Source/MainWindow.cpp +++ b/Projects/Client/Studio/Source/MainWindow.cpp @@ -114,6 +114,7 @@ void MainWindow::createToolbar() QAction* run_action = toolbar->addAction(QIcon("content/textures/studio/icons/run.png"), "", this, SLOT(run())); QAction* pause_action = toolbar->addAction(QIcon("content/textures/studio/icons/pause.png"), "", this, SLOT(pause())); + QAction* playSolo_action = toolbar->addAction(QIcon("content/textures/studio/icons/play.png"), "", this, SLOT(playSolo())); #ifndef NDEBUG toolbar->addSeparator(); @@ -131,6 +132,17 @@ void MainWindow::pause() this->ogreWidget->world->getRunService()->pause(); } +void MainWindow::playSolo() +{ + this->ogreWidget->world->getRunService()->run(); + + RNR::Players* players = (RNR::Players*)this->ogreWidget->world->getDatamodel()->getService("Players"); + RNR::Player* player = players->createLocalPlayer(0); + player->setName(QInputDialog::getText(this, "Player Name", "Enter your player name").toLocal8Bit().data()); + + updateTree(ogreWidget->world->getDatamodel()); +} + void MainWindow::dbg_pointlight() { if(!ogreWidget->selectedInstance) @@ -144,8 +156,8 @@ void MainWindow::dbg_pointlight() 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); + double g = QInputDialog::getDouble(this, "Green", "Set green component [0.0-1.0]", 1.0, 0.0, 1.0, 2); + double b = QInputDialog::getDouble(this, "Blue", "Set blue component [0.0-1.0]", 1.0, 0.0, 1.0, 2); dbg_light->setColor(Ogre::Vector3(r,g,b)); updateTree(ogreWidget->world->getDatamodel()); diff --git a/Projects/Engine/CMakeLists.txt b/Projects/Engine/CMakeLists.txt index 09cd9a0..78f0797 100644 --- a/Projects/Engine/CMakeLists.txt +++ b/Projects/Engine/CMakeLists.txt @@ -4,6 +4,8 @@ add_library(Engine STATIC Header/Helpers/XML.hpp Header/Helpers/NormalId.hpp Header/App/Script/ReflectionProperty.hpp + Header/App/Script/Script.hpp + Header/App/Script/ScriptContext.hpp Header/App/GUI/GuiBase3d.hpp Header/App/GUI/InstanceAdornment.hpp Header/App/GUI/SelectionBox.hpp @@ -26,6 +28,8 @@ add_library(Engine STATIC Header/App/BrickColor.hpp Header/App/InputManager.hpp Header/Network/GUID.hpp + Header/Network/Player.hpp + Header/Network/Players.hpp Header/Rendering/Adorn.hpp Source/Helpers/Name.cpp @@ -33,6 +37,7 @@ add_library(Engine STATIC Source/Helpers/XML.cpp Source/Helpers/NormalId.cpp Source/App/Script/ReflectionProperty.cpp + Source/App/Script/Script.cpp Source/App/GUI/GuiBase3d.cpp Source/App/GUI/InstanceAdornment.cpp Source/App/GUI/SelectionBox.cpp @@ -55,6 +60,8 @@ add_library(Engine STATIC Source/App/InputManager.cpp Source/App/V8/World/World.cpp Source/Network/GUID.cpp + Source/Network/Player.cpp + Source/Network/Players.cpp Source/Rendering/Adorn.cpp ) diff --git a/Projects/Engine/Header/App/GUI/TopMenuBar.hpp b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp index 98f6360..12734fd 100644 --- a/Projects/Engine/Header/App/GUI/TopMenuBar.hpp +++ b/Projects/Engine/Header/App/GUI/TopMenuBar.hpp @@ -14,6 +14,9 @@ namespace RNR class TopMenuBar { Ogre::TextAreaOverlayElement* m_debugText; + Ogre::TextAreaOverlayElement* m_playerList; + Ogre::OverlayContainer* m_playerPanel; + Ogre::OverlayManager* m_overlayManager; World* m_world; public: TopMenuBar(World* world); diff --git a/Projects/Engine/Header/App/Script/ScriptContext.hpp b/Projects/Engine/Header/App/Script/ScriptContext.hpp new file mode 100644 index 0000000..8411fbf --- /dev/null +++ b/Projects/Engine/Header/App/Script/ScriptContext.hpp @@ -0,0 +1,9 @@ +#pragma once + +namespace RNR +{ + class ScriptContext + { + + }; +} \ 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 9314c72..ca1657d 100644 --- a/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp +++ b/Projects/Engine/Header/App/V8/DataModel/PartInstance.hpp @@ -11,6 +11,8 @@ namespace RNR { protected: int m_brickColor; + float m_transparency; + float m_reflectance; Ogre::Matrix4 m_matrix; Ogre::Vector3 m_position; Ogre::Vector3 m_size; @@ -28,6 +30,11 @@ namespace RNR Ogre::Vector3 getSize() { return m_size; } Ogre::Vector4 getColor() { return m_color; } + void setReflectance(float reflectance) { m_reflectance = reflectance; } + float getReflectance() { return m_reflectance; } + void setTransparency(float transparency) { m_transparency = transparency; } + float getTransparency() { return m_transparency; } + Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); } void setBrickColor(int brickcolor) { m_brickColor = brickcolor; } diff --git a/Projects/Engine/Header/App/V8/World/World.hpp b/Projects/Engine/Header/App/V8/World/World.hpp index 7595e06..ff2e87f 100644 --- a/Projects/Engine/Header/App/V8/World/World.hpp +++ b/Projects/Engine/Header/App/V8/World/World.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ namespace RNR DataModel* m_datamodel; Workspace* m_workspace; RunService* m_runService; + Players* m_players; Ogre::Root* m_ogreRoot; Ogre::SceneManager* m_ogreSceneManager; TopMenuBar* m_tmb; diff --git a/Projects/Engine/Header/Network/Player.hpp b/Projects/Engine/Header/Network/Player.hpp new file mode 100644 index 0000000..6354492 --- /dev/null +++ b/Projects/Engine/Header/Network/Player.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include + +namespace RNR +{ + class Player : public Instance + { + ModelInstance* m_character; + int m_userId; + public: + Player(); + + ModelInstance* getCharacter() { return m_character; } + void setCharacter(ModelInstance* model) { m_character = model; } + virtual std::string getClassName() { return "Player"; } + virtual void addProperties(std::vector& properties); + }; +} \ No newline at end of file diff --git a/Projects/Engine/Header/Network/Players.hpp b/Projects/Engine/Header/Network/Players.hpp new file mode 100644 index 0000000..1539efa --- /dev/null +++ b/Projects/Engine/Header/Network/Players.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace RNR +{ + class Players : public Instance + { + private: + Player* m_localPlayer; + public: + Players(); + + virtual std::string getClassName() { return "Players"; } + + Player* getLocalPlayer() { return m_localPlayer; }; + Player* createLocalPlayer(int userId); + virtual void addProperties(std::vector& properties); + }; +} \ 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 1733f12..59164a8 100644 --- a/Projects/Engine/Source/App/GUI/TopMenuBar.cpp +++ b/Projects/Engine/Source/App/GUI/TopMenuBar.cpp @@ -7,7 +7,7 @@ namespace RNR { m_world = world; - Ogre::OverlayManager* overlayManager = Ogre::OverlayManager::getSingletonPtr(); + m_overlayManager = Ogre::OverlayManager::getSingletonPtr(); Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("Background", "General"); material->getTechnique(0)->getPass(0)->createTextureUnitState("textures/placeholder.png"); material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, Ogre::ColourValue(0.5, 0.5, 0.5)); @@ -17,7 +17,7 @@ namespace RNR material->getTechnique(0)->getPass(0)->setLightingEnabled(false); material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SceneBlendType::SBT_TRANSPARENT_COLOUR); - Ogre::OverlayContainer* panel = static_cast(overlayManager->createOverlayElement("Panel", "TopMenuBarPanel")); + Ogre::OverlayContainer* panel = static_cast(m_overlayManager->createOverlayElement("Panel", "TopMenuBarPanel")); panel->setMetricsMode(Ogre::GMM_PIXELS); panel->setPosition(0,0); panel->setDimensions(128 * 5, 20); @@ -25,7 +25,7 @@ namespace RNR Ogre::ColourValue text_color = Ogre::ColourValue(0.25, 0.25, 0.25); - Ogre::TextAreaOverlayElement* toolsTextArea = static_cast(overlayManager->createOverlayElement("TextArea", "TopMenuBarTools")); + Ogre::TextAreaOverlayElement* toolsTextArea = static_cast(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarTools")); toolsTextArea->setMetricsMode(Ogre::GMM_PIXELS); toolsTextArea->setPosition(0, 0); toolsTextArea->setDimensions(128, 24); @@ -34,7 +34,7 @@ namespace RNR toolsTextArea->setFontName("ComicSans"); toolsTextArea->setColour(text_color); - Ogre::TextAreaOverlayElement* insertTextArea = static_cast(overlayManager->createOverlayElement("TextArea", "TopMenuBarInsert")); + Ogre::TextAreaOverlayElement* insertTextArea = static_cast(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarInsert")); insertTextArea->setMetricsMode(Ogre::GMM_PIXELS); insertTextArea->setPosition(128, 0); insertTextArea->setDimensions(128, 24); @@ -43,7 +43,7 @@ namespace RNR insertTextArea->setFontName("ComicSans"); insertTextArea->setColour(text_color); - Ogre::TextAreaOverlayElement* fullscreenTextArea = static_cast(overlayManager->createOverlayElement("TextArea", "TopMenuBarFullscreen")); + Ogre::TextAreaOverlayElement* fullscreenTextArea = static_cast(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarFullscreen")); fullscreenTextArea->setMetricsMode(Ogre::GMM_PIXELS); fullscreenTextArea->setPosition(128*2, 0); fullscreenTextArea->setDimensions(128, 24); @@ -52,7 +52,7 @@ namespace RNR fullscreenTextArea->setFontName("ComicSans"); fullscreenTextArea->setColour(text_color); - Ogre::TextAreaOverlayElement* helpTextArea = static_cast(overlayManager->createOverlayElement("TextArea", "TopMenuBarHelp")); + Ogre::TextAreaOverlayElement* helpTextArea = static_cast(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarHelp")); helpTextArea->setMetricsMode(Ogre::GMM_PIXELS); helpTextArea->setPosition(128*3, 0); helpTextArea->setDimensions(128, 24); @@ -61,7 +61,7 @@ namespace RNR helpTextArea->setFontName("ComicSans"); helpTextArea->setColour(text_color); - Ogre::TextAreaOverlayElement* exitTextArea = static_cast(overlayManager->createOverlayElement("TextArea", "TopMenuBarExit")); + Ogre::TextAreaOverlayElement* exitTextArea = static_cast(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarExit")); exitTextArea->setMetricsMode(Ogre::GMM_PIXELS); exitTextArea->setPosition(128*4, 0); exitTextArea->setDimensions(128, 24); @@ -76,7 +76,7 @@ namespace RNR panel->addChild(helpTextArea); panel->addChild(exitTextArea); - m_debugText = static_cast(overlayManager->createOverlayElement("TextArea", "DebugTextArea")); + m_debugText = static_cast(m_overlayManager->createOverlayElement("TextArea", "DebugTextArea")); m_debugText->setMetricsMode(Ogre::GMM_PIXELS); m_debugText->setPosition(0, 300); m_debugText->setDimensions(420, 500); @@ -87,8 +87,26 @@ namespace RNR panel->addChild(m_debugText); - Ogre::Overlay* overlay = overlayManager->create("OverlayName"); + m_playerPanel = static_cast(m_overlayManager->createOverlayElement("Panel", "PlayerListPanel")); + m_playerPanel->setMetricsMode(Ogre::GMM_PIXELS); + m_playerPanel->setDimensions(128, 20); + m_playerPanel->setMaterial(material); + + m_playerList = static_cast(m_overlayManager->createOverlayElement("TextArea", "PlayerListTextArea")); + m_playerList->setMetricsMode(Ogre::GMM_PIXELS); + m_playerList->setPosition(0, 0); + m_playerList->setDimensions(1000, 1000); + m_playerList->setCaption("Player List"); + m_playerList->setCharHeight(24); + m_playerList->setFontName("ComicSans"); + m_playerList->setColour(Ogre::ColourValue(1.0f, 1.0f, 1.0f)); + + m_playerPanel->addChild(m_playerList); + m_playerPanel->setVisible(false); + + Ogre::Overlay* overlay = m_overlayManager->create("TopMenuBarOverlay"); overlay->add2D(panel); + overlay->add2D(m_playerPanel); overlay->setZOrder(500); overlay->show(); @@ -111,5 +129,24 @@ namespace RNR } snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n",m_world->getLastDelta(),render_debugtext,m_world->getOgreSceneManager()); m_debugText->setCaption(debugtext); + + Players* players = (Players*)m_world->getDatamodel()->getService("Players"); + auto player_list = players->getChildren(); + if(player_list->size() == 0) + { + m_playerPanel->setVisible(false); + } + else + { + m_playerPanel->setVisible(true); + m_playerPanel->setPosition(m_overlayManager->getViewportWidth() - 128 - 5,5); + std::string player_list_text = "Player List\n"; + for(auto player : *player_list) + { + player_list_text += player->getName() + "\n"; + } + m_playerList->setCaption(player_list_text); + m_playerPanel->setDimensions(128, 20 * (player_list->size() + 1)); + } } } \ 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 8fb0f38..bec7c7c 100644 --- a/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/PartInstance.cpp @@ -9,6 +9,8 @@ namespace RNR setName("Part"); m_color = Ogre::Vector4(0.63, 0.64, 0.63, 1.0); + m_transparency = 0.0; + m_reflectance = 0.0; setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode()); setObject(world->getOgreSceneManager()->createEntity("fonts/Cube.mesh")); @@ -30,6 +32,7 @@ namespace RNR for(auto& subentity : entity->getSubEntities()) { subentity->setMaterial(BrickColor::material(m_brickColor)); + subentity->getMaterial()->setShininess(64); } } @@ -47,6 +50,14 @@ namespace RNR printf("PartInstance::deserializeProperty: BrickColor not valid number (%i)\n", getBrickColor()); } } + else if(prop_name == std::string("Reflectance")) + { + setReflectance(node.text().as_float()); + } + else if(prop_name == std::string("Transparency")) + { + setTransparency(node.text().as_float()); + } else PVInstance::deserializeProperty(prop_name, node); updateMatrix(); @@ -63,6 +74,14 @@ namespace RNR 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); ) }, + { this, std::string("Reflectance"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_FLOAT, + REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_reflectance; ), + REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setReflectance(*(float*)value); ) }, + { this, std::string("Transparency"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_FLOAT, + REFLECTION_GETTER(PartInstance* instance = (PartInstance*)object; return &instance->m_transparency; ), + REFLECTION_SETTER(PartInstance* instance = (PartInstance*)object; instance->setTransparency(*(float*)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 ac9dd77..b314c73 100644 --- a/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp +++ b/Projects/Engine/Source/App/V8/DataModel/Workspace.cpp @@ -19,7 +19,7 @@ namespace RNR break; case BATCH_STATIC_GEOMETRY: m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom"); - m_geom->setRegionDimensions(Ogre::Vector3(255,255,255)); + m_geom->setRegionDimensions(Ogre::Vector3(512,512,512)); m_geom->setCastShadows(true); break; } @@ -40,6 +40,7 @@ namespace RNR replica->setPosition(part->getPosition()); replica->setOrientation(part->getCFrame().getRotation()); replica->setScale(part->getSize()); + childAdded->setObject(replica); } break; case BATCH_STATIC_GEOMETRY: diff --git a/Projects/Engine/Source/App/V8/World/World.cpp b/Projects/Engine/Source/App/V8/World/World.cpp index 5228445..38bc843 100644 --- a/Projects/Engine/Source/App/V8/World/World.cpp +++ b/Projects/Engine/Source/App/V8/World/World.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,8 @@ namespace RNR m_instanceFactory->registerInstance("Workspace", InstanceFactory::instanceBuilder); m_instanceFactory->registerInstance("Humanoid", InstanceFactory::instanceBuilder); m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder); + m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder); + m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder); m_ogreRoot = ogre; m_ogreSceneManager = ogreSceneManager; @@ -31,6 +34,7 @@ namespace RNR m_datamodel->setName("DataModel"); m_workspace = (Workspace*)m_datamodel->getService("Workspace"); m_runService = (RunService*)m_datamodel->getService("RunService"); + m_players = (Players*)m_datamodel->getService("Players"); m_tmb = new TopMenuBar(this); diff --git a/Projects/Engine/Source/Network/Player.cpp b/Projects/Engine/Source/Network/Player.cpp new file mode 100644 index 0000000..352b7fe --- /dev/null +++ b/Projects/Engine/Source/Network/Player.cpp @@ -0,0 +1,25 @@ +#include +#include + +namespace RNR +{ + Player::Player() + { + setName("Player"); + setParent(world->getDatamodel()->getService("Players")); + + m_character = NULL; + } + + void Player::addProperties(std::vector& properties) + { + ReflectionProperty _properties[] = { + { this, std::string("Character"), std::string(""), + ACCESS_NONE, OPERATION_READWRITE, PROPERTY_INSTANCE, + REFLECTION_GETTER(Player* instance = (Player*)object; return instance->m_character; ), + REFLECTION_SETTER(Player* instance = (Player*)object; instance->setCharacter((ModelInstance*)value); ) }, + }; + + properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); + } +} diff --git a/Projects/Engine/Source/Network/Players.cpp b/Projects/Engine/Source/Network/Players.cpp new file mode 100644 index 0000000..186610b --- /dev/null +++ b/Projects/Engine/Source/Network/Players.cpp @@ -0,0 +1,34 @@ +#include + +namespace RNR +{ + Players::Players() + { + setName("Players"); + m_localPlayer = 0; + } + + Player* Players::createLocalPlayer(int userId) + { + if(m_localPlayer) + { + printf("Players::createLocalPlayer: attempt to create another local player\n", userId); + return m_localPlayer; + } + printf("Players::createLocalPlayer: created player %i\n", userId); + m_localPlayer = new Player(); + return m_localPlayer; + } + + void Players::addProperties(std::vector& properties) + { + ReflectionProperty _properties[] = { + { this, std::string("LocalPlayer"), std::string(""), + ACCESS_NONE, OPERATION_READ, PROPERTY_INSTANCE, + REFLECTION_GETTER(Players* instance = (Players*)object; return instance->m_localPlayer; ), + REFLECTION_SETTER( ) }, + }; + + properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty))); + } +} \ No newline at end of file