163 lines
4.3 KiB
C++
163 lines
4.3 KiB
C++
#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));
|
|
}
|
|
|
|
CloseWindow();
|
|
engine->ShutDownAndRelease();
|
|
}
|