More Coding Stuff. Yey!
This commit is contained in:
66
Scripts/SampleInspector Simplified.cpp
Normal file
66
Scripts/SampleInspector Simplified.cpp
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#include "ScriptRuntime.h"
|
||||||
|
#include "SceneObject.h"
|
||||||
|
#include "ThirdParty/imgui/imgui.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Script state (persisted by AutoSetting binder)
|
||||||
|
bool autoRotate = false;
|
||||||
|
glm::vec3 spinSpeed = glm::vec3(0.0f, 45.0f, 0.0f); // deg/sec
|
||||||
|
glm::vec3 offset = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
char targetName[128] = "MyTarget";
|
||||||
|
|
||||||
|
// Runtime behavior
|
||||||
|
static void ApplyAutoRotate(ScriptContext& ctx, float deltaTime) {
|
||||||
|
if (!autoRotate || !ctx.object) return;
|
||||||
|
ctx.SetRotation(ctx.object->rotation + spinSpeed * deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||||
|
// Auto settings (loaded once, saved only when changed)
|
||||||
|
ctx.AutoSetting("autoRotate", autoRotate);
|
||||||
|
ctx.AutoSetting("spinSpeed", spinSpeed);
|
||||||
|
ctx.AutoSetting("offset", offset);
|
||||||
|
ctx.AutoSetting("targetName", targetName, sizeof(targetName));
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("SampleInspector");
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
changed |= ImGui::Checkbox("Auto Rotate", &autoRotate);
|
||||||
|
changed |= ImGui::DragFloat3("Spin Speed (deg/s)", &spinSpeed.x, 1.0f, -360.0f, 360.0f);
|
||||||
|
changed |= ImGui::DragFloat3("Offset", &offset.x, 0.1f);
|
||||||
|
changed |= ImGui::InputText("Target Name", targetName, sizeof(targetName));
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
ctx.SaveAutoSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.object) {
|
||||||
|
ImGui::TextDisabled("Attached to: %s (id=%d)", ctx.object->name.c_str(), ctx.object->id);
|
||||||
|
|
||||||
|
if (ImGui::Button("Apply Offset To Self")) {
|
||||||
|
ctx.SetPosition(ctx.object->position + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ImGui::Button("Nudge Target")) {
|
||||||
|
if (SceneObject* target = ctx.FindObjectByName(targetName)) {
|
||||||
|
target->position += offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Begin(ScriptContext& ctx, float /*deltaTime*/) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spec(ScriptContext& ctx, float deltaTime) {
|
||||||
|
ApplyAutoRotate(ctx, deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestEditor(ScriptContext& ctx, float deltaTime) {
|
||||||
|
ApplyAutoRotate(ctx, deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TickUpdate(ScriptContext& ctx, float deltaTime) {
|
||||||
|
ApplyAutoRotate(ctx, deltaTime);
|
||||||
|
}
|
||||||
10
src/Common.h
10
src/Common.h
@@ -14,6 +14,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include "ThirdParty/imgui/imgui.h"
|
#include "ThirdParty/imgui/imgui.h"
|
||||||
@@ -41,6 +42,15 @@ constexpr float NEAR_PLANE = 0.1f;
|
|||||||
constexpr float FAR_PLANE = 100.0f;
|
constexpr float FAR_PLANE = 100.0f;
|
||||||
constexpr float PI = 3.14159265359f;
|
constexpr float PI = 3.14159265359f;
|
||||||
|
|
||||||
|
inline glm::vec3 NormalizeEulerDegrees(const glm::vec3& deg) {
|
||||||
|
auto wrap = [](float a) {
|
||||||
|
float r = std::fmod(a, 360.0f);
|
||||||
|
if (r < 0.0f) r += 360.0f;
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
return glm::vec3(wrap(deg.x), wrap(deg.y), wrap(deg.z));
|
||||||
|
}
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class OBJLoader;
|
class OBJLoader;
|
||||||
|
|||||||
@@ -1031,6 +1031,10 @@ void Engine::logToConsole(const std::string& message) {
|
|||||||
addConsoleMessage(message, ConsoleMessageType::Info);
|
addConsoleMessage(message, ConsoleMessageType::Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::addConsoleMessageFromScript(const std::string& message, ConsoleMessageType type) {
|
||||||
|
addConsoleMessage(message, type);
|
||||||
|
}
|
||||||
|
|
||||||
SceneObject* Engine::findObjectByName(const std::string& name) {
|
SceneObject* Engine::findObjectByName(const std::string& name) {
|
||||||
auto it = std::find_if(sceneObjects.begin(), sceneObjects.end(), [&](const SceneObject& o) {
|
auto it = std::find_if(sceneObjects.begin(), sceneObjects.end(), [&](const SceneObject& o) {
|
||||||
return o.name == name;
|
return o.name == name;
|
||||||
|
|||||||
@@ -204,4 +204,6 @@ public:
|
|||||||
SceneObject* findObjectById(int id);
|
SceneObject* findObjectById(int id);
|
||||||
fs::path resolveScriptBinary(const fs::path& sourcePath);
|
fs::path resolveScriptBinary(const fs::path& sourcePath);
|
||||||
void markProjectDirty();
|
void markProjectDirty();
|
||||||
|
// Script-accessible logging wrapper
|
||||||
|
void addConsoleMessageFromScript(const std::string& message, ConsoleMessageType type);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1853,6 +1853,7 @@ void Engine::renderInspectorPanel() {
|
|||||||
ImGui::Text("Rotation");
|
ImGui::Text("Rotation");
|
||||||
ImGui::PushItemWidth(-1);
|
ImGui::PushItemWidth(-1);
|
||||||
if (ImGui::DragFloat3("##Rotation", &obj.rotation.x, 1.0f, -360.0f, 360.0f)) {
|
if (ImGui::DragFloat3("##Rotation", &obj.rotation.x, 1.0f, -360.0f, 360.0f)) {
|
||||||
|
obj.rotation = NormalizeEulerDegrees(obj.rotation);
|
||||||
projectManager.currentProject.hasUnsavedChanges = true;
|
projectManager.currentProject.hasUnsavedChanges = true;
|
||||||
}
|
}
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
@@ -3176,7 +3177,7 @@ void Engine::renderViewport() {
|
|||||||
glm::vec3 t, r, s;
|
glm::vec3 t, r, s;
|
||||||
DecomposeMatrix(newM, t, r, s);
|
DecomposeMatrix(newM, t, r, s);
|
||||||
o.position = t;
|
o.position = t;
|
||||||
o.rotation = glm::degrees(r);
|
o.rotation = NormalizeEulerDegrees(glm::degrees(r));
|
||||||
o.scale = s;
|
o.scale = s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ bool SceneSerializer::loadScene(const fs::path& filePath,
|
|||||||
¤tObj->rotation.x,
|
¤tObj->rotation.x,
|
||||||
¤tObj->rotation.y,
|
¤tObj->rotation.y,
|
||||||
¤tObj->rotation.z);
|
¤tObj->rotation.z);
|
||||||
|
currentObj->rotation = NormalizeEulerDegrees(currentObj->rotation);
|
||||||
} else if (key == "scale") {
|
} else if (key == "scale") {
|
||||||
sscanf(value.c_str(), "%f,%f,%f",
|
sscanf(value.c_str(), "%f,%f,%f",
|
||||||
¤tObj->scale.x,
|
¤tObj->scale.x,
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ struct ScriptComponent {
|
|||||||
std::string path;
|
std::string path;
|
||||||
std::vector<ScriptSetting> settings;
|
std::vector<ScriptSetting> settings;
|
||||||
std::string lastBinaryPath;
|
std::string lastBinaryPath;
|
||||||
|
std::vector<void*> activeIEnums; // function pointers registered via IEnum_Start
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneObject {
|
class SceneObject {
|
||||||
|
|||||||
@@ -204,10 +204,11 @@ bool ScriptCompiler::makeCommands(const ScriptBuildConfig& config, const fs::pat
|
|||||||
auto detectFunction = [](const std::string& source, const std::string& name) -> FunctionSpec {
|
auto detectFunction = [](const std::string& source, const std::string& name) -> FunctionSpec {
|
||||||
FunctionSpec spec;
|
FunctionSpec spec;
|
||||||
try {
|
try {
|
||||||
std::regex ctxDeltaPattern("\\bvoid\\s+" + name + "\\s*\\(\\s*ScriptContext\\s*[&*][^,\\)]*,[^\\)]*(float|double)[^\\)]*\\)");
|
const std::string prefix = "\\bvoid\\s+(?:IEnum\\s+)?";
|
||||||
std::regex ctxOnlyPattern("\\bvoid\\s+" + name + "\\s*\\(\\s*ScriptContext\\s*[&*][^\\)]*\\)");
|
std::regex ctxDeltaPattern(prefix + name + "\\s*\\(\\s*ScriptContext\\s*[&*][^,\\)]*,[^\\)]*(float|double)[^\\)]*\\)");
|
||||||
std::regex deltaPattern("\\bvoid\\s+" + name + "\\s*\\(\\s*(float|double)[^\\)]*\\)");
|
std::regex ctxOnlyPattern(prefix + name + "\\s*\\(\\s*ScriptContext\\s*[&*][^\\)]*\\)");
|
||||||
std::regex basicPattern("\\bvoid\\s+" + name + "\\s*\\(\\s*\\)");
|
std::regex deltaPattern(prefix + name + "\\s*\\(\\s*(float|double)[^\\)]*\\)");
|
||||||
|
std::regex basicPattern(prefix + name + "\\s*\\(\\s*\\)");
|
||||||
|
|
||||||
if (std::regex_search(source, ctxDeltaPattern)) {
|
if (std::regex_search(source, ctxDeltaPattern)) {
|
||||||
spec.present = true;
|
spec.present = true;
|
||||||
|
|||||||
@@ -19,15 +19,191 @@ SceneObject* ScriptContext::FindObjectById(int id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScriptContext::SetPosition(const glm::vec3& pos) {
|
void ScriptContext::SetPosition(const glm::vec3& pos) {
|
||||||
if (object) object->position = pos;
|
if (object) {
|
||||||
|
object->position = pos;
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptContext::SetRotation(const glm::vec3& rot) {
|
void ScriptContext::SetRotation(const glm::vec3& rot) {
|
||||||
if (object) object->rotation = rot;
|
if (object) {
|
||||||
|
object->rotation = NormalizeEulerDegrees(rot);
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptContext::SetScale(const glm::vec3& scl) {
|
void ScriptContext::SetScale(const glm::vec3& scl) {
|
||||||
if (object) object->scale = scl;
|
if (object) {
|
||||||
|
object->scale = scl;
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ScriptContext::GetSetting(const std::string& key, const std::string& fallback) const {
|
||||||
|
if (!script) return fallback;
|
||||||
|
auto it = std::find_if(script->settings.begin(), script->settings.end(),
|
||||||
|
[&](const ScriptSetting& s){ return s.key == key; });
|
||||||
|
return (it != script->settings.end()) ? it->value : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::SetSetting(const std::string& key, const std::string& value) {
|
||||||
|
if (!script) return;
|
||||||
|
auto it = std::find_if(script->settings.begin(), script->settings.end(),
|
||||||
|
[&](const ScriptSetting& s){ return s.key == key; });
|
||||||
|
if (it != script->settings.end()) {
|
||||||
|
it->value = value;
|
||||||
|
} else {
|
||||||
|
script->settings.push_back({key, value});
|
||||||
|
}
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptContext::GetSettingBool(const std::string& key, bool fallback) const {
|
||||||
|
std::string v = GetSetting(key, fallback ? "1" : "0");
|
||||||
|
if (v == "1" || v == "true" || v == "True") return true;
|
||||||
|
if (v == "0" || v == "false" || v == "False") return false;
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::SetSettingBool(const std::string& key, bool value) {
|
||||||
|
SetSetting(key, value ? "1" : "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 ScriptContext::GetSettingVec3(const std::string& key, const glm::vec3& fallback) const {
|
||||||
|
std::string v = GetSetting(key, "");
|
||||||
|
if (v.empty()) return fallback;
|
||||||
|
glm::vec3 out = fallback;
|
||||||
|
std::stringstream ss(v);
|
||||||
|
std::string part;
|
||||||
|
for (int i = 0; i < 3 && std::getline(ss, part, ','); ++i) {
|
||||||
|
try { out[i] = std::stof(part); } catch (...) {}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::SetSettingVec3(const std::string& key, const glm::vec3& value) {
|
||||||
|
SetSetting(key,
|
||||||
|
std::to_string(value.x) + "," +
|
||||||
|
std::to_string(value.y) + "," +
|
||||||
|
std::to_string(value.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::AddConsoleMessage(const std::string& message, ConsoleMessageType type) {
|
||||||
|
if (engine) {
|
||||||
|
engine->addConsoleMessageFromScript(message, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::AutoSetting(const std::string& key, bool& value) {
|
||||||
|
if (!script) return;
|
||||||
|
if (autoSettings.end() != std::find_if(autoSettings.begin(), autoSettings.end(),
|
||||||
|
[&](const AutoSettingEntry& e){ return e.key == key; })) return;
|
||||||
|
|
||||||
|
value = GetSettingBool(key, value);
|
||||||
|
AutoSettingEntry entry;
|
||||||
|
entry.type = AutoSettingType::Bool;
|
||||||
|
entry.key = key;
|
||||||
|
entry.ptr = &value;
|
||||||
|
entry.initialBool = value;
|
||||||
|
autoSettings.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::AutoSetting(const std::string& key, glm::vec3& value) {
|
||||||
|
if (!script) return;
|
||||||
|
if (autoSettings.end() != std::find_if(autoSettings.begin(), autoSettings.end(),
|
||||||
|
[&](const AutoSettingEntry& e){ return e.key == key; })) return;
|
||||||
|
|
||||||
|
value = GetSettingVec3(key, value);
|
||||||
|
AutoSettingEntry entry;
|
||||||
|
entry.type = AutoSettingType::Vec3;
|
||||||
|
entry.key = key;
|
||||||
|
entry.ptr = &value;
|
||||||
|
entry.initialVec3 = value;
|
||||||
|
autoSettings.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::AutoSetting(const std::string& key, char* buffer, size_t bufferSize) {
|
||||||
|
if (!script || !buffer || bufferSize == 0) return;
|
||||||
|
if (autoSettings.end() != std::find_if(autoSettings.begin(), autoSettings.end(),
|
||||||
|
[&](const AutoSettingEntry& e){ return e.key == key; })) return;
|
||||||
|
|
||||||
|
std::string existing = GetSetting(key, std::string(buffer));
|
||||||
|
if (!existing.empty()) {
|
||||||
|
std::snprintf(buffer, bufferSize, "%s", existing.c_str());
|
||||||
|
}
|
||||||
|
AutoSettingEntry entry;
|
||||||
|
entry.type = AutoSettingType::StringBuf;
|
||||||
|
entry.key = key;
|
||||||
|
entry.ptr = buffer;
|
||||||
|
entry.bufSize = bufferSize;
|
||||||
|
entry.initialString = buffer;
|
||||||
|
autoSettings.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::SaveAutoSettings() {
|
||||||
|
if (!script) return;
|
||||||
|
bool changed = false;
|
||||||
|
for (const auto& e : autoSettings) {
|
||||||
|
std::string newVal;
|
||||||
|
switch (e.type) {
|
||||||
|
case AutoSettingType::Bool: {
|
||||||
|
bool cur = *static_cast<bool*>(e.ptr);
|
||||||
|
if (cur == e.initialBool) continue;
|
||||||
|
newVal = cur ? "1" : "0";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AutoSettingType::Vec3: {
|
||||||
|
glm::vec3 cur = *static_cast<glm::vec3*>(e.ptr);
|
||||||
|
if (glm::all(glm::epsilonEqual(cur, e.initialVec3, 1e-6f))) continue;
|
||||||
|
newVal = std::to_string(cur.x) + "," + std::to_string(cur.y) + "," + std::to_string(cur.z);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AutoSettingType::StringBuf: {
|
||||||
|
const char* cur = static_cast<const char*>(e.ptr);
|
||||||
|
if (cur && e.initialString == cur) continue;
|
||||||
|
newVal = cur ? cur : "";
|
||||||
|
if (!cur || newVal == e.initialString) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
SetSetting(e.key, newVal);
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::StartIEnum(void(*fn)(ScriptContext&, float)) {
|
||||||
|
if (!script || !fn) return;
|
||||||
|
auto& v = script->activeIEnums;
|
||||||
|
if (std::find(v.begin(), v.end(), reinterpret_cast<void*>(fn)) == v.end()) {
|
||||||
|
v.push_back(reinterpret_cast<void*>(fn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::StopIEnum(void(*fn)(ScriptContext&, float)) {
|
||||||
|
if (!script || !fn) return;
|
||||||
|
auto& v = script->activeIEnums;
|
||||||
|
auto it = std::find(v.begin(), v.end(), reinterpret_cast<void*>(fn));
|
||||||
|
if (it != v.end()) {
|
||||||
|
v.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::EnsureIEnum(void(*fn)(ScriptContext&, float)) {
|
||||||
|
if (!IsIEnumRunning(fn)) StartIEnum(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptContext::IsIEnumRunning(void(*fn)(ScriptContext&, float)) const {
|
||||||
|
if (!script || !fn) return false;
|
||||||
|
auto it = std::find(script->activeIEnums.begin(), script->activeIEnums.end(),
|
||||||
|
reinterpret_cast<void*>(fn));
|
||||||
|
return it != script->activeIEnums.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptContext::StopAllIEnums() {
|
||||||
|
if (script) script->activeIEnums.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptContext::MarkDirty() {
|
void ScriptContext::MarkDirty() {
|
||||||
@@ -133,6 +309,15 @@ void ScriptRuntime::tickModule(const fs::path& binaryPath, ScriptContext& ctx, f
|
|||||||
if (runTest && mod->testEditor) {
|
if (runTest && mod->testEditor) {
|
||||||
mod->testEditor(ctx, deltaTime);
|
mod->testEditor(ctx, deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tick any IEnum tasks registered by the script (per ScriptComponent instance).
|
||||||
|
if (ctx.script && !ctx.script->activeIEnums.empty()) {
|
||||||
|
auto tasks = ctx.script->activeIEnums; // copy so tasks can modify the list
|
||||||
|
for (void* p : tasks) {
|
||||||
|
auto fn = reinterpret_cast<IEnumFn>(p);
|
||||||
|
if (fn) fn(ctx, deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptRuntime::unloadAll() {
|
void ScriptRuntime::unloadAll() {
|
||||||
|
|||||||
@@ -10,6 +10,17 @@ struct ScriptContext {
|
|||||||
Engine* engine = nullptr;
|
Engine* engine = nullptr;
|
||||||
SceneObject* object = nullptr;
|
SceneObject* object = nullptr;
|
||||||
ScriptComponent* script = nullptr;
|
ScriptComponent* script = nullptr;
|
||||||
|
enum class AutoSettingType { Bool, Vec3, StringBuf };
|
||||||
|
struct AutoSettingEntry {
|
||||||
|
AutoSettingType type;
|
||||||
|
std::string key;
|
||||||
|
void* ptr = nullptr;
|
||||||
|
size_t bufSize = 0;
|
||||||
|
bool initialBool = false;
|
||||||
|
glm::vec3 initialVec3 = glm::vec3(0.0f);
|
||||||
|
std::string initialString;
|
||||||
|
};
|
||||||
|
std::vector<AutoSettingEntry> autoSettings;
|
||||||
|
|
||||||
// Convenience helpers for scripts
|
// Convenience helpers for scripts
|
||||||
SceneObject* FindObjectByName(const std::string& name);
|
SceneObject* FindObjectByName(const std::string& name);
|
||||||
@@ -17,6 +28,26 @@ struct ScriptContext {
|
|||||||
void SetPosition(const glm::vec3& pos);
|
void SetPosition(const glm::vec3& pos);
|
||||||
void SetRotation(const glm::vec3& rot);
|
void SetRotation(const glm::vec3& rot);
|
||||||
void SetScale(const glm::vec3& scl);
|
void SetScale(const glm::vec3& scl);
|
||||||
|
// Settings helpers (auto-mark dirty)
|
||||||
|
std::string GetSetting(const std::string& key, const std::string& fallback = "") const;
|
||||||
|
void SetSetting(const std::string& key, const std::string& value);
|
||||||
|
bool GetSettingBool(const std::string& key, bool fallback = false) const;
|
||||||
|
void SetSettingBool(const std::string& key, bool value);
|
||||||
|
glm::vec3 GetSettingVec3(const std::string& key, const glm::vec3& fallback = glm::vec3(0.0f)) const;
|
||||||
|
void SetSettingVec3(const std::string& key, const glm::vec3& value);
|
||||||
|
// Console helper
|
||||||
|
void AddConsoleMessage(const std::string& message, ConsoleMessageType type = ConsoleMessageType::Info);
|
||||||
|
// Auto-binding helpers: bind once per call, optionally load stored value, then SaveAutoSettings() writes back on change.
|
||||||
|
void AutoSetting(const std::string& key, bool& value);
|
||||||
|
void AutoSetting(const std::string& key, glm::vec3& value);
|
||||||
|
void AutoSetting(const std::string& key, char* buffer, size_t bufferSize);
|
||||||
|
void SaveAutoSettings();
|
||||||
|
// IEnum helpers
|
||||||
|
void StartIEnum(void(*fn)(ScriptContext&, float));
|
||||||
|
void StopIEnum(void(*fn)(ScriptContext&, float));
|
||||||
|
void EnsureIEnum(void(*fn)(ScriptContext&, float));
|
||||||
|
bool IsIEnumRunning(void(*fn)(ScriptContext&, float)) const;
|
||||||
|
void StopAllIEnums();
|
||||||
void MarkDirty();
|
void MarkDirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -28,6 +59,7 @@ public:
|
|||||||
using UpdateFn = void(*)(ScriptContext&, float);
|
using UpdateFn = void(*)(ScriptContext&, float);
|
||||||
using TickUpdateFn = void(*)(ScriptContext&, float);
|
using TickUpdateFn = void(*)(ScriptContext&, float);
|
||||||
using InspectorFn = void(*)(ScriptContext&);
|
using InspectorFn = void(*)(ScriptContext&);
|
||||||
|
using IEnumFn = void(*)(ScriptContext&, float);
|
||||||
|
|
||||||
InspectorFn getInspector(const fs::path& binaryPath);
|
InspectorFn getInspector(const fs::path& binaryPath);
|
||||||
void tickModule(const fs::path& binaryPath, ScriptContext& ctx, float deltaTime,
|
void tickModule(const fs::path& binaryPath, ScriptContext& ctx, float deltaTime,
|
||||||
@@ -50,3 +82,18 @@ private:
|
|||||||
std::unordered_map<std::string, Module> loaded;
|
std::unordered_map<std::string, Module> loaded;
|
||||||
std::string lastError;
|
std::string lastError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Lightweight coroutine-style helpers (opt-in and no-ops unless used by scripts).
|
||||||
|
#ifndef IEnum
|
||||||
|
#define IEnum
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IEnum_Start
|
||||||
|
#define IEnum_Start(fn) ctx.StartIEnum(fn)
|
||||||
|
#endif
|
||||||
|
#ifndef IEnum_Stop
|
||||||
|
#define IEnum_Stop(fn) ctx.StopIEnum(fn)
|
||||||
|
#endif
|
||||||
|
#ifndef IEnum_Ensure
|
||||||
|
#define IEnum_Ensure(fn) ctx.EnsureIEnum(fn)
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user