CoreAPI initialization hooked up to WrenState

Foreign method binding system setup
master
Joey Pollack 3 years ago
parent 09c4b10392
commit 3c55ca9c5b

@ -1,5 +1,8 @@
Editor:
☐ Generate boiler-plate code when a new script is created
☐ Include setting the entity ID
☐ Add pure virtual ShowProperties method to EditorAsset
✔ Script Editor Asset @done(22-11-14 18:19)
✔ Editor Assets need to switch to using UUIDs @critical @done(22-11-02 18:51)

@ -36,7 +36,7 @@ IF NOT "!BUILD_ERRORLEVEL!"=="0" (
xcopy /y test_data\engine_state.json build\Release\
xcopy /y test_data\world_interface.wren build\Release\
xcopy /y src\scripting\internal_scripts\*.wren build\Release\
xcopy /y src\renderer\shaders\* build\Release\*
@ -51,7 +51,7 @@ IF NOT "!BUILD_ERRORLEVEL!"=="0" (
xcopy /y test_data\engine_state.json build\RelWithDebInfo\
xcopy /y test_data\world_interface.wren build\RelWithDebInfo\
xcopy /y src\scripting\internal_scripts\*.wren build\RelWithDebInfo\
xcopy /y src\renderer\shaders\* build\RelWithDebInfo\*
) ELSE (
@ -65,7 +65,7 @@ IF NOT "!BUILD_ERRORLEVEL!"=="0" (
xcopy /y test_data\engine_state.json build\Debug\
xcopy /y test_data\world_interface.wren build\Debug\
xcopy /y src\scripting\internal_scripts\*.wren build\Debug\
xcopy /y src\renderer\shaders\* build\Debug\*
)

@ -12,6 +12,7 @@
#include "window.h"
#include <vector>
#include <map>
namespace lunarium
{
@ -221,6 +222,95 @@ namespace lunarium
KeyCode::MOUSE_X1_BUTTON,
KeyCode::MOUSE_X2_BUTTON
};
static std::map<std::string, KeyCode> KeyCodeMap =
{
std::pair<std::string, KeyCode> {"A", KeyCode::A},
std::pair<std::string, KeyCode> {"B", KeyCode::B},
std::pair<std::string, KeyCode> {"C", KeyCode::C},
std::pair<std::string, KeyCode> {"D", KeyCode::D},
std::pair<std::string, KeyCode> {"E", KeyCode::E},
std::pair<std::string, KeyCode> {"F", KeyCode::F},
std::pair<std::string, KeyCode> {"G", KeyCode::G},
std::pair<std::string, KeyCode> {"H", KeyCode::H},
std::pair<std::string, KeyCode> {"I", KeyCode::I},
std::pair<std::string, KeyCode> {"J", KeyCode::J},
std::pair<std::string, KeyCode> {"K", KeyCode::K},
std::pair<std::string, KeyCode> {"L", KeyCode::L},
std::pair<std::string, KeyCode> {"M", KeyCode::M},
std::pair<std::string, KeyCode> {"N", KeyCode::N},
std::pair<std::string, KeyCode> {"O", KeyCode::O},
std::pair<std::string, KeyCode> {"P", KeyCode::P},
std::pair<std::string, KeyCode> {"Q", KeyCode::Q},
std::pair<std::string, KeyCode> {"R", KeyCode::R},
std::pair<std::string, KeyCode> {"S", KeyCode::S},
std::pair<std::string, KeyCode> {"T", KeyCode::T},
std::pair<std::string, KeyCode> {"U", KeyCode::U},
std::pair<std::string, KeyCode> {"V", KeyCode::V},
std::pair<std::string, KeyCode> {"W", KeyCode::W},
std::pair<std::string, KeyCode> {"X", KeyCode::X},
std::pair<std::string, KeyCode> {"Y", KeyCode::Y},
std::pair<std::string, KeyCode> {"Z", KeyCode::Z},
std::pair<std::string, KeyCode> {"NUM_0", KeyCode::NUM_0},
std::pair<std::string, KeyCode> {"NUM_1", KeyCode::NUM_1},
std::pair<std::string, KeyCode> {"NUM_2", KeyCode::NUM_2},
std::pair<std::string, KeyCode> {"NUM_3", KeyCode::NUM_3},
std::pair<std::string, KeyCode> {"NUM_4", KeyCode::NUM_4},
std::pair<std::string, KeyCode> {"NUM_5", KeyCode::NUM_5},
std::pair<std::string, KeyCode> {"NUM_6", KeyCode::NUM_6},
std::pair<std::string, KeyCode> {"NUM_7", KeyCode::NUM_7},
std::pair<std::string, KeyCode> {"NUM_8", KeyCode::NUM_8},
std::pair<std::string, KeyCode> {"NUM_9", KeyCode::NUM_9},
std::pair<std::string, KeyCode> {"F1", KeyCode::F1},
std::pair<std::string, KeyCode> {"F2", KeyCode::F2},
std::pair<std::string, KeyCode> {"F3", KeyCode::F3},
std::pair<std::string, KeyCode> {"F4", KeyCode::F4},
std::pair<std::string, KeyCode> {"F5", KeyCode::F5},
std::pair<std::string, KeyCode> {"F6", KeyCode::F6},
std::pair<std::string, KeyCode> {"F7", KeyCode::F7},
std::pair<std::string, KeyCode> {"F8", KeyCode::F8},
std::pair<std::string, KeyCode> {"F9", KeyCode::F9},
std::pair<std::string, KeyCode> {"F10", KeyCode::F10},
std::pair<std::string, KeyCode> {"F11", KeyCode::F11},
std::pair<std::string, KeyCode> {"F12", KeyCode::F12},
std::pair<std::string, KeyCode> {"LSHIFT", KeyCode::LSHIFT},
std::pair<std::string, KeyCode> {"RSHIFT", KeyCode::RSHIFT},
std::pair<std::string, KeyCode> {"LCONTROL", KeyCode::LCONTROL},
std::pair<std::string, KeyCode> {"RCONTROL", KeyCode::RCONTROL},
std::pair<std::string, KeyCode> {"LALT", KeyCode::LALT},
std::pair<std::string, KeyCode> {"RALT", KeyCode::RALT},
std::pair<std::string, KeyCode> {"SPACE", KeyCode::SPACE},
std::pair<std::string, KeyCode> {"LEFT", KeyCode::LEFT},
std::pair<std::string, KeyCode> {"UP", KeyCode::UP},
std::pair<std::string, KeyCode> {"RIGHT", KeyCode::RIGHT},
std::pair<std::string, KeyCode> {"DOWN", KeyCode::DOWN},
std::pair<std::string, KeyCode> {"DEL", KeyCode::DEL},
std::pair<std::string, KeyCode> {"RETURN", KeyCode::RETURN},
std::pair<std::string, KeyCode> {"BACKSPACE", KeyCode::BACKSPACE},
std::pair<std::string, KeyCode> {"TAB", KeyCode::TAB},
std::pair<std::string, KeyCode> {"ESCAPE", KeyCode::ESCAPE},
std::pair<std::string, KeyCode> {"PAGE_UP", KeyCode::PAGE_UP},
std::pair<std::string, KeyCode> {"PAGE_DOWN", KeyCode::PAGE_DOWN},
std::pair<std::string, KeyCode> {"SEMICOLON", KeyCode::SEMICOLON},
std::pair<std::string, KeyCode> {"EQUALS", KeyCode::EQUALS},
std::pair<std::string, KeyCode> {"COMMA", KeyCode::COMMA},
std::pair<std::string, KeyCode> {"DASH", KeyCode::DASH},
std::pair<std::string, KeyCode> {"DOT", KeyCode::DOT},
std::pair<std::string, KeyCode> {"FORWARD_SLASH", KeyCode::FORWARD_SLASH},
std::pair<std::string, KeyCode> {"TILDE", KeyCode::TILDE},
std::pair<std::string, KeyCode> {"OPEN_BRACKET", KeyCode::OPEN_BRACKET},
std::pair<std::string, KeyCode> {"BACKSLASH", KeyCode::BACKSLASH},
std::pair<std::string, KeyCode> {"CLOSE_BRACKET", KeyCode::CLOSE_BRACKET},
std::pair<std::string, KeyCode> {"QUOTE", KeyCode::QUOTE},
std::pair<std::string, KeyCode> {"MOUSE_LEFT_BUTTON", KeyCode::MOUSE_LEFT_BUTTON},
std::pair<std::string, KeyCode> {"MOUSE_RIGHT_BUTTON", KeyCode::MOUSE_RIGHT_BUTTON},
std::pair<std::string, KeyCode> {"MOUSE_MIDDLE_BUTTON", KeyCode::MOUSE_MIDDLE_BUTTON},
std::pair<std::string, KeyCode> {"MOUSE_X1_BUTTON", KeyCode::MOUSE_X1_BUTTON},
std::pair<std::string, KeyCode> {"MOUSE_X2_BUTTON", KeyCode::MOUSE_X2_BUTTON}
};
}

@ -11,12 +11,15 @@
#include "coreAPI.h"
#include "wren_state.h"
#include <core/core.h>
#include <platform/key_codes.h>
#include <utils/logger.h>
#include <utils/helpers.h>
namespace lunarium
{
CoreAPI* CoreAPI::mpInstance = nullptr;
WrenScript CoreAPI::mScript;
std::vector<CoreAPI::ForeignMethodID> CoreAPI::mForeignMethods;
CoreAPI& CoreAPI::GetInstance()
{
if (mpInstance == nullptr)
@ -37,14 +40,62 @@ namespace lunarium
{
mCat = sman.GetLogCat();
// Register callbacks
sman.RegisterForeignMethodBinder((FMBinder*)&CoreAPI::ForeignMethodBinder);
// Generate Code
std::string keys_script = GenerateWrenKeyCodes();
sman.RunSnippet("KeyCodes", keys_script);
// DEBUG - SAVE GENERATED SCRIPT TO FILE FOR REVIEW
File::WriteTextFile("key_codes.wren", keys_script);
// Load Main Script
mScript.SetModuleName("CoreAPI");
std::string code = File::ReadTextFile("core_api.wren"); // This will eventually move to internal data
mScript.SetScriptCode(code);
// Register methods
// sman.mState["SetWindowSize"] = &CoreAPI::SetWindowSize;
// sman.mState["Log"] = &CoreAPI::Log;
// return OpRes::Fail("CoreAPI::Initialize not implemented yet!");
return OpRes::OK();
}
WrenForeignMethodFn CoreAPI::ForeignMethodBinder(WrenVM* vm, const char* module, const char* class_name, bool isStatic, const char* signature)
{
ForeignMethodID FMID = { module, class_name, isStatic, signature };
for (auto iter = mForeignMethods.begin(); iter != mForeignMethods.end(); iter++)
{
if (FMID == (*iter))
{
iter->FM;
}
}
return nullptr;
}
std::string CoreAPI::GenerateWrenKeyCodes()
{
std::string key_codes = "class KeyCodes {\n";
for (auto iter = KeyCodeMap.begin(); iter != KeyCodeMap.end(); iter++)
{
key_codes += "\tstatic ";
key_codes += iter->first;
key_codes += "() { ";
key_codes += std::to_string((u32)iter->second);
key_codes += " }\n";
}
key_codes += "}";
return key_codes;
}
////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////
@ -66,4 +117,9 @@ namespace lunarium
default: { Logger::Trace(mpInstance->mCat, msg); break; }
}
}
bool CoreAPI::IsKeyDown(WrenVM* vm)
{
return false;
}
}

