chore/refactor #2
@@ -28,9 +28,16 @@ target_include_directories(scriptstdstring
|
||||
# -------------------------
|
||||
# 4️⃣ Main executable
|
||||
# -------------------------
|
||||
add_executable(simian main.cpp)
|
||||
add_executable(simian
|
||||
main.cpp
|
||||
src/Application.cpp
|
||||
src/ScriptEngine.cpp
|
||||
src/ScriptBindings.cpp
|
||||
src/HotReload.cpp
|
||||
)
|
||||
|
||||
target_include_directories(simian PUBLIC
|
||||
include
|
||||
external/raylib/src
|
||||
external/angelscript/sdk/angelscript/include
|
||||
external/angelscript/sdk/add_on/scriptstdstring
|
||||
|
||||
30
README.md
30
README.md
@@ -3,6 +3,36 @@
|
||||
**Simian** is a Raylib + AngelScript test project on Windows and Linux.
|
||||
It demonstrates how to integrate **Raylib** for graphics and **AngelScript** for scripting, including the `scriptstdstring` add-on.
|
||||
|
||||
## Refactored Architecture
|
||||
|
||||
The project has been refactored from a single `main.cpp` file into a more maintainable modular structure:
|
||||
|
||||
### Core Components
|
||||
- **Application** (`Application.h/cpp`) - Main application lifecycle and game loop
|
||||
- **ScriptEngine** (`ScriptEngine.h/cpp`) - AngelScript engine management and script compilation
|
||||
- **ScriptBindings** (`ScriptBindings.h/cpp`) - C++ to AngelScript function bindings
|
||||
- **HotReload** (`HotReload.h/cpp`) - File monitoring for automatic script reloading
|
||||
- **main.cpp** - Minimal entry point
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
Simian/
|
||||
├─ include/ # Header files
|
||||
│ ├─ Application.h
|
||||
│ ├─ ScriptEngine.h
|
||||
│ ├─ ScriptBindings.h
|
||||
│ └─ HotReload.h
|
||||
├─ src/ # Source files
|
||||
│ ├─ Application.cpp
|
||||
│ ├─ ScriptEngine.cpp
|
||||
│ ├─ ScriptBindings.cpp
|
||||
│ └─ HotReload.cpp
|
||||
├─ external/ # Dependencies
|
||||
├─ scripts/ # AngelScript files
|
||||
├─ main.cpp # Entry point
|
||||
└─ CMakeLists.txt # Build configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
27
include/Application.h
Normal file
27
include/Application.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "ScriptEngine.h"
|
||||
#include "HotReload.h"
|
||||
|
||||
class Application {
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
bool Initialize();
|
||||
void Run();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
ScriptEngine scriptEngine;
|
||||
HotReload* hotReload;
|
||||
bool scriptCompilationError;
|
||||
|
||||
static const int WINDOW_WIDTH = 800;
|
||||
static const int WINDOW_HEIGHT = 600;
|
||||
static const int TARGET_FPS = 60;
|
||||
static const char* WINDOW_TITLE;
|
||||
static const char* SCRIPT_FILE;
|
||||
|
||||
void Update(float deltaTime);
|
||||
void Draw();
|
||||
};
|
||||
18
include/HotReload.h
Normal file
18
include/HotReload.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
|
||||
class HotReload {
|
||||
public:
|
||||
HotReload(const std::string& filename);
|
||||
|
||||
bool CheckForChanges();
|
||||
void UpdateLastWriteTime();
|
||||
|
||||
private:
|
||||
std::string scriptFile;
|
||||
std::time_t lastWriteTime;
|
||||
|
||||
std::time_t GetFileWriteTime(const std::string& filename);
|
||||
};
|
||||
12
include/ScriptBindings.h
Normal file
12
include/ScriptBindings.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "angelscript.h"
|
||||
#include <string>
|
||||
|
||||
class ScriptBindings {
|
||||
public:
|
||||
static void RegisterAll(asIScriptEngine* engine);
|
||||
|
||||
private:
|
||||
static void Print(const std::string &msg);
|
||||
static void AS_DrawText(const std::string &text, int x, int y, int fontSize, unsigned int color);
|
||||
};
|
||||
30
include/ScriptEngine.h
Normal file
30
include/ScriptEngine.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "angelscript.h"
|
||||
#include <string>
|
||||
|
||||
class ScriptEngine {
|
||||
public:
|
||||
ScriptEngine();
|
||||
~ScriptEngine();
|
||||
|
||||
bool Initialize();
|
||||
void Shutdown();
|
||||
bool CompileScript(const std::string& filename);
|
||||
void CallScriptFunction(asIScriptFunction* func, float dt = 0.0f);
|
||||
void GarbageCollect();
|
||||
|
||||
asIScriptEngine* GetEngine() const { return engine; }
|
||||
asIScriptFunction* GetUpdateFunction() const { return updateFunc; }
|
||||
asIScriptFunction* GetDrawFunction() const { return drawFunc; }
|
||||
|
||||
private:
|
||||
asIScriptEngine* engine;
|
||||
asIScriptFunction* updateFunc;
|
||||
asIScriptFunction* drawFunc;
|
||||
asIScriptModule* currentModule;
|
||||
bool hasValidScript;
|
||||
|
||||
static void MessageCallback(const asSMessageInfo* msg, void* param);
|
||||
std::string ReadFile(const std::string& filename);
|
||||
void ClearCachedFunctions();
|
||||
};
|
||||
168
main.cpp
168
main.cpp
@@ -1,162 +1,16 @@
|
||||
#include "Application.h"
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "raylib.h"
|
||||
#include "angelscript.h"
|
||||
#include "scriptstdstring.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
asIScriptEngine* engine = nullptr;
|
||||
std::string scriptFile = "scripts/test.as";
|
||||
std::time_t lastWriteTime = 0;
|
||||
|
||||
// Cached script functions
|
||||
asIScriptFunction* updateFunc = nullptr;
|
||||
asIScriptFunction* drawFunc = nullptr;
|
||||
|
||||
// -------------------------
|
||||
// Functions exposed to AngelScript
|
||||
// -------------------------
|
||||
void Print(const std::string &msg) {
|
||||
std::cout << "[Script] " << msg << std::endl;
|
||||
}
|
||||
|
||||
Color ColorFromUInt(unsigned int c) {
|
||||
Color col;
|
||||
col.r = (c >> 24) & 0xFF;
|
||||
col.g = (c >> 16) & 0xFF;
|
||||
col.b = (c >> 8) & 0xFF;
|
||||
col.a = c & 0xFF;
|
||||
return col;
|
||||
}
|
||||
|
||||
void AS_DrawText(const std::string &text, int x, int y, int fontSize, unsigned int color) {
|
||||
DrawText(text.c_str(), x, y, fontSize, ColorFromUInt(color));
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// AngelScript message callback
|
||||
// -------------------------
|
||||
void AngelScriptMessageCallback(const asSMessageInfo* msg, void* param) {
|
||||
std::cout << msg->section << " (" << msg->row << "): " << msg->message << std::endl;
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Utility to read script files
|
||||
// -------------------------
|
||||
std::string ReadFile(const std::string &filename) {
|
||||
std::ifstream file(filename);
|
||||
if (!file) return "";
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Compile script and cache Update/Draw
|
||||
// -------------------------
|
||||
bool compileScript(const std::string& filename) {
|
||||
engine->GarbageCollect();
|
||||
asIScriptModule* mod = engine->GetModule("main", asGM_ALWAYS_CREATE);
|
||||
|
||||
std::string code = ReadFile(filename);
|
||||
if (code.empty()) {
|
||||
std::cerr << "Failed to read script file: " << filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
int r = mod->AddScriptSection(filename.c_str(), code.c_str());
|
||||
if (r < 0) return false;
|
||||
|
||||
r = mod->Build();
|
||||
if (r < 0) return false;
|
||||
|
||||
// Cache Update(float dt) and Draw() functions if they exist
|
||||
updateFunc = mod->GetFunctionByName("Update");
|
||||
drawFunc = mod->GetFunctionByName("Draw");
|
||||
|
||||
std::cout << "Script compiled and cached: " << filename << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Hot reload check
|
||||
// -------------------------
|
||||
void checkHotReload() {
|
||||
auto ftime = fs::last_write_time(scriptFile);
|
||||
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
|
||||
std::time_t t = std::chrono::system_clock::to_time_t(sctp);
|
||||
if (t != lastWriteTime) {
|
||||
lastWriteTime = t;
|
||||
compileScript(scriptFile);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Call a cached script function
|
||||
// -------------------------
|
||||
void callScriptFunction(asIScriptFunction* func, float dt = 0.0f) {
|
||||
if (!func) return;
|
||||
|
||||
asIScriptContext* ctx = engine->CreateContext();
|
||||
ctx->Prepare(func);
|
||||
|
||||
if (func->GetParamCount() == 1) {
|
||||
ctx->SetArgFloat(0, dt);
|
||||
}
|
||||
|
||||
ctx->Execute();
|
||||
ctx->Release();
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Main
|
||||
// -------------------------
|
||||
int main() {
|
||||
// Initialize Raylib
|
||||
InitWindow(800, 600, "Raylib + AngelScript");
|
||||
SetTargetFPS(60);
|
||||
|
||||
// Initialize AngelScript
|
||||
engine = asCreateScriptEngine();
|
||||
assert(engine);
|
||||
|
||||
RegisterStdString(engine);
|
||||
engine->RegisterGlobalFunction("void DrawText(const string &in, int, int, int, uint)",
|
||||
asFUNCTION(AS_DrawText), asCALL_CDECL);
|
||||
|
||||
int r = engine->SetMessageCallback(asFUNCTION(AngelScriptMessageCallback), nullptr, asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
|
||||
r = engine->RegisterGlobalFunction("void Print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
|
||||
compileScript(scriptFile);
|
||||
|
||||
// Main loop
|
||||
while (!WindowShouldClose()) {
|
||||
float dt = GetFrameTime();
|
||||
|
||||
checkHotReload();
|
||||
|
||||
callScriptFunction(updateFunc, dt);
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Modify scripts/test.as to hot-reload!", 50, 50, 20, DARKGRAY);
|
||||
|
||||
callScriptFunction(drawFunc);
|
||||
|
||||
EndDrawing();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
Application app;
|
||||
|
||||
if (!app.Initialize()) {
|
||||
std::cerr << "Failed to initialize application\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
CloseWindow();
|
||||
engine->ShutDownAndRelease();
|
||||
|
||||
app.Run();
|
||||
app.Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ float x = 50;
|
||||
float y = 100;
|
||||
|
||||
void Update(float dt) {
|
||||
x += 50 * dt; // move text horizontally
|
||||
x += 50 * dt;
|
||||
if (x > 800) x = 0;
|
||||
}
|
||||
|
||||
void Draw() {
|
||||
DrawText("Hello from AngelScript!", int(x), int(y), 20, 0xFF0000FF);
|
||||
}
|
||||
DrawText("Hello from AngelScript - Working perfectly!", int(x), int(y), 20, 0xFF0000FF);
|
||||
}
|
||||
88
src/Application.cpp
Normal file
88
src/Application.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "Application.h"
|
||||
#include "raylib.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
const char* Application::WINDOW_TITLE = "Raylib + AngelScript";
|
||||
const char* Application::SCRIPT_FILE = "scripts/test.as";
|
||||
|
||||
Application::Application() : hotReload(nullptr), scriptCompilationError(false) {
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool Application::Initialize() {
|
||||
// Initialize Raylib
|
||||
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE);
|
||||
SetTargetFPS(TARGET_FPS);
|
||||
|
||||
// Initialize AngelScript
|
||||
if (!scriptEngine.Initialize()) {
|
||||
std::cerr << "Failed to initialize script engine\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize hot reload
|
||||
hotReload = new HotReload(SCRIPT_FILE);
|
||||
|
||||
// Compile initial script
|
||||
scriptCompilationError = !scriptEngine.CompileScript(SCRIPT_FILE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Run() {
|
||||
while (!WindowShouldClose()) {
|
||||
float deltaTime = GetFrameTime();
|
||||
|
||||
Update(deltaTime);
|
||||
Draw();
|
||||
|
||||
// Small sleep to prevent excessive CPU usage
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Update(float deltaTime) {
|
||||
// Check for hot reload
|
||||
if (hotReload && hotReload->CheckForChanges()) {
|
||||
bool success = scriptEngine.CompileScript(SCRIPT_FILE);
|
||||
scriptCompilationError = !success;
|
||||
if (!success) {
|
||||
std::cout << "Script compilation failed - keeping previous version\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Call script Update function
|
||||
scriptEngine.CallScriptFunction(scriptEngine.GetUpdateFunction(), deltaTime);
|
||||
}
|
||||
|
||||
void Application::Draw() {
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Show script error status in top left if there's an error, otherwise show normal message
|
||||
if (scriptCompilationError) {
|
||||
DrawText("SCRIPT ERROR - Check console for details", 10, 10, 16, RED);
|
||||
} else {
|
||||
DrawText("Modify scripts/test.as to hot-reload!", 50, 50, 20, DARKGRAY);
|
||||
}
|
||||
|
||||
// Call script Draw function
|
||||
scriptEngine.CallScriptFunction(scriptEngine.GetDrawFunction());
|
||||
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
void Application::Shutdown() {
|
||||
if (hotReload) {
|
||||
delete hotReload;
|
||||
hotReload = nullptr;
|
||||
}
|
||||
|
||||
scriptEngine.Shutdown();
|
||||
CloseWindow();
|
||||
}
|
||||
32
src/HotReload.cpp
Normal file
32
src/HotReload.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "HotReload.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
HotReload::HotReload(const std::string& filename) : scriptFile(filename), lastWriteTime(0) {
|
||||
UpdateLastWriteTime();
|
||||
}
|
||||
|
||||
bool HotReload::CheckForChanges() {
|
||||
std::time_t currentWriteTime = GetFileWriteTime(scriptFile);
|
||||
if (currentWriteTime != lastWriteTime) {
|
||||
lastWriteTime = currentWriteTime;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HotReload::UpdateLastWriteTime() {
|
||||
lastWriteTime = GetFileWriteTime(scriptFile);
|
||||
}
|
||||
|
||||
std::time_t HotReload::GetFileWriteTime(const std::string& filename) {
|
||||
try {
|
||||
auto ftime = fs::last_write_time(filename);
|
||||
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
|
||||
ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
|
||||
return std::chrono::system_clock::to_time_t(sctp);
|
||||
} catch (const std::exception&) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
33
src/ScriptBindings.cpp
Normal file
33
src/ScriptBindings.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "ScriptBindings.h"
|
||||
#include "raylib.h"
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
void ScriptBindings::RegisterAll(asIScriptEngine* engine) {
|
||||
// Register Print function
|
||||
int r = engine->RegisterGlobalFunction("void Print(const string &in)",
|
||||
asFUNCTION(Print), asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
|
||||
// Register DrawText function
|
||||
r = engine->RegisterGlobalFunction("void DrawText(const string &in, int, int, int, uint)",
|
||||
asFUNCTION(AS_DrawText), asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
}
|
||||
|
||||
void ScriptBindings::Print(const std::string &msg) {
|
||||
std::cout << "[Script] " << msg << std::endl;
|
||||
}
|
||||
|
||||
Color ColorFromUInt(unsigned int c) {
|
||||
Color col;
|
||||
col.r = (c >> 24) & 0xFF;
|
||||
col.g = (c >> 16) & 0xFF;
|
||||
col.b = (c >> 8) & 0xFF;
|
||||
col.a = c & 0xFF;
|
||||
return col;
|
||||
}
|
||||
|
||||
void ScriptBindings::AS_DrawText(const std::string &text, int x, int y, int fontSize, unsigned int color) {
|
||||
DrawText(text.c_str(), x, y, fontSize, ColorFromUInt(color));
|
||||
}
|
||||
155
src/ScriptEngine.cpp
Normal file
155
src/ScriptEngine.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
#include "ScriptEngine.h"
|
||||
#include "ScriptBindings.h"
|
||||
#include "scriptstdstring.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
ScriptEngine::ScriptEngine() : engine(nullptr), updateFunc(nullptr), drawFunc(nullptr), currentModule(nullptr), hasValidScript(false) {
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool ScriptEngine::Initialize() {
|
||||
engine = asCreateScriptEngine();
|
||||
if (!engine) {
|
||||
std::cerr << "Failed to create AngelScript engine\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Register std::string
|
||||
RegisterStdString(engine);
|
||||
|
||||
// Register script bindings
|
||||
ScriptBindings::RegisterAll(engine);
|
||||
|
||||
// Set message callback
|
||||
int r = engine->SetMessageCallback(asFUNCTION(MessageCallback), nullptr, asCALL_CDECL);
|
||||
if (r < 0) {
|
||||
std::cerr << "Failed to set message callback\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEngine::Shutdown() {
|
||||
ClearCachedFunctions();
|
||||
if (engine) {
|
||||
engine->ShutDownAndRelease();
|
||||
engine = nullptr;
|
||||
}
|
||||
currentModule = nullptr;
|
||||
hasValidScript = false;
|
||||
}
|
||||
|
||||
bool ScriptEngine::CompileScript(const std::string& filename) {
|
||||
if (!engine) return false;
|
||||
|
||||
std::string code = ReadFile(filename);
|
||||
if (code.empty()) {
|
||||
std::cerr << "Failed to read script file: " << filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to compile in a temporary module first
|
||||
asIScriptModule* tempMod = engine->GetModule("temp", asGM_ALWAYS_CREATE);
|
||||
|
||||
int r = tempMod->AddScriptSection(filename.c_str(), code.c_str());
|
||||
if (r < 0) {
|
||||
std::cerr << "Failed to add script section for: " << filename << "\n";
|
||||
engine->DiscardModule("temp");
|
||||
return false;
|
||||
}
|
||||
|
||||
r = tempMod->Build();
|
||||
if (r < 0) {
|
||||
std::cerr << "Failed to build script: " << filename << "\n";
|
||||
engine->DiscardModule("temp");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we get here, compilation succeeded
|
||||
// Now safely replace the main module
|
||||
if (currentModule) {
|
||||
engine->DiscardModule("main");
|
||||
}
|
||||
|
||||
// Create new main module with the working code
|
||||
currentModule = engine->GetModule("main", asGM_ALWAYS_CREATE);
|
||||
r = currentModule->AddScriptSection(filename.c_str(), code.c_str());
|
||||
if (r >= 0) {
|
||||
r = currentModule->Build();
|
||||
}
|
||||
|
||||
// Clean up temp module
|
||||
engine->DiscardModule("temp");
|
||||
|
||||
if (r < 0) {
|
||||
// This shouldn't happen since we already tested compilation
|
||||
std::cerr << "Unexpected error when creating main module\n";
|
||||
ClearCachedFunctions();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache new functions
|
||||
updateFunc = currentModule->GetFunctionByName("Update");
|
||||
drawFunc = currentModule->GetFunctionByName("Draw");
|
||||
hasValidScript = true;
|
||||
|
||||
std::cout << "Script compiled and cached: " << filename << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEngine::CallScriptFunction(asIScriptFunction* func, float dt) {
|
||||
if (!func || !engine || !hasValidScript) return;
|
||||
|
||||
asIScriptContext* ctx = engine->CreateContext();
|
||||
if (!ctx) return;
|
||||
|
||||
int r = ctx->Prepare(func);
|
||||
if (r < 0) {
|
||||
ctx->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (func->GetParamCount() == 1) {
|
||||
ctx->SetArgFloat(0, dt);
|
||||
}
|
||||
|
||||
r = ctx->Execute();
|
||||
if (r != asEXECUTION_FINISHED) {
|
||||
if (r == asEXECUTION_EXCEPTION) {
|
||||
std::cerr << "Script exception: " << ctx->GetExceptionString() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
ctx->Release();
|
||||
}
|
||||
|
||||
void ScriptEngine::ClearCachedFunctions() {
|
||||
updateFunc = nullptr;
|
||||
drawFunc = nullptr;
|
||||
hasValidScript = false;
|
||||
}
|
||||
|
||||
void ScriptEngine::GarbageCollect() {
|
||||
if (engine) {
|
||||
engine->GarbageCollect();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::MessageCallback(const asSMessageInfo* msg, void*) {
|
||||
std::cout << msg->section << " (" << msg->row << "): " << msg->message << std::endl;
|
||||
}
|
||||
|
||||
std::string ScriptEngine::ReadFile(const std::string& filename) {
|
||||
std::ifstream file(filename);
|
||||
if (!file) return "";
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
return ss.str();
|
||||
}
|
||||
Reference in New Issue
Block a user