Files
simian/main.cpp

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();
}