Merge branch 'trunk' of https://github.com/lrre-foss/rnr into trunk
|
|
@ -17,13 +17,13 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
name: Clone repository
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: msys2/setup-msys2@v2
|
||||
name: Set up MSYS2 and install required packages
|
||||
|
||||
- name: Set up MSYS2 and install required packages
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.sys }}
|
||||
install: >-
|
||||
|
|
@ -34,6 +34,7 @@ jobs:
|
|||
mingw-w64-${{ matrix.env }}-pugixml
|
||||
mingw-w64-${{ matrix.env }}-ogre3d
|
||||
mingw-w64-${{ matrix.env }}-qt6
|
||||
mingw-w64-${{ matrix.env }}-bullet
|
||||
|
||||
- name: Generate Ninja build files
|
||||
run: cmake -G Ninja -B build -DCI=ON -DCMAKE_BUILD_TYPE=${{ matrix.configuration == 'Release' && 'MinSizeRel' || matrix.configuration }} .
|
||||
|
|
@ -58,7 +59,7 @@ jobs:
|
|||
run: mkdir build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/Main/* build/dist/shaders && cp -R /${{ matrix.sys }}/share/OGRE/Media/RTShaderLib/* build/dist/shaders
|
||||
|
||||
- name: Add additional runtime dependencies
|
||||
run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "clang64" | xargs -I '{}' cp -v '{}' build/dist
|
||||
run: ldd build/dist/*.exe | grep "=> /" | awk '{print $3}' | grep "${{ matrix.sys }}" | xargs -I '{}' cp -v '{}' build/dist
|
||||
|
||||
- name: Set output variables
|
||||
id: vars
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ add_compile_options(-Wno-attributes -Wno-return-type) # Ignore warnings generate
|
|||
find_package(Boost REQUIRED)
|
||||
find_package(OGRE REQUIRED COMPONENTS Bites CONFIG)
|
||||
find_package(pugixml REQUIRED)
|
||||
find_package(Bullet CONFIG REQUIRED)
|
||||
set(RNR_BULLET_LIBRARIES LinearMath Bullet3Common BulletDynamics BulletSoftBody BulletCollision BulletInverseDynamics)
|
||||
|
||||
add_subdirectory(Projects)
|
||||
|
||||
if(CI AND UNIX)
|
||||
file(COPY ${OGRE_MEDIA_DIR}/Main/ DESTINATION ${CMAKE_BINARY_DIR}/shaders)
|
||||
file(COPY ${OGRE_MEDIA_DIR}/ShadowVolume/ 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)
|
||||
endif()
|
||||
|
|
@ -16,7 +16,6 @@ material materials/partinstanced
|
|||
|
||||
rtshader_system
|
||||
{
|
||||
transform_stage instanced
|
||||
lighting_stage per_pixel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 6.4 KiB |
|
|
@ -34,6 +34,7 @@ namespace RNR
|
|||
Ogre::SceneManager* ogreSceneManager;
|
||||
Ogre::Camera* ogreCamera;
|
||||
Ogre::Viewport* ogreViewport;
|
||||
Ogre::Light* ogreSceneLight;
|
||||
Ogre::RTShader::ShaderGenerator* ogreShaderGen;
|
||||
|
||||
QCursor cursor;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
#include <OgreWidget.hpp>
|
||||
#include <QApplication>
|
||||
#include <filesystem>
|
||||
|
||||
#include <OGRE/Bites/OgreSGTechniqueResolverListener.h>
|
||||
#include <OGRE/OgreDefaultDebugDrawer.h>
|
||||
#include <OGRE/Overlay/OgreOverlaySystem.h>
|
||||
#include <OGRE/Overlay/OgreOverlayManager.h>
|
||||
#include <OGRE/Overlay/OgreFontManager.h>
|
||||
#include <App/V8/DataModel/Lighting.hpp>
|
||||
|
||||
#ifdef __unix__
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
|
@ -70,6 +72,11 @@ namespace RNR
|
|||
if(Ogre::RTShader::ShaderGenerator::initialize())
|
||||
{
|
||||
ogreShaderGen = Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
|
||||
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
|
||||
std::filesystem::create_directory("ShaderCache");
|
||||
}
|
||||
|
||||
ogreShaderGen->setShaderCachePath("ShaderCache/");
|
||||
ogreShaderGen->addSceneManager(ogreSceneManager);
|
||||
|
||||
|
|
@ -90,19 +97,19 @@ namespace RNR
|
|||
pFont->setTrueTypeSize(16);
|
||||
pFont->load();
|
||||
|
||||
ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_ADDITIVE);
|
||||
ogreSceneManager->setShadowTechnique(Ogre::ShadowTechnique::SHADOWTYPE_STENCIL_MODULATIVE);
|
||||
ogreSceneManager->setShadowFarDistance(500.f);
|
||||
|
||||
Ogre::Light* light = ogreSceneManager->createLight("SunLight");
|
||||
ogreSceneLight = ogreSceneManager->createLight("SunLight");
|
||||
Ogre::SceneNode* lightNode = ogreSceneManager->getRootSceneNode()->createChildSceneNode();
|
||||
lightNode->setPosition(0, 10, 15);
|
||||
lightNode->setDirection(-0.25, -0.5, -0.5);
|
||||
lightNode->attachObject(light);
|
||||
lightNode->attachObject(ogreSceneLight);
|
||||
|
||||
light->setCastShadows(true);
|
||||
light->setDiffuseColour(0.9, 0.9, 1.0);
|
||||
light->setSpecularColour(1.0, 1.0, 1.0);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
ogreSceneLight->setCastShadows(true);
|
||||
ogreSceneLight->setDiffuseColour(0.9, 0.9, 1.0);
|
||||
ogreSceneLight->setSpecularColour(1.0, 1.0, 1.0);
|
||||
ogreSceneLight->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
|
||||
Ogre::MaterialManager::getSingletonPtr()->reloadAll();
|
||||
Ogre::MaterialManager::getSingletonPtr()->load("sky/null_plainsky512", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
|
@ -126,6 +133,21 @@ namespace RNR
|
|||
ogreCamera->getParentSceneNode()->setPosition(cam->getCFrame().getPosition());
|
||||
ogreCamera->getParentSceneNode()->setOrientation(Ogre::Quaternion(cam->getCFrame().getRotation()));
|
||||
}
|
||||
|
||||
RNR::Lighting* lighting = (RNR::Lighting*)world->getDatamodel()->getService("Lighting");
|
||||
if(lighting)
|
||||
{
|
||||
Ogre::Vector3 clearColor = lighting->getClearColor();
|
||||
ogreViewport->setBackgroundColour(Ogre::ColourValue(clearColor.x, clearColor.y, clearColor.z));
|
||||
Ogre::Vector3 shadowColor = lighting->getShadowColor();
|
||||
ogreSceneManager->setShadowColour(Ogre::ColourValue(shadowColor.x, shadowColor.y, shadowColor.z));
|
||||
Ogre::Vector3 topAmbient = lighting->getTopAmbient();
|
||||
ogreSceneLight->setDiffuseColour(Ogre::ColourValue(topAmbient.x, topAmbient.y, topAmbient.z));
|
||||
Ogre::Vector3 bottomAmbient = lighting->getBottomAmbient();
|
||||
ogreSceneManager->setAmbientLight(Ogre::ColourValue(bottomAmbient.x, bottomAmbient.y, bottomAmbient.z));
|
||||
Ogre::Vector3 spotLight = lighting->getSpotLight();
|
||||
ogreSceneLight->setSpecularColour(Ogre::ColourValue(spotLight.x, spotLight.y, spotLight.z));
|
||||
}
|
||||
|
||||
if(isVisible())
|
||||
ogreRoot->renderOneFrame(this->delta);
|
||||
|
|
@ -198,7 +220,11 @@ namespace RNR
|
|||
|
||||
void OgreWidget::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
delete world;
|
||||
|
||||
ogreWindow->destroy();
|
||||
ogreRoot->destroySceneManager(ogreSceneManager);
|
||||
ogreRoot->shutdown();
|
||||
}
|
||||
|
||||
QPaintEngine* OgreWidget::paintEngine() const
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
|
||||
std::filesystem::create_directory("ShaderCache");
|
||||
}
|
||||
|
||||
QApplication app(argc, argv);
|
||||
MainWindow window = MainWindow();
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ void MainWindow::widgetItemPrepare(QTreeWidgetItem* item, RNR::Instance* instanc
|
|||
{
|
||||
QString icon_path;
|
||||
icon_path = "content/textures/studio/icons/";
|
||||
icon_path += instance->getClassName();
|
||||
icon_path += instance->getExplorerIcon();
|
||||
icon_path += ".png";
|
||||
QIcon icon;
|
||||
if(QFile::exists(icon_path))
|
||||
|
|
@ -138,7 +138,10 @@ void MainWindow::playSolo()
|
|||
|
||||
RNR::Players* players = (RNR::Players*)this->ogreWidget->world->getDatamodel()->getService("Players");
|
||||
RNR::Player* player = players->createLocalPlayer(0);
|
||||
if(!player)
|
||||
return;
|
||||
player->setName(QInputDialog::getText(this, "Player Name", "Enter your player name").toLocal8Bit().data());
|
||||
player->loadCharacter();
|
||||
|
||||
updateTree(ogreWidget->world->getDatamodel());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ void PropertyViewer::view(RNR::Instance* instance)
|
|||
QImage image;
|
||||
QString icon_path;
|
||||
icon_path = "content/textures/studio/icons/";
|
||||
icon_path += instance_ref->getClassName();
|
||||
icon_path += instance_ref->getExplorerIcon();
|
||||
icon_path += ".png";
|
||||
if(QFile::exists(icon_path))
|
||||
image = QImage(icon_path);
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (!std::filesystem::is_directory("ShaderCache") || !std::filesystem::exists("ShaderCache")) {
|
||||
std::filesystem::create_directory("ShaderCache");
|
||||
}
|
||||
|
||||
QSurfaceFormat format;
|
||||
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ add_library(Engine STATIC
|
|||
Header/App/V8/DataModel/ForceField.hpp
|
||||
Header/App/V8/DataModel/PartInstance.hpp
|
||||
Header/App/V8/DataModel/Light.hpp
|
||||
Header/App/V8/DataModel/Lighting.hpp
|
||||
Header/App/V8/DataModel/FaceInstance.hpp
|
||||
Header/App/V8/DataModel/RunService.hpp
|
||||
Header/App/V8/DataModel/Workspace.hpp
|
||||
|
|
@ -48,6 +49,7 @@ add_library(Engine STATIC
|
|||
Source/App/V8/DataModel/ForceField.cpp
|
||||
Source/App/V8/DataModel/PartInstance.cpp
|
||||
Source/App/V8/DataModel/Light.cpp
|
||||
Source/App/V8/DataModel/Lighting.cpp
|
||||
Source/App/V8/DataModel/FaceInstance.cpp
|
||||
Source/App/V8/DataModel/RunService.cpp
|
||||
Source/App/V8/DataModel/Workspace.cpp
|
||||
|
|
@ -65,5 +67,7 @@ add_library(Engine STATIC
|
|||
Source/Rendering/Adorn.cpp
|
||||
)
|
||||
|
||||
target_include_directories(Engine PUBLIC ${BOOST_INCLUDE_DIRS} Header/)
|
||||
target_link_libraries(Engine PUBLIC ${BOOST_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM)
|
||||
target_include_directories(Engine PUBLIC ${Boost_INCLUDE_DIRS} ${BULLET_ROOT_DIR}/${BULLET_INCLUDE_DIR} Header/)
|
||||
target_compile_definitions(Engine PUBLIC ${BULLET_DEFINITIONS})
|
||||
target_link_directories(Engine PUBLIC ${Bullet_DIR}/${BULLET_ROOT_DIR}/${BULLET_LIBRARY_DIRS})
|
||||
target_link_libraries(Engine PUBLIC ${Boost_LIBRARIES} ${RNR_BULLET_LIBRARIES} pugixml OgreBites Luau.Analysis Luau.Ast Luau.Compiler Luau.VM)
|
||||
|
|
@ -20,6 +20,7 @@ namespace RNR
|
|||
PartInstance* getTorso();
|
||||
PartInstance* getHead();
|
||||
|
||||
void inputFrame(float dx, float dy);
|
||||
void createHealthBar();
|
||||
|
||||
float getHealth() { return m_health; };
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ namespace RNR
|
|||
{
|
||||
World* m_world;
|
||||
std::vector<int> scancodes_down;
|
||||
float m_mouseDX;
|
||||
float m_mouseDY;
|
||||
protected:
|
||||
MouseState state;
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace RNR
|
|||
private:
|
||||
CoordinateFrame m_cframe;
|
||||
CoordinateFrame m_focus;
|
||||
Ogre::Radian m_yaw;
|
||||
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
|
||||
virtual void addProperties(std::vector<ReflectionProperty>& properties);
|
||||
public:
|
||||
|
|
@ -24,6 +25,7 @@ namespace RNR
|
|||
virtual std::string getClassName() { return "Camera"; }
|
||||
CoordinateFrame& getCFrame() { return m_cframe; };
|
||||
CoordinateFrame& getFocus() { return m_focus; }
|
||||
Ogre::Radian getYaw() { return m_yaw; }
|
||||
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
|
||||
void setFocus(CoordinateFrame focus) { m_focus = focus; }
|
||||
bool zoom(float distance);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
#include <App/V8/Tree/Instance.hpp>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
class Lighting : public Instance
|
||||
{
|
||||
float m_brightness;
|
||||
float m_geographicLatitude;
|
||||
|
||||
Ogre::Vector3 m_bottomAmbient;
|
||||
Ogre::Vector3 m_topAmbient;
|
||||
Ogre::Vector3 m_spotLight;
|
||||
Ogre::Vector3 m_shadowColor;
|
||||
Ogre::Vector3 m_clearColor;
|
||||
|
||||
virtual void addProperties(std::vector<ReflectionProperty>& properties);
|
||||
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
|
||||
public:
|
||||
Lighting();
|
||||
|
||||
void setBottomAmbient(Ogre::Vector3 color) { m_bottomAmbient = color; }
|
||||
Ogre::Vector3 getBottomAmbient() { return m_bottomAmbient; }
|
||||
void setTopAmbient(Ogre::Vector3 color) { m_topAmbient = color; }
|
||||
Ogre::Vector3 getTopAmbient() { return m_topAmbient; }
|
||||
void setSpotLight(Ogre::Vector3 color) { m_spotLight = color; }
|
||||
Ogre::Vector3 getSpotLight() { return m_spotLight; }
|
||||
void setShadowColor(Ogre::Vector3 color) { m_shadowColor = color; }
|
||||
Ogre::Vector3 getShadowColor() { return m_shadowColor; }
|
||||
void setClearColor(Ogre::Vector3 color) { m_clearColor = color; }
|
||||
Ogre::Vector3 getClearColor() { return m_clearColor; }
|
||||
|
||||
virtual std::string getClassName() { return "Lighting"; }
|
||||
virtual std::string getExplorerIcon() { return "PointLight"; }
|
||||
};
|
||||
}
|
||||
|
|
@ -13,8 +13,10 @@ namespace RNR
|
|||
|
||||
enum WorkspaceBatchingMode
|
||||
{
|
||||
BATCH_DONT,
|
||||
BATCH_INSTANCED,
|
||||
BATCH_STATIC_GEOMETRY,
|
||||
BATCH_DYNAMIC_RENDERABLE,
|
||||
};
|
||||
|
||||
class Workspace : public ModelInstance
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
|
||||
#include <OGRE/Ogre.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
|
@ -36,7 +37,7 @@ namespace RNR
|
|||
|
||||
public:
|
||||
Instance();
|
||||
~Instance();
|
||||
virtual ~Instance();
|
||||
|
||||
virtual std::vector<ReflectionProperty> getProperties();
|
||||
void deserializeXmlProperty(pugi::xml_node prop); // TODO: eventually replace this with a method that uses getProperties
|
||||
|
|
@ -61,6 +62,7 @@ namespace RNR
|
|||
RNR::Instance* getParent() { return this->m_parent; };
|
||||
std::string getName() { return this->m_name; };
|
||||
virtual std::string getClassName() { return "Instance"; }
|
||||
virtual std::string getExplorerIcon() { return getClassName(); }
|
||||
|
||||
void setParent(RNR::Instance* newParent);
|
||||
void setName(std::string name);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace RNR
|
|||
|
||||
CoordinateFrame& getCFrame() { return m_cframe; };
|
||||
void setCFrame(CoordinateFrame cframe) { m_cframe = cframe; };
|
||||
Ogre::Vector3 relativePositionTo(PVInstance* point);
|
||||
virtual std::string getClassName() { return "PVInstance"; }
|
||||
|
||||
Ogre::Vector3 getPosition() { return m_cframe.getPosition(); }
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#include <OGRE/Ogre.h>
|
||||
#include <pugixml.hpp>
|
||||
#include <stack>
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
|
|
@ -28,6 +31,7 @@ namespace RNR
|
|||
private:
|
||||
std::map<std::string, Instance*> m_refs;
|
||||
std::stack<WorldUndeserialized> m_undeserialized;
|
||||
btDiscreteDynamicsWorld* m_dynamicsWorld;
|
||||
DataModel* m_datamodel;
|
||||
Workspace* m_workspace;
|
||||
RunService* m_runService;
|
||||
|
|
@ -52,6 +56,7 @@ namespace RNR
|
|||
double step(float timestep);
|
||||
void update();
|
||||
|
||||
btDiscreteDynamicsWorld* getDynamicsWorld() { return m_dynamicsWorld; }
|
||||
float getLastDelta() { return m_lastDelta; }
|
||||
DataModel* getDatamodel() { return m_datamodel; }
|
||||
void setInputManager(IInputManager* inputManager) { m_inputManager = inputManager; }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <cstddef>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ namespace RNR
|
|||
{
|
||||
public:
|
||||
static Ogre::Vector3 getVector3(pugi::xml_node node);
|
||||
static Ogre::Vector3 getColor(pugi::xml_node node);
|
||||
static CoordinateFrame getCFrame(pugi::xml_node node);
|
||||
};
|
||||
}
|
||||
|
|
@ -10,10 +10,13 @@ namespace RNR
|
|||
int m_userId;
|
||||
public:
|
||||
Player();
|
||||
|
||||
void initLocalPlayer();
|
||||
void loadCharacter();
|
||||
|
||||
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);
|
||||
virtual void addProperties(std::vector<ReflectionProperty>& properties);
|
||||
};
|
||||
}
|
||||
|
|
@ -115,6 +115,7 @@ namespace RNR
|
|||
void TopMenuBar::frame()
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
btDiscreteDynamicsWorld* dynamicsWorld = m_world->getDynamicsWorld();
|
||||
|
||||
char debugtext[512];
|
||||
char render_debugtext[255];
|
||||
|
|
@ -127,7 +128,11 @@ namespace RNR
|
|||
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());
|
||||
snprintf(debugtext, 512, "Render\nLast DT = %f\n%s\n\nPhysics\n%i objects, %i constraints",
|
||||
m_world->getLastDelta(),
|
||||
render_debugtext,
|
||||
m_world->getOgreSceneManager(),
|
||||
dynamicsWorld->getNumCollisionObjects(), dynamicsWorld->getNumConstraints());
|
||||
m_debugText->setCaption(debugtext);
|
||||
|
||||
Players* players = (Players*)m_world->getDatamodel()->getService("Players");
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <App/V8/World/World.hpp>
|
||||
#include <App/InputManager.hpp>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
Humanoid::Humanoid()
|
||||
{
|
||||
//
|
||||
setName("Humanoid");
|
||||
|
||||
m_maxHealth = 100.f;
|
||||
m_health = 100.f;
|
||||
}
|
||||
|
||||
Humanoid::~Humanoid()
|
||||
|
|
@ -42,13 +46,38 @@ namespace RNR
|
|||
}
|
||||
if(getNode())
|
||||
world->getOgreSceneManager()->destroySceneNode(getNode());
|
||||
|
||||
setNode(world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode());
|
||||
Ogre::BillboardSet* healthBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidHealth" + getParent()->getName());
|
||||
Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(100, 0, 200));
|
||||
getNode()->attachObject(healthBarSet);
|
||||
getNode()->setPosition(getHead()->getPosition());
|
||||
healthBarSet->setBillboardType(Ogre::BillboardType::BBT_PERPENDICULAR_COMMON);
|
||||
healthBarSet->setDebugDisplayEnabled(true);
|
||||
//Ogre::Billboard* healthBarBillboard = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(1, 0, 0, 1));
|
||||
Ogre::Billboard* healthBarBillboardFilled = healthBarSet->createBillboard(Ogre::Vector3(0, 2, 0), Ogre::ColourValue(0, 1, 0, 1));
|
||||
float healthBarScale = 0.5f;
|
||||
//healthBarBillboard->setDimensions(5 * healthBarScale, 1 * healthBarScale);
|
||||
healthBarBillboardFilled->setDimensions((m_health / m_maxHealth) * 5.f * healthBarScale, 1 * healthBarScale);
|
||||
healthBarSet->setCastShadows(true);
|
||||
|
||||
printf("Humanoid::createHealthBar: WIP");
|
||||
Ogre::BillboardSet* nameBarSet = world->getOgreSceneManager()->createBillboardSet("HumanoidName" + getParent()->getName());
|
||||
nameBarSet->setDebugDisplayEnabled(true);
|
||||
Ogre::FontPtr comic = Ogre::FontManager::getSingletonPtr()->getByName("ComicSans");
|
||||
if(!comic)
|
||||
printf("Humanoid::createHealthBar: comic == NULL\n");
|
||||
comic->putText(nameBarSet, getParent()->getName(), 1);
|
||||
int num_billboards = nameBarSet->getNumBillboards();
|
||||
for(int i = 0; i < num_billboards; i++)
|
||||
{
|
||||
Ogre::Billboard* chara = nameBarSet->getBillboard(i);
|
||||
Ogre::Vector3 chara_pos = chara->getPosition();
|
||||
chara_pos.y += 2 + healthBarScale;
|
||||
chara->setPosition(chara_pos);
|
||||
}
|
||||
getNode()->attachObject(healthBarSet);
|
||||
getNode()->attachObject(nameBarSet);
|
||||
getNode()->setPosition(getHead()->getPosition());
|
||||
getNode()->setOrientation(getHead()->getRotation());
|
||||
|
||||
printf("Humanoid::createHealthBar: WIP\n");
|
||||
}
|
||||
|
||||
void Humanoid::deserializeProperty(char* prop_name, pugi::xml_node prop)
|
||||
|
|
@ -63,6 +92,58 @@ namespace RNR
|
|||
}
|
||||
}
|
||||
|
||||
void Humanoid::inputFrame(float dx, float dy)
|
||||
{
|
||||
IInputManager* inputManager = world->getInputManager();
|
||||
PartInstance* torso = getTorso();
|
||||
Camera* camera = world->getWorkspace()->getCurrentCamera();
|
||||
if(!torso)
|
||||
{
|
||||
printf("Humanoid::inputFrame: no torso\n");
|
||||
return;
|
||||
}
|
||||
if(inputManager)
|
||||
{
|
||||
Ogre::Matrix3 camera_rotation;
|
||||
camera_rotation.FromEulerAnglesYXZ(camera->getYaw(), Ogre::Radian(0), Ogre::Radian(0)); // we only want yaw because otherwise the movement target will go through the ground/in the air
|
||||
Ogre::Quaternion direction = torso->getRotation();
|
||||
Ogre::Quaternion new_direction = Ogre::Quaternion::nlerp(0.5f, direction, camera_rotation);
|
||||
float forward = 0;
|
||||
|
||||
if(inputManager->isKeyDown('W'))
|
||||
forward = 16;
|
||||
|
||||
Ogre::Vector3 move = Ogre::Vector3(0, 0, -forward);
|
||||
move = direction * move;
|
||||
move *= world->getLastDelta();
|
||||
|
||||
bool move_valid = true;
|
||||
|
||||
// TODO: collision checking
|
||||
|
||||
if(!move_valid)
|
||||
return;
|
||||
|
||||
for(auto& child : *getParent()->getChildren())
|
||||
{
|
||||
PartInstance* bp = dynamic_cast<PartInstance*>(child);
|
||||
if(bp)
|
||||
{
|
||||
Ogre::Vector3 bp_p = bp->getPosition();
|
||||
bp_p += move;
|
||||
bp->getCFrame().setPosition(bp_p);
|
||||
Ogre::Matrix3 new_rotation_matrix;
|
||||
new_direction.ToRotationMatrix(new_rotation_matrix);
|
||||
bp->getCFrame().setRotation(new_rotation_matrix);
|
||||
bp->updateMatrix();
|
||||
world->getWorkspace()->setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
camera->getCFrame().setPosition(camera->getCFrame().getPosition() + move);
|
||||
}
|
||||
}
|
||||
|
||||
void Humanoid::addProperties(std::vector<ReflectionProperty>& properties)
|
||||
{
|
||||
ReflectionProperty _properties[] = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <App/InputManager.hpp>
|
||||
#include <App/V8/DataModel/Camera.hpp>
|
||||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace RNR
|
||||
|
|
@ -9,8 +10,7 @@ namespace RNR
|
|||
state.mouse_primary = false;
|
||||
state.mouse_secondary = false;
|
||||
state.mouse_middle = false;
|
||||
state.mouse_scroll = 0;
|
||||
}
|
||||
state.mouse_scroll = 0; }
|
||||
|
||||
void IInputManager::keyDown(int scancode)
|
||||
{
|
||||
|
|
@ -43,14 +43,14 @@ namespace RNR
|
|||
{
|
||||
if(m_world)
|
||||
{
|
||||
float xd = x * m_world->getLastDelta();
|
||||
float yd = y * m_world->getLastDelta();
|
||||
m_mouseDX = x * m_world->getLastDelta();
|
||||
m_mouseDY = y * m_world->getLastDelta();
|
||||
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera && state.mouse_secondary)
|
||||
{
|
||||
camera->cameraFrame(xd, yd);
|
||||
camera->cameraFrame(m_mouseDX, m_mouseDY);
|
||||
|
||||
resetMouse();
|
||||
}
|
||||
|
|
@ -59,10 +59,29 @@ namespace RNR
|
|||
|
||||
void IInputManager::frame()
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera)
|
||||
camera->cameraFrame(0, 0, false); // update camera position
|
||||
Players* players = (Players*)m_world->getDatamodel()->getService("Players");
|
||||
Player* localPlayer = players->getLocalPlayer();
|
||||
if(localPlayer)
|
||||
{
|
||||
ModelInstance* character = localPlayer->getCharacter();
|
||||
if(character)
|
||||
{
|
||||
Humanoid* humanoid = (Humanoid*)character->findFirstChildOfType("Humanoid");
|
||||
if(humanoid)
|
||||
{
|
||||
humanoid->inputFrame(m_mouseDX, m_mouseDY);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Workspace* workspace = m_world->getWorkspace();
|
||||
Camera* camera = workspace->getCurrentCamera();
|
||||
if(camera)
|
||||
camera->cameraFrame(0, 0, false); // update camera position
|
||||
}
|
||||
m_mouseDX = 0;
|
||||
m_mouseDY = 0;
|
||||
}
|
||||
|
||||
void IInputManager::mousePrimaryState(bool down)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <App/CoordinateFrame.hpp>
|
||||
#include <App/BrickColor.hpp>
|
||||
#include <Helpers/Strings.hpp>
|
||||
#include <format>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <App/V8/DataModel/Camera.hpp>
|
||||
#include <App/V8/World/World.hpp>
|
||||
#include <App/InputManager.hpp>
|
||||
#include <Network/Players.hpp>
|
||||
#include <Helpers/XML.hpp>
|
||||
|
||||
namespace RNR
|
||||
|
|
@ -40,6 +41,7 @@ namespace RNR
|
|||
|
||||
pitch = old_pitch + pitch;
|
||||
yaw = old_yaw - yaw;
|
||||
m_yaw = yaw;
|
||||
|
||||
Ogre::Matrix3 rotation;
|
||||
rotation.FromEulerAnglesYXZ(yaw, pitch, Ogre::Radian(0));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
#include <App/V8/DataModel/Lighting.hpp>
|
||||
#include <Helpers/XML.hpp>
|
||||
|
||||
namespace RNR
|
||||
{
|
||||
Lighting::Lighting()
|
||||
{
|
||||
setName("Lighting");
|
||||
setClearColor(Ogre::Vector3(255.f/255.f,255.f/255.f,255.f/255.f));
|
||||
setShadowColor(Ogre::Vector3(127.f/255.f,127.f/255.f,127.f/255.f));
|
||||
setBottomAmbient(Ogre::Vector3(122.f/255.f,134.f/255.f,120.f/255.f));
|
||||
setTopAmbient(Ogre::Vector3(209.f/255.f,208.f/255.f,217.f/255.f));
|
||||
setSpotLight(Ogre::Vector3(191.f/255.f,191.f/255.f,191.f/255.f));
|
||||
}
|
||||
|
||||
void Lighting::deserializeProperty(char* prop_name, pugi::xml_node node)
|
||||
{
|
||||
if(prop_name == std::string("ClearColor"))
|
||||
{
|
||||
setClearColor(XML::getColor(node));
|
||||
}
|
||||
else if(prop_name == std::string("ShadowColor"))
|
||||
{
|
||||
setShadowColor(XML::getColor(node));
|
||||
}
|
||||
else if(prop_name == std::string("SpotLightV9"))
|
||||
{
|
||||
setSpotLight(XML::getColor(node));
|
||||
}
|
||||
else if(prop_name == std::string("BottomAmbientV9"))
|
||||
{
|
||||
setBottomAmbient(XML::getColor(node));
|
||||
}
|
||||
else if(prop_name == std::string("TopAmbientV9"))
|
||||
{
|
||||
setTopAmbient(XML::getColor(node));
|
||||
}
|
||||
}
|
||||
|
||||
void Lighting::addProperties(std::vector<ReflectionProperty>& properties)
|
||||
{
|
||||
ReflectionProperty _properties[] = {
|
||||
{ this, std::string("BottomAmbientV9"), std::string(""),
|
||||
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
|
||||
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_bottomAmbient; ),
|
||||
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setBottomAmbient(*(Ogre::Vector3*)value); ) },
|
||||
{ this, std::string("TopAmbientV9"), std::string(""),
|
||||
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
|
||||
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_topAmbient; ),
|
||||
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setTopAmbient(*(Ogre::Vector3*)value); ) },
|
||||
{ this, std::string("ClearColor"), std::string(""),
|
||||
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
|
||||
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_clearColor; ),
|
||||
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setClearColor(*(Ogre::Vector3*)value); ) },
|
||||
{ this, std::string("ShadowColor"), std::string(""),
|
||||
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
|
||||
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_shadowColor; ),
|
||||
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setShadowColor(*(Ogre::Vector3*)value); ) },
|
||||
{ this, std::string("SpotLightV9"), std::string(""),
|
||||
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_VECTOR3,
|
||||
REFLECTION_GETTER(Lighting* instance = (Lighting*)object; return &instance->m_spotLight; ),
|
||||
REFLECTION_SETTER(Lighting* instance = (Lighting*)object; instance->setSpotLight(*(Ogre::Vector3*)value); ) },
|
||||
};
|
||||
|
||||
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace RNR
|
|||
Workspace::Workspace() : ModelInstance()
|
||||
{
|
||||
setName("Workspace");
|
||||
m_batchMode = BATCH_STATIC_GEOMETRY;
|
||||
m_batchMode = BATCH_DONT;
|
||||
|
||||
m_worldspawn = world->getOgreSceneManager()->getRootSceneNode()->createChildSceneNode();
|
||||
|
||||
|
|
@ -19,9 +19,11 @@ namespace RNR
|
|||
break;
|
||||
case BATCH_STATIC_GEOMETRY:
|
||||
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
|
||||
m_geom->setRegionDimensions(Ogre::Vector3(512,512,512));
|
||||
m_geom->setRegionDimensions(Ogre::Vector3(2048,2048,2048));
|
||||
m_geom->setCastShadows(true);
|
||||
break;
|
||||
case BATCH_DONT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,11 +38,12 @@ namespace RNR
|
|||
case BATCH_INSTANCED:
|
||||
{
|
||||
Ogre::Entity* childEntity = (Ogre::Entity*)childAdded->getObject();
|
||||
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity(childEntity->getSubEntity(0)->getMaterialName());
|
||||
Ogre::InstancedEntity* replica = m_instanceManager->createInstancedEntity("materials/partinstanced");
|
||||
replica->setPosition(part->getPosition());
|
||||
replica->setOrientation(part->getCFrame().getRotation());
|
||||
replica->setScale(part->getSize());
|
||||
childAdded->setObject(replica);
|
||||
child_node->setVisible(false);
|
||||
}
|
||||
break;
|
||||
case BATCH_STATIC_GEOMETRY:
|
||||
|
|
@ -48,10 +51,12 @@ namespace RNR
|
|||
part->getPosition(),
|
||||
part->getCFrame().getRotation(),
|
||||
part->getSize());
|
||||
child_node->setVisible(false);
|
||||
m_geomDirty = true;
|
||||
break;
|
||||
case BATCH_DONT:
|
||||
break;
|
||||
}
|
||||
child_node->setVisible(false);
|
||||
m_geomDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,17 @@ namespace RNR
|
|||
Instance::~Instance()
|
||||
{
|
||||
setParent(NULL);
|
||||
if(getNode())
|
||||
{
|
||||
getNode()->removeAndDestroyAllChildren();
|
||||
delete getNode();
|
||||
}
|
||||
if(getObject())
|
||||
{
|
||||
if(getObject()->getParentNode() != 0)
|
||||
getObject()->detachFromParent();
|
||||
delete getObject();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ReflectionProperty> Instance::getProperties()
|
||||
|
|
@ -47,6 +58,8 @@ namespace RNR
|
|||
pugi::xml_attribute prop_name = prop.attribute("name");
|
||||
if(prop_name.as_string() == std::string("Name"))
|
||||
setName(prop.text().as_string());
|
||||
else if(prop_name.as_string() == std::string("archivable"))
|
||||
m_archivable = prop.text().as_bool();
|
||||
else
|
||||
deserializeProperty((char*)prop_name.as_string(), prop);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace RNR
|
|||
{
|
||||
PVInstance::PVInstance() : m_cframe(), Instance()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PVInstance::deserializeProperty(char* prop_name, pugi::xml_node node)
|
||||
|
|
@ -28,4 +28,9 @@ namespace RNR
|
|||
|
||||
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
|
||||
}
|
||||
|
||||
Ogre::Vector3 PVInstance::relativePositionTo(PVInstance* point)
|
||||
{
|
||||
return point->getPosition() - getPosition();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#include <App/V8/World/World.hpp>
|
||||
#include <App/V8/Tree/InstanceFactory.hpp>
|
||||
#include <App/V8/DataModel/PartInstance.hpp>
|
||||
#include <App/V8/DataModel/Lighting.hpp>
|
||||
#include <App/GUI/SelectionBox.hpp>
|
||||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <App/InputManager.hpp>
|
||||
|
|
@ -14,6 +15,13 @@ namespace RNR
|
|||
{
|
||||
Instance::setWorld(this);
|
||||
|
||||
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
|
||||
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
|
||||
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
|
||||
m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
|
||||
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
|
||||
|
||||
m_inputManager = 0;
|
||||
|
||||
m_instanceFactory = new InstanceFactory();
|
||||
|
|
@ -27,6 +35,7 @@ namespace RNR
|
|||
m_instanceFactory->registerInstance("RunService", InstanceFactory::instanceBuilder<RunService>);
|
||||
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
|
||||
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
|
||||
m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>);
|
||||
|
||||
m_ogreRoot = ogre;
|
||||
m_ogreSceneManager = ogreSceneManager;
|
||||
|
|
@ -109,13 +118,14 @@ namespace RNR
|
|||
WorldUndeserialized s = m_undeserialized.top();
|
||||
m_undeserialized.pop();
|
||||
|
||||
s.instance->setParent(s.parent);
|
||||
|
||||
pugi::xml_node props = s.node.child("Properties");
|
||||
for(pugi::xml_node prop : props.children())
|
||||
{
|
||||
s.instance->deserializeXmlProperty(prop);
|
||||
}
|
||||
|
||||
s.instance->setParent(s.parent);
|
||||
if(s.instance->getClassName() == "Model")
|
||||
{
|
||||
ModelInstance* m = (ModelInstance*)s.instance;
|
||||
|
|
@ -140,7 +150,10 @@ namespace RNR
|
|||
double World::step(float timestep)
|
||||
{
|
||||
if(m_runService && m_runService->getRunning())
|
||||
{
|
||||
m_runService->step(timestep);
|
||||
m_dynamicsWorld->stepSimulation(timestep);
|
||||
}
|
||||
m_lastDelta = timestep;
|
||||
return 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,16 @@ namespace RNR
|
|||
);
|
||||
}
|
||||
|
||||
Ogre::Vector3 XML::getColor(pugi::xml_node node)
|
||||
{
|
||||
Ogre::Vector3 rgb;
|
||||
unsigned int hex = node.text().as_uint();
|
||||
rgb.x = ((hex >> 16) & 0xff) / 255.0;
|
||||
rgb.y = ((hex >> 8) & 0xff) / 255.0;
|
||||
rgb.z = ((hex) & 0xff) / 255.0;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
CoordinateFrame XML::getCFrame(pugi::xml_node node)
|
||||
{
|
||||
CoordinateFrame cframe;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <Network/Player.hpp>
|
||||
#include <App/Humanoid/Humanoid.hpp>
|
||||
#include <App/V8/World/World.hpp>
|
||||
|
||||
namespace RNR
|
||||
|
|
@ -22,4 +23,38 @@ namespace RNR
|
|||
|
||||
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
|
||||
}
|
||||
|
||||
void Player::initLocalPlayer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::loadCharacter()
|
||||
{
|
||||
m_character = new ModelInstance();
|
||||
m_character->setName(getName());
|
||||
|
||||
PartInstance* head = new PartInstance();
|
||||
head->setName("Head");
|
||||
head->setSize(Ogre::Vector3(2, 1, 1));
|
||||
head->setBrickColor(24);
|
||||
head->getCFrame().setPosition(Ogre::Vector3(0, 1.5, 0));
|
||||
head->updateMatrix();
|
||||
head->setParent(m_character);
|
||||
|
||||
PartInstance* torso = new PartInstance();
|
||||
torso->setName("Torso");
|
||||
torso->setSize(Ogre::Vector3(2, 2, 1));
|
||||
torso->setBrickColor(23);
|
||||
torso->getCFrame().setPosition(Ogre::Vector3(0, 0, 0));
|
||||
torso->updateMatrix();
|
||||
torso->setParent(m_character);
|
||||
|
||||
Humanoid* character_humanoid = new Humanoid();
|
||||
character_humanoid->setParent(m_character);
|
||||
m_character->setParent(world->getWorkspace());
|
||||
|
||||
Camera* player_camera = world->getWorkspace()->getCurrentCamera();
|
||||
player_camera->setCFrame(CoordinateFrame());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@ namespace RNR
|
|||
{
|
||||
if(m_localPlayer)
|
||||
{
|
||||
printf("Players::createLocalPlayer: attempt to create another local player\n", userId);
|
||||
return m_localPlayer;
|
||||
printf("Players::createLocalPlayer: attempt to create another local player %i\n", userId);
|
||||
return 0;
|
||||
}
|
||||
printf("Players::createLocalPlayer: created player %i\n", userId);
|
||||
m_localPlayer = new Player();
|
||||
m_localPlayer->initLocalPlayer();
|
||||
return m_localPlayer;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
# RNR
|
||||
[](https://github.com/lrre-foss/rnr/actions)
|
||||
[](https://discord.gg/2tj4TREby3)
|
||||
[](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 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.
|
||||
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.
|
||||
|
||||
Interested in contributing? [Feel free to make a pull request!](https://github.com/lrre-foss/RNR/pulls)
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ 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
|
||||
|
|
|
|||