@ -12,8 +12,12 @@
#define CORE_API_H_
#include <core/common_defs.h>
#include "wren_script.h"
#include <utils/op_res.h>
#include <input/input_manager.h>
#include <map>
struct WrenVM;
namespace lunarium
{
@ -27,15 +31,42 @@ namespace lunarium
OpRes Initialize(WrenState& state);
private:
static CoreAPI* mpInstance;
static WrenScript mScript;
u32 mCat;
typedef void (*ForeignMethod)(WrenVM*);
struct ForeignMethodID
{
std::string Module;
std::string Class;
bool IsStatic;
std::string Signature;
ForeignMethod FM;
bool operator==(const ForeignMethodID& rhs)
{
return (Module == rhs.Module && Class == rhs.Class && IsStatic == rhs.IsStatic && Signature == rhs.Signature);
}
};
static std::vector<ForeignMethodID> mForeignMethods;
private: // Helper methods
std::string GenerateWrenKeyCodes();
private: // Callbacks
static ForeignMethod ForeignMethodBinder(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature);
public: // API
static void SetWindowSize(int w, int h);
static void Log(int level, const char* msg);
static bool IsKeyDown(WrenVM* vm);
};
}

@ -0,0 +1,27 @@
/******************************************************************************
* File - components.wren
* Author - Joey Pollack
* Date - 2022/11/17 (y/m/d)
* Mod Date - 2022/11/17 (y/m/d)
* Description - The foreign classes for components
******************************************************************************/
class Component {
EntityID { _EntityID }
EntityID=(value) {
_EntityID = value
}
}
foreign class VelocityComponent is Component {
// The parameter will be used on the C++ side to set the correct C++ component
construct new(entity_id) {
super.EntityID = entity_id
}
// maybe wrap these in non-foreign methods
// to abstract pulling data out of slots?
foreign GetVelocity()
foreign SetVelocity(x, y)
}

@ -0,0 +1,11 @@
/******************************************************************************
* File - core_api.wren
* Author - Joey Pollack
* Date - 2022/11/21 (y/m/d)
* Mod Date - 2022/11/21 (y/m/d)
* Description - The Core API exposes core Lunarium features to scripts
******************************************************************************/
class Core {
//foreign static IsKeyDown(key)
}

@ -6,6 +6,15 @@
* Description - The main interface for scripts to interact with the game world
******************************************************************************/
class Component {
Tag { 1 }
Transform { 2 }
Velocity { 3 }
Camera { 4 }
BlockOut { 5 }
Script { 6 }
}
// Manages all of the EntityBehaviors
class WorldInterface {
@ -14,6 +23,10 @@ class WorldInterface {
System.print("WorldInterface initialized")
}
/////////////////////////////////////////////////////////////////////
// EVENTS
/////////////////////////////////////////////////////////////////////
static RegisterBehavior(behavior) {
__Behaviors.add(behavior)
// behavior.OnLoad()
@ -37,11 +50,25 @@ class WorldInterface {
behavior.Update(dt)
}
}
/////////////////////////////////////////////////////////////////////
// API
/////////////////////////////////////////////////////////////////////
static GetComponent(entity_id, component_id) {
}
}
class EntityBehavior {
EntityID { _EntityID }
EntityID=(value) {
_EntityID = value
}
OnLoad() {
}

@ -9,11 +9,13 @@
#include "wren_state.h"
#include "wren_script.h"
#include "coreAPI.h"
#include <utils/logger.h>
#include <utils/helpers.h>
namespace lunarium
{
std::vector<FMBinder*> WrenState::mFMBinders;
WrenState::~WrenState()
{
@ -36,6 +38,8 @@ namespace lunarium
mpVM = wrenNewVM(&config);
CoreAPI::GetInstance().Initialize(*this);
return OpRes::OK();
}
@ -44,6 +48,15 @@ namespace lunarium
return mLogCat;
}
void WrenState::RegisterForeignMethodBinder(FMBinder* binder_method)
{
mFMBinders.push_back(binder_method);
}
/////////////////////////////////////////////////////////////////////
// HANDLES
/////////////////////////////////////////////////////////////////////
WrenHandle* WrenState::GetWrenClassHandle(std::string from_module, std::string class_name)
{
// Load the class into slot 0.
@ -90,6 +103,9 @@ namespace lunarium
wrenReleaseHandle(mpVM, handle);
}
/////////////////////////////////////////////////////////////////////
// CODE PROCESSING
/////////////////////////////////////////////////////////////////////
void WrenState::RunScript(WrenScript* script)
{
@ -127,6 +143,9 @@ namespace lunarium
}
}
/////////////////////////////////////////////////////////////////////
// VM CALLBACK METHODS
/////////////////////////////////////////////////////////////////////
void WrenState::WriteFN(WrenVM* vm, const char* text)
{
@ -155,4 +174,23 @@ namespace lunarium
break;
}
}
WrenForeignMethodFn WrenState::BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature)
{
// Bind methods
// If method not recognized, call any registered FMBinder methods
for (auto iter = mFMBinders.begin(); iter != mFMBinders.end(); iter++)
{
auto FN = ((FMBinder)(*iter))(vm, module, className, isStatic, signature);
if (FN)
{
return FN;
}
}
Logger::Error(mLogCat, "Failed to bind foreign method: %s::%s", className, signature);
return nullptr;
}
}

@ -42,6 +42,8 @@ namespace lunarium
class WrenScript;
typedef WrenForeignMethodFn (*FMBinder) (WrenVM*, const char*, const char*, bool, const char*);
class WrenState
{
public:
@ -50,6 +52,8 @@ namespace lunarium
void Shutdown();
u32 GetLogCat() const;
void RegisterForeignMethodBinder(FMBinder* binder_method);
void RunScript(WrenScript* script);
void RunSnippet(std::string name, std::string code);
@ -61,12 +65,14 @@ namespace lunarium
// CALL BACKS
static void WriteFN(WrenVM* vm, const char* text);
static void ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message);
static WrenForeignMethodFn BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature);
private:
static u32 mLogCat;
WrenVM* mpVM;
static std::vector<FMBinder*> mFMBinders;
};
}

@ -338,26 +338,22 @@ namespace lunarium
}
std::string File::ReadScriptFile(std::string filename)
void File::WriteTextFile(std::string filename, std::string text, bool truncate)
{
std::ifstream ifs(filename);
if (!ifs.is_open())
{
Logger::Error(LogCategory::UTILITIES, "Could not open file: %s", filename.c_str());
return "";
}
std::ofstream ofs;
if (truncate)
ofs.open(filename, std::ios_base::trunc);
else
ofs.open(filename, std::ios_base::app);
std::string contents;
while (ifs)
if (!ofs.is_open())
{
contents += ifs.get();
Logger::Error(LogCategory::UTILITIES, "Could not open file: %s", filename.c_str());
}
contents.erase(contents.end() - 1);
ofs.write(text.c_str(), text.size());
ifs.close();
ifs.clear();
return contents;
ofs.close();
ofs.clear();
}
}

