feat(lua): added basis for lua scripting
This commit is contained in:
parent
4cfb327b65
commit
c081469a49
17 changed files with 164 additions and 14 deletions
|
@ -11,11 +11,15 @@ find_package(pugixml 1.15 REQUIRED)
|
|||
find_package(Stb REQUIRED)
|
||||
include_directories(${Stb_INCLUDE_DIR})
|
||||
|
||||
# PkgConfig packages
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LUAJIT REQUIRED luajit)
|
||||
|
||||
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h")
|
||||
add_library(openblocks STATIC ${SOURCES})
|
||||
set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks")
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
target_include_directories(openblocks PUBLIC "src" "../include")
|
||||
target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml)
|
||||
target_include_directories(openblocks PUBLIC "src" "../include" ${LUAJIT_INCLUDE_DIR})
|
||||
|
||||
# Windows-specific dependencies
|
||||
if(WIN32)
|
||||
|
|
7
core/src/lua.h
Normal file
7
core/src/lua.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
extern "C" {
|
||||
#include <luajit-2.1/luajit.h>
|
||||
#include <luajit-2.1/lauxlib.h>
|
||||
#include <luajit-2.1/lualib.h>
|
||||
#include <luajit-2.1/lua.h>
|
||||
}
|
|
@ -25,9 +25,11 @@ class Workspace;
|
|||
|
||||
typedef int InstanceFlags;
|
||||
// This instance should only be instantiated in special circumstances (i.e. by DataModel) and should be creatable directly via any API
|
||||
const InstanceFlags INSTANCE_NOTCREATABLE = (InstanceFlags)0x1;
|
||||
const InstanceFlags INSTANCE_NOTCREATABLE = (InstanceFlags)1<<0;
|
||||
// This instance is a service
|
||||
const InstanceFlags INSTANCE_SERVICE = (InstanceFlags)0x2;
|
||||
const InstanceFlags INSTANCE_SERVICE = (InstanceFlags)1<<1;
|
||||
// This instance should be hidden from the explorer
|
||||
const InstanceFlags INSTANCE_HIDDEN = (InstanceFlags)1<<2;
|
||||
|
||||
// Struct describing information about an instance
|
||||
struct InstanceType {
|
||||
|
|
|
@ -17,4 +17,7 @@ void Service::OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent
|
|||
}
|
||||
|
||||
void Service::InitService() {
|
||||
}
|
||||
|
||||
void Service::OnRun() {
|
||||
}
|
|
@ -8,6 +8,7 @@ class Service : public Instance {
|
|||
protected:
|
||||
Service(const InstanceType* type);
|
||||
virtual void InitService();
|
||||
virtual void OnRun();
|
||||
|
||||
void OnParentUpdated(std::optional<std::shared_ptr<Instance>> oldParent, std::optional<std::shared_ptr<Instance>> newParent) override;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "objects/base/refstate.h"
|
||||
#include "objects/base/service.h"
|
||||
#include "objects/meta.h"
|
||||
#include "objects/script/serverscriptservice.h"
|
||||
#include "workspace.h"
|
||||
#include "logger.h"
|
||||
#include "panic.h"
|
||||
|
@ -27,16 +28,19 @@ DataModel::DataModel()
|
|||
this->name = "Place";
|
||||
}
|
||||
|
||||
void DataModel::Init() {
|
||||
void DataModel::Init(bool runMode) {
|
||||
// Create the workspace if it doesn't exist
|
||||
if (this->services.count("Workspace") == 0) {
|
||||
this->services["Workspace"] = std::make_shared<Workspace>();
|
||||
AddChild(this->services["Workspace"]);
|
||||
}
|
||||
|
||||
GetService<ServerScriptService>();
|
||||
|
||||
// Init all services
|
||||
for (auto [_, service] : this->services) {
|
||||
service->InitService();
|
||||
if (runMode) service->OnRun();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +132,7 @@ result<std::shared_ptr<Service>, NoSuchService> DataModel::GetService(std::strin
|
|||
if (services.count(className) != 0)
|
||||
return std::dynamic_pointer_cast<Service>(services[className]);
|
||||
|
||||
if (!INSTANCE_MAP[className] || (INSTANCE_MAP[className]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
||||
if (!INSTANCE_MAP[className] || ~(INSTANCE_MAP[className]->flags & (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) == 0) {
|
||||
return NoSuchService(className);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
std::optional<std::string> currentFile;
|
||||
|
||||
DataModel();
|
||||
void Init();
|
||||
void Init(bool runMode = false);
|
||||
|
||||
static inline std::shared_ptr<DataModel> New() { return std::make_shared<DataModel>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
|
|
|
@ -6,7 +6,7 @@ const InstanceType JointsService::TYPE = {
|
|||
.super = &Instance::TYPE,
|
||||
.className = "JointsService",
|
||||
.constructor = &JointsService::Create,
|
||||
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE,
|
||||
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE | INSTANCE_HIDDEN,
|
||||
};
|
||||
|
||||
const InstanceType* JointsService::GetClass() {
|
||||
|
|
|
@ -4,15 +4,23 @@
|
|||
#include "objects/part.h"
|
||||
#include "objects/joint/snap.h"
|
||||
#include "objects/script.h"
|
||||
#include "objects/script/scriptcontext.h"
|
||||
#include "objects/script/serverscriptservice.h"
|
||||
#include "objects/workspace.h"
|
||||
|
||||
std::map<std::string, const InstanceType*> INSTANCE_MAP = {
|
||||
{ "Instance", &Instance::TYPE },
|
||||
{ "Part", &Part::TYPE },
|
||||
{ "Workspace", &Workspace::TYPE },
|
||||
{ "DataModel", &DataModel::TYPE },
|
||||
|
||||
{ "Part", &Part::TYPE },
|
||||
{ "Snap", &Snap::TYPE },
|
||||
{ "JointInstance", &JointInstance::TYPE },
|
||||
{ "JointsService", &JointsService::TYPE },
|
||||
{ "Script", &Script::TYPE },
|
||||
|
||||
// Services
|
||||
|
||||
{ "Workspace", &Workspace::TYPE },
|
||||
{ "JointsService", &JointsService::TYPE },
|
||||
{ "ScriptContext", &ScriptContext::TYPE },
|
||||
{ "ServerScriptService", &ServerScriptService::TYPE },
|
||||
};
|
|
@ -28,4 +28,12 @@ Script::Script(): Instance(&TYPE) {
|
|||
}
|
||||
|
||||
Script::~Script() {
|
||||
}
|
||||
|
||||
void Script::Run() {
|
||||
|
||||
}
|
||||
|
||||
void Script::Stop() {
|
||||
// TODO:
|
||||
}
|
|
@ -11,6 +11,8 @@ public:
|
|||
~Script();
|
||||
|
||||
std::string source;
|
||||
void Run();
|
||||
void Stop();
|
||||
|
||||
static inline std::shared_ptr<Script> New() { return std::make_shared<Script>(); };
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Script>(); };
|
||||
|
|
29
core/src/objects/script/scriptcontext.cpp
Normal file
29
core/src/objects/script/scriptcontext.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "scriptcontext.h"
|
||||
#include <luajit-2.1/lauxlib.h>
|
||||
#include <luajit-2.1/lua.h>
|
||||
|
||||
const InstanceType ScriptContext::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "ScriptContext",
|
||||
.constructor = &ScriptContext::Create,
|
||||
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE | INSTANCE_HIDDEN,
|
||||
};
|
||||
|
||||
const InstanceType* ScriptContext::GetClass() {
|
||||
return &TYPE;
|
||||
}
|
||||
|
||||
ScriptContext::ScriptContext(): Service(&TYPE) {
|
||||
}
|
||||
|
||||
ScriptContext::~ScriptContext() {
|
||||
if (state)
|
||||
lua_close(state);
|
||||
}
|
||||
|
||||
void ScriptContext::InitService() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
state = luaL_newstate();
|
||||
}
|
22
core/src/objects/script/scriptcontext.h
Normal file
22
core/src/objects/script/scriptcontext.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "objects/base/service.h"
|
||||
#include "lua.h"
|
||||
|
||||
class ScriptContext : public Service {
|
||||
private:
|
||||
protected:
|
||||
void InitService() override;
|
||||
bool initialized = false;
|
||||
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
ScriptContext();
|
||||
~ScriptContext();
|
||||
|
||||
lua_State* state;
|
||||
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ScriptContext>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
};
|
37
core/src/objects/script/serverscriptservice.cpp
Normal file
37
core/src/objects/script/serverscriptservice.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include "serverscriptservice.h"
|
||||
#include "objects/script.h"
|
||||
#include "objects/workspace.h"
|
||||
|
||||
const InstanceType ServerScriptService::TYPE = {
|
||||
.super = &Instance::TYPE,
|
||||
.className = "ServerScriptService",
|
||||
.constructor = &ServerScriptService::Create,
|
||||
.flags = INSTANCE_NOTCREATABLE | INSTANCE_SERVICE,
|
||||
};
|
||||
|
||||
const InstanceType* ServerScriptService::GetClass() {
|
||||
return &TYPE;
|
||||
}
|
||||
|
||||
ServerScriptService::ServerScriptService(): Service(&TYPE) {
|
||||
}
|
||||
|
||||
ServerScriptService::~ServerScriptService() = default;
|
||||
|
||||
void ServerScriptService::InitService() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void Service::OnRun() {
|
||||
auto workspace = dataModel().value()->GetService<Workspace>();
|
||||
for (auto it = workspace->GetDescendantsStart(); it != workspace->GetDescendantsEnd(); it++) {
|
||||
if (!it->IsA<Script>()) continue;
|
||||
it->CastTo<Script>().expect()->Run();
|
||||
}
|
||||
|
||||
for (auto it = GetDescendantsStart(); it != GetDescendantsEnd(); it++) {
|
||||
if (!it->IsA<Script>()) continue;
|
||||
it->CastTo<Script>().expect()->Run();
|
||||
}
|
||||
}
|
22
core/src/objects/script/serverscriptservice.h
Normal file
22
core/src/objects/script/serverscriptservice.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "objects/base/service.h"
|
||||
|
||||
// Container class for server scripts
|
||||
// Also handles/manages running server scripts on run
|
||||
class ServerScriptService : public Service {
|
||||
private:
|
||||
protected:
|
||||
void InitService() override;
|
||||
void OnRun() override;
|
||||
bool initialized = false;
|
||||
|
||||
public:
|
||||
const static InstanceType TYPE;
|
||||
|
||||
ServerScriptService();
|
||||
~ServerScriptService();
|
||||
|
||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<ServerScriptService>(); };
|
||||
virtual const InstanceType* GetClass() override;
|
||||
};
|
|
@ -1,5 +1,7 @@
|
|||
#include "explorermodel.h"
|
||||
#include "common.h"
|
||||
#include "objects/base/instance.h"
|
||||
#include "objects/base/member.h"
|
||||
#include <qicon.h>
|
||||
#include <qmimedata.h>
|
||||
#include <QWidget>
|
||||
|
@ -43,7 +45,7 @@ QModelIndex ExplorerModel::index(int row, int column, const QModelIndex &parent)
|
|||
? static_cast<Instance*>(parent.internalPointer())
|
||||
: rootItem.get();
|
||||
|
||||
if (parentItem->GetChildren().size() >= row)
|
||||
if (parentItem->GetChildren().size() >= row && !(parentItem->GetChildren()[row]->GetClass()->flags & INSTANCE_HIDDEN))
|
||||
return createIndex(row, column, parentItem->GetChildren()[row].get());
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ void PlaceDocument::setRunState(RunState newState) {
|
|||
|
||||
std::shared_ptr<DataModel> newModel = editModeDataModel->CloneModel();
|
||||
gDataModel = newModel;
|
||||
gDataModel->Init();
|
||||
gDataModel->Init(true);
|
||||
} else if (newState == RUN_PAUSED && _runState == RUN_RUNNING) {
|
||||
_runState = RUN_PAUSED;
|
||||
} else if (newState == RUN_STOPPED) {
|
||||
|
@ -41,7 +41,6 @@ void PlaceDocument::setRunState(RunState newState) {
|
|||
|
||||
// GC: Check to make sure gDataModel gets properly garbage collected prior to this
|
||||
gDataModel = editModeDataModel;
|
||||
gDataModel->Init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue