3.6 KiB
3.6 KiB
Modularity C++ Scripting Quickstart
Project setup
- Scripts live under
Scripts/(configurable viaScripts.modu). - The engine generates a wrapper per script when compiling. It exports fixed entry points with
extern "C"linkage:Script_OnInspector(ScriptContext&)Script_Begin(ScriptContext&, float deltaTime)Script_Spec(ScriptContext&, float deltaTime)Script_TestEditor(ScriptContext&, float deltaTime)Script_Update(ScriptContext&, float deltaTime)(fallback if TickUpdate is absent)Script_TickUpdate(ScriptContext&, float deltaTime)
- Build config file:
Scripts.modu(auto-created per project). Keys:scriptsDir,outDir,includeDir=...,define=...,linux.linkLib,win.linkLib,cppStandard.
Lifecycle hooks
- Inspector:
Script_OnInspector(ScriptContext&)is called when the script is inspected in the UI. - Begin:
Script_Beginruns once per object instance before ticking. - Spec/Test:
Script_SpecandScript_TestEditorrun every frame when the global “Spec Mode” / “Test Mode” toggles are enabled (Scripts menu). - Tick:
Script_TickUpdateruns every frame for each script;Script_Updateis a fallback if TickUpdate is missing. - All tick-style hooks receive
deltaTime(seconds) and theScriptContext.
ScriptContext helpers
Available methods:
FindObjectByName,FindObjectByIdSetPosition,SetRotation,SetScaleHasRigidbodySetRigidbodyVelocity,GetRigidbodyVelocitySetRigidbodyAngularVelocity,GetRigidbodyAngularVelocityAddRigidbodyForce,AddRigidbodyImpulseAddRigidbodyTorque,AddRigidbodyAngularImpulseSetRigidbodyRotation,TeleportRigidbodyMarkDirty(flags the project as having unsaved changes) Fields:engine: pointer to the Engineobject: pointer to the owningSceneObjectscript: pointer to the owningScriptComponent(gives access to per-scriptsettings)
Persisting per-script settings
- Each
ScriptComponenthassettings(key/value strings) serialized with the scene. - You can read/write them via
ctx.script->settingsor helper functions in your script. - After mutating settings or object transforms, call
ctx.MarkDirty()so Ctrl+S captures changes.
Example pattern (simplified)
static bool autoRotate = false;
static glm::vec3 speed = {0, 45, 0};
void Script_OnInspector(ScriptContext& ctx) {
ImGui::Checkbox("Auto Rotate", &autoRotate);
ImGui::DragFloat3("Speed", &speed.x, 1.f, -360.f, 360.f);
ctx.MarkDirty();
}
void Script_Begin(ScriptContext& ctx, float) {
ctx.MarkDirty(); // ensure initial state is saved
}
void Script_TickUpdate(ScriptContext& ctx, float dt) {
if (autoRotate && ctx.object) {
ctx.SetRotation(ctx.object->rotation + speed * dt);
}
}
Runtime behavior
- Scripts tick for all objects every frame, even if not selected.
- Spec/Test toggles are global (main menu → Scripts).
- Compile scripts via the UI “Compile Script” button or run the build command; wrapper generation is automatic.
Manual compile (CLI)
Linux example:
g++ -std=c++20 -fPIC -O0 -g -I../src -I../include -c SampleInspector.cpp -o ../Cache/ScriptBin/SampleInspector.o
g++ -shared ../Cache/ScriptBin/SampleInspector.o -o ../Cache/ScriptBin/SampleInspector.so -ldl -lpthread
Windows example:
cl /nologo /std:c++20 /EHsc /MD /Zi /Od /I ..\\src /I ..\\include /c SampleInspector.cpp /Fo ..\\Cache\\ScriptBin\\SampleInspector.obj
link /nologo /DLL ..\\Cache\\ScriptBin\\SampleInspector.obj /OUT:..\\Cache\\ScriptBin\\SampleInspector.dll User32.lib Advapi32.lib