Merge branch 'trunk' of https://github.com/lrre-foss/rnr into trunk

This commit is contained in:
sorket 2023-07-19 13:33:30 -04:00
commit 17812a3460
31 changed files with 536 additions and 87 deletions

View File

@ -16,6 +16,7 @@ material materials/partinstanced
rtshader_system
{
transform_stage instanced
lighting_stage per_pixel
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -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);

View File

@ -39,6 +39,7 @@ class MainWindow : public QMainWindow
void selectInstance(QTreeWidgetItem *item, int column);
void run();
void pause();
void playSolo();
void dbg_pointlight();
protected:

View File

@ -1,7 +1,10 @@
#include <MainWindow.hpp>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QInputDialog>
#include <App/V8/Tree/ModelInstance.hpp>
#include <App/V8/DataModel/Light.hpp>
MainWindow::MainWindow()
{
@ -111,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();
@ -128,9 +132,35 @@ 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)
{
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, "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());
}
void MainWindow::closeEvent(QCloseEvent* event)

View File

@ -3,6 +3,8 @@
#include <QHeaderView>
#include <QFile>
#include <App/BrickColor.hpp>
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);

View File

@ -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
)

View File

@ -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);
};
}

View File

@ -1,12 +1,26 @@
#pragma once
#include <OGRE/Ogre.h>
#include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreOverlayContainer.h>
#include <OGRE/Overlay/OgreTextAreaOverlayElement.h>
#include <OGRE/Overlay/OgreFontManager.h>
#include <OGRE/Overlay/OgreOverlay.h>
namespace RNR
{
class World;
class TopMenuBar
{
Ogre::TextAreaOverlayElement* m_debugText;
Ogre::TextAreaOverlayElement* m_playerList;
Ogre::OverlayContainer* m_playerPanel;
Ogre::OverlayManager* m_overlayManager;
World* m_world;
public:
TopMenuBar();
TopMenuBar(World* world);
void frame();
};
}

View File

@ -41,6 +41,7 @@ namespace RNR
PROPERTY_CFRAME,
PROPERTY_INSTANCE,
PROPERTY_FLOAT,
PROPERTY_BRICKCOLOR,
};
class ReflectionProperty

View File

@ -0,0 +1,9 @@
#pragma once
namespace RNR
{
class ScriptContext
{
};
}

View File

@ -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; }
};
}

View File

@ -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,13 @@ 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; }
int getBrickColor() { return m_brickColor; }
};

View File

@ -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<ReflectionProperty>& 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;

View File

@ -30,6 +30,9 @@ namespace RNR
RNR::Instance* m_parent;
std::vector<RNR::Instance*> 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);
};
}

View File

@ -6,6 +6,7 @@
#include <App/V8/DataModel/Camera.hpp>
#include <App/V8/DataModel/RunService.hpp>
#include <App/V8/DataModel/DataModel.hpp>
#include <Network/Players.hpp>
#include <App/GUI/TopMenuBar.hpp>
#include <OGRE/Ogre.h>
#include <pugixml.hpp>
@ -18,6 +19,7 @@ namespace RNR
struct WorldUndeserialized
{
Instance* instance;
Instance* parent;
pugi::xml_node node;
};
@ -29,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;

View File

@ -0,0 +1,19 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
#include <App/V8/Tree/ModelInstance.hpp>
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<ReflectionProperty>& properties);
};
}

View File

@ -0,0 +1,21 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
#include <Network/Player.hpp>
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<ReflectionProperty>& properties);
};
}

View File

@ -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;
}
}

View File