@ -96,7 +96,7 @@ namespace lunarium
{
public:
static std::string ReadTextFile(std::string filename);
static std::string ReadScriptFile(std::string filename);
static void WriteTextFile(std::string filename, std::string text, bool truncate = true);
};
}

@ -77,22 +77,18 @@ namespace lunarium
#if !BUILD_NO_EDITOR
editor::Script* pScript = (editor::Script*) editor::ContentManager::GetInstance().GetAsset(script_comp.ScriptID);
WrenScript script(pScript->GetScriptFile().filename().string().c_str(), pScript->GetScript());
mScriptState.RunScript(&script);
#endif
}
// Call OnLoad for each registered EntityBehavior class object
//mScriptState.RunSnippet("WorldInterface", "WorldInterface.DoOnLoad()");
mScriptState.CallWrenMethod(mWIDoOnLoadMethod, mWIHandle, {}, "WorldInterface.DoOnLoad()");
}
void World::OnUnload()
{
// TODO: Call OnUnLoad for each registered EntityBehavior class object
//mScriptState.RunSnippet("WorldInterface", "WorldInterface.DoOnUnload()");
mScriptState.CallWrenMethod(mWIDoOnUnloadMethod, mWIHandle, {}, "WorldInterface.DoOnUnload()");
mScriptState.Shutdown();
}
@ -110,13 +106,8 @@ namespace lunarium
void World::Update(float dt)
{
// Update all scripts
// Call OnUpdate for each registered EntityBehavior class object
// std::string code = "WorldInterface.Update(";
// code.append(std::to_string(dt));
// code.append(")");
// mScriptState.RunSnippet("WorldInterface", code);
// Call Update for each registered EntityBehavior class object
mScriptState.CallWrenMethod(mWIUpdateMethod, mWIHandle, { {WrenParamType::WPT_DOUBLE, (double)dt} }, "WorldInterface.Update(dt)");
// Update Transforms for any enity with a velocity

Loading…
Cancel
Save