feat: hot reload and draw text example
This commit is contained in:
144
main.cpp
144
main.cpp
@@ -1,9 +1,22 @@
|
||||
#include "raylib.h"
|
||||
#include <angelscript.h>
|
||||
#include <scriptstdstring.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#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
|
||||
@@ -12,6 +25,19 @@ 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
|
||||
// -------------------------
|
||||
@@ -19,6 +45,74 @@ 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
|
||||
// -------------------------
|
||||
@@ -28,45 +122,41 @@ int main() {
|
||||
SetTargetFPS(60);
|
||||
|
||||
// Initialize AngelScript
|
||||
asIScriptEngine* engine = asCreateScriptEngine();
|
||||
engine = asCreateScriptEngine();
|
||||
assert(engine);
|
||||
|
||||
RegisterStdString(engine);
|
||||
engine->RegisterGlobalFunction("void DrawText(const string &in, int, int, int, uint)",
|
||||
asFUNCTION(AS_DrawText), asCALL_CDECL);
|
||||
|
||||
// Register the message callback
|
||||
int r = engine->SetMessageCallback(asFUNCTION(AngelScriptMessageCallback), nullptr, asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
|
||||
// Register the Print function for scripts
|
||||
r = engine->RegisterGlobalFunction("void Print(const string &in)", asFUNCTION(Print), asCALL_CDECL);
|
||||
assert(r >= 0);
|
||||
|
||||
// Create a module and add a simple script
|
||||
asIScriptModule* mod = engine->GetModule("Game", asGM_ALWAYS_CREATE);
|
||||
const char* scriptCode =
|
||||
"void main() { "
|
||||
" Print('Hello from AngelScript!'); "
|
||||
"}";
|
||||
mod->AddScriptSection("test", scriptCode);
|
||||
r = mod->Build();
|
||||
if (r < 0) std::cerr << "Failed to build script.\n";
|
||||
|
||||
// Prepare and execute the script
|
||||
asIScriptFunction* func = mod->GetFunctionByDecl("void main()");
|
||||
asIScriptContext* ctx = engine->CreateContext();
|
||||
ctx->Prepare(func);
|
||||
ctx->Execute();
|
||||
ctx->Release();
|
||||
compileScript(scriptFile);
|
||||
|
||||
// Main loop
|
||||
while (!WindowShouldClose()) {
|
||||
float dt = GetFrameTime();
|
||||
|
||||
checkHotReload();
|
||||
|
||||
callScriptFunction(updateFunc, dt);
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
DrawText("Raylib + AngelScript running!", 180, 280, 20, DARKGRAY);
|
||||
|
||||
DrawText("Modify scripts/test.as to hot-reload!", 50, 50, 20, DARKGRAY);
|
||||
|
||||
callScriptFunction(drawFunc);
|
||||
|
||||
EndDrawing();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
// Clean up
|
||||
CloseWindow();
|
||||
engine->Release();
|
||||
engine->ShutDownAndRelease();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user