@ -1,44 +1,152 @@
#include <App/GUI/TopMenuBar.hpp>
#include <OGRE/Overlay/OgreOverlayManager.h>
#include <OGRE/Overlay/OgreOverlayContainer.h>
#include <OGRE/Overlay/OgreTextAreaOverlayElement.h>
#include <OGRE/Overlay/OgreFontManager.h>
#include <OGRE/Overlay/OgreOverlay.h>
#include <App/V8/World/World.hpp>
namespace RNR
{
TopMenuBar::TopMenuBar()
TopMenuBar::TopMenuBar(World* world)
{
Ogre::OverlayManager* overlayManager = Ogre::OverlayManager::getSingletonPtr();
m_world = world;
m_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)->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));
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);
material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SceneBlendType::SBT_TRANSPARENT_COLOUR);
Ogre::OverlayContainer* panel = static_cast<Ogre::OverlayContainer*>(overlayManager->createOverlayElement("Panel", "PanelName"));
Ogre::OverlayContainer* panel = static_cast<Ogre::OverlayContainer*>(m_overlayManager->createOverlayElement("Panel", "TopMenuBarPanel"));
panel->setMetricsMode(Ogre::GMM_PIXELS);
panel->setPosition(0,0);
panel->setDimensions(320, 24);
panel->setDimensions(128 * 5, 20);
panel->setMaterial(material);
Ogre::TextAreaOverlayElement* textArea = static_cast<Ogre::TextAreaOverlayElement*>(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::ColourValue text_color = Ogre::ColourValue(0.25, 0.25, 0.25);
Ogre::Overlay* overlay = overlayManager->create("OverlayName");
Ogre::TextAreaOverlayElement* toolsTextArea = static_cast<Ogre::TextAreaOverlayElement*>(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarTools"));
toolsTextArea->setMetricsMode(Ogre::GMM_PIXELS);
toolsTextArea->setPosition(0, 0);
toolsTextArea->setDimensions(128, 24);
toolsTextArea->setCaption("Tools");
toolsTextArea->setCharHeight(24);
toolsTextArea->setFontName("ComicSans");
toolsTextArea->setColour(text_color);
Ogre::TextAreaOverlayElement* insertTextArea = static_cast<Ogre::TextAreaOverlayElement*>(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarInsert"));
insertTextArea->setMetricsMode(Ogre::GMM_PIXELS);
insertTextArea->setPosition(128, 0);
insertTextArea->setDimensions(128, 24);
insertTextArea->setCaption("Insert");
insertTextArea->setCharHeight(24);
insertTextArea->setFontName("ComicSans");
insertTextArea->setColour(text_color);
Ogre::TextAreaOverlayElement* fullscreenTextArea = static_cast<Ogre::TextAreaOverlayElement*>(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarFullscreen"));
fullscreenTextArea->setMetricsMode(Ogre::GMM_PIXELS);
fullscreenTextArea->setPosition(128*2, 0);
fullscreenTextArea->setDimensions(128, 24);
fullscreenTextArea->setCaption("Fullscreen");
fullscreenTextArea->setCharHeight(24);
fullscreenTextArea->setFontName("ComicSans");
fullscreenTextArea->setColour(text_color);
Ogre::TextAreaOverlayElement* helpTextArea = static_cast<Ogre::TextAreaOverlayElement*>(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarHelp"));
helpTextArea->setMetricsMode(Ogre::GMM_PIXELS);
helpTextArea->setPosition(128*3, 0);
helpTextArea->setDimensions(128, 24);
helpTextArea->setCaption("Help...");
helpTextArea->setCharHeight(24);
helpTextArea->setFontName("ComicSans");
helpTextArea->setColour(text_color);
Ogre::TextAreaOverlayElement* exitTextArea = static_cast<Ogre::TextAreaOverlayElement*>(m_overlayManager->createOverlayElement("TextArea", "TopMenuBarExit"));
exitTextArea->setMetricsMode(Ogre::GMM_PIXELS);
exitTextArea->setPosition(128*4, 0);
exitTextArea->setDimensions(128, 24);
exitTextArea->setCaption("Exit");
exitTextArea->setCharHeight(24);
exitTextArea->setFontName("ComicSans");
exitTextArea->setColour(text_color);
panel->addChild(toolsTextArea);
panel->addChild(insertTextArea);
panel->addChild(fullscreenTextArea);
panel->addChild(helpTextArea);
panel->addChild(exitTextArea);
m_debugText = static_cast<Ogre::TextAreaOverlayElement*>(m_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(16);
m_debugText->setFontName("ComicSans");
m_debugText->setColour(Ogre::ColourValue(0.5f,0.f,0.5f));
panel->addChild(m_debugText);
m_playerPanel = static_cast<Ogre::OverlayContainer*>(m_overlayManager->createOverlayElement("Panel", "PlayerListPanel"));
m_playerPanel->setMetricsMode(Ogre::GMM_PIXELS);
m_playerPanel->setDimensions(128, 20);
m_playerPanel->setMaterial(material);
m_playerList = static_cast<Ogre::TextAreaOverlayElement*>(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);
panel->addChild(textArea);
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);
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));
}
}
}

View File

@ -1,6 +1,7 @@
#include <App/Script/ReflectionProperty.hpp>
#include <App/V8/Tree/Instance.hpp>
#include <App/CoordinateFrame.hpp>
#include <App/BrickColor.hpp>
#include <Helpers/Strings.hpp>
#include <format>
@ -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("???");
}

View File

@ -1,4 +1,6 @@
#include <App/V8/DataModel/Light.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/World/World.hpp>
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<PartInstance*>(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);
}
}

View File

@ -9,6 +9,12 @@ 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"));
getNode()->attachObject(getObject());
updateMatrix();
}
@ -17,6 +23,17 @@ 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->setMaterial(BrickColor::material(m_brickColor));
subentity->getMaterial()->setShininess(64);
}
}
void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node)
@ -33,8 +50,17 @@ 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();
}
void PartInstance::addProperties(std::vector<ReflectionProperty>& properties)
@ -44,6 +70,18 @@ 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); ) },
{ 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);

View File

@ -8,81 +8,69 @@ 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(512,512,512));
m_geom->setCastShadows(true);
break;
}
}
void Workspace::onChildAdded(Instance* childAdded)
void Workspace::onDescendantAdded(Instance* childAdded)
{
m_geomDirty = true;
PartInstance* part = dynamic_cast<PartInstance*>(childAdded);
if(part)
{
Ogre::SceneNode* child_node = childAdded->getNode();
switch(m_batchMode)
{
case BATCH_INSTANCED:
{
Ogre::Entity* childEntity = (Ogre::Entity*)childAdded->getObject();
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity(childEntity->getSubEntity(0)->getMaterialName());
replica->setPosition(part->getPosition());
replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize());
childAdded->setObject(replica);
}
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<PartInstance*>(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

View File

@ -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)

View File

@ -4,6 +4,7 @@
#include <App/GUI/SelectionBox.hpp>
#include <App/Humanoid/Humanoid.hpp>
#include <App/InputManager.hpp>
#include <Network/Player.hpp>
#include <stdexcept>
#include <pugixml.hpp>
@ -24,6 +25,8 @@ namespace RNR
m_instanceFactory->registerInstance("Workspace", InstanceFactory::instanceBuilder<Workspace>);
m_instanceFactory->registerInstance("Humanoid", InstanceFactory::instanceBuilder<Humanoid>);
m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder<RunService>);
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
m_ogreRoot = ogre;
m_ogreSceneManager = ogreSceneManager;
@ -31,8 +34,9 @@ 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();
m_tmb = new TopMenuBar(this);
Camera* start_cam = new Camera();
start_cam->setParent(m_workspace);
@ -70,9 +74,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 +115,7 @@ namespace RNR
s.instance->deserializeXmlProperty(prop);
}
s.instance->setParent(s.parent);
if(s.instance->getClassName() == "Model")
{
ModelInstance* m = (ModelInstance*)s.instance;
@ -129,6 +134,7 @@ namespace RNR
{
if(m_inputManager)
m_inputManager->frame();
m_tmb->frame();
}
double World::step(float timestep)

View File

@ -0,0 +1,25 @@
#include <Network/Player.hpp>
#include <App/V8/World/World.hpp>
namespace RNR
{
Player::Player()
{
setName("Player");
setParent(world->getDatamodel()->getService("Players"));
m_character = NULL;
}
void Player::addProperties(std::vector<ReflectionProperty>& 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)));
}
}

View File

@ -0,0 +1,34 @@
#include <Network/Players.hpp>
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<ReflectionProperty>& 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)));
}
}

View File

@ -3,7 +3,7 @@
[![Star](https://img.shields.io/github/stars/lrre-foss/RNR?style=social)](https://github.com/lrre-foss/RNR/stargazers)
[Discord](https://discord.gg/89WagAUr)
RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining fully compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries.
RNR (**R**NR's **N**ot **R**oblox) is a project that aims to recreate the look and feel of classic Roblox with new features while remaining partially compatible with clients from that era. It is built upon an engine that closely resembles Roblox's own at the time, referencing disassemblies of legacy client binaries.
Interested in contributing? [Feel free to make a pull request!](https://github.com/lrre-foss/RNR/pulls)
@ -13,7 +13,6 @@ There are several goals that RNR seeks to accomplish, them being;
- Easy-to-use (simple CLI options to launch and host games, as well as a level editor with a modern UI)
- Fully compatible with Roblox versions up to 0.3.744.0 (dated April 2008) in areas such as hosting, joining, levels, etc.
- Incorporates all the various facets of the Roblox engine, plus a little bit extra (e.g. a network replication whitelist, fancy shader support, etc.)
- Made using clean-room reverse engineering
- Uses Roblox's [Luau](https://luau-lang.org/) as its scripting language while remaining fully compatible with classic Roblox scripts written using Lua 5.1
- As free and open-source as possible (with client code licensed under the GPL and the engine itself being released into the public domain, void of any copyright)
- Patching all the security vulnerabilities and fixing bugs/inefficiencies that legacy Roblox clients had