Better Physics a little, New UI! And not only that, More simple scripting, Yey!!!!
This commit is contained in:
44
Scripts/FPSDisplay.cpp
Normal file
44
Scripts/FPSDisplay.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "ScriptRuntime.h"
|
||||
#include "SceneObject.h"
|
||||
#include "ThirdParty/imgui/imgui.h"
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
bool clampTo120 = false;
|
||||
float smoothFps = 0.0f;
|
||||
float smoothing = 0.15f;
|
||||
}
|
||||
|
||||
extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
ctx.AutoSetting("ClampFPS120", clampTo120);
|
||||
if (ctx.script) {
|
||||
std::string saved = ctx.GetSetting("FpsSmoothing", "");
|
||||
if (!saved.empty()) {
|
||||
try { smoothing = std::stof(saved); } catch (...) {}
|
||||
}
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
ImGui::TextUnformatted("FPS Display");
|
||||
ImGui::Separator();
|
||||
changed |= ImGui::Checkbox("Clamp FPS to 120", &clampTo120);
|
||||
changed |= ImGui::DragFloat("Smoothing", &smoothing, 0.01f, 0.0f, 1.0f, "%.2f");
|
||||
|
||||
if (changed) {
|
||||
ctx.SetFPSCap(clampTo120, 120.0f);
|
||||
ctx.SetSetting("FpsSmoothing", std::to_string(smoothing));
|
||||
ctx.SaveAutoSettings();
|
||||
}
|
||||
|
||||
ImGui::TextDisabled("Attach to a UI Text object.");
|
||||
}
|
||||
|
||||
void TickUpdate(ScriptContext& ctx, float deltaTime) {
|
||||
if (!ctx.object || ctx.object->type != ObjectType::UIText) return;
|
||||
float fps = (deltaTime > 1e-6f) ? (1.0f / deltaTime) : 0.0f;
|
||||
float k = std::clamp(smoothing, 0.0f, 1.0f);
|
||||
if (smoothFps <= 0.0f) smoothFps = fps;
|
||||
smoothFps = smoothFps + (fps - smoothFps) * k;
|
||||
ctx.object->ui.label = "FPS: " + std::to_string(static_cast<int>(smoothFps + 0.5f));
|
||||
}
|
||||
@@ -36,15 +36,10 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
ImGui::TextUnformatted("RigidbodyTest");
|
||||
ImGui::Separator();
|
||||
|
||||
bool changed = false;
|
||||
changed |= ImGui::Checkbox("Launch on Begin", &autoLaunch);
|
||||
changed |= ImGui::Checkbox("Show Velocity Readback", &showVelocity);
|
||||
changed |= ImGui::DragFloat3("Launch Velocity", &launchVelocity.x, 0.25f, -50.0f, 50.0f);
|
||||
changed |= ImGui::DragFloat3("Teleport Offset", &teleportOffset.x, 0.1f, -10.0f, 10.0f);
|
||||
|
||||
if (changed) {
|
||||
ctx.SaveAutoSettings();
|
||||
}
|
||||
ImGui::Checkbox("Launch on Begin", &autoLaunch);
|
||||
ImGui::Checkbox("Show Velocity Readback", &showVelocity);
|
||||
ImGui::DragFloat3("Launch Velocity", &launchVelocity.x, 0.25f, -50.0f, 50.0f);
|
||||
ImGui::DragFloat3("Teleport Offset", &teleportOffset.x, 0.1f, -10.0f, 10.0f);
|
||||
|
||||
if (ImGui::Button("Launch Now")) {
|
||||
Launch(ctx);
|
||||
@@ -76,4 +71,4 @@ void Begin(ScriptContext& ctx, float /*deltaTime*/) {
|
||||
if (autoLaunch) {
|
||||
Launch(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
#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);
|
||||
@@ -17,7 +15,6 @@ namespace {
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -26,15 +23,10 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
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();
|
||||
}
|
||||
ImGui::Checkbox("Auto Rotate", &autoRotate);
|
||||
ImGui::DragFloat3("Spin Speed (deg/s)", &spinSpeed.x, 1.0f, -360.0f, 360.0f);
|
||||
ImGui::DragFloat3("Offset", &offset.x, 0.1f);
|
||||
ImGui::InputText("Target Name", targetName, sizeof(targetName));
|
||||
|
||||
if (ctx.object) {
|
||||
ImGui::TextDisabled("Attached to: %s (id=%d)", ctx.object->name.c_str(), ctx.object->id);
|
||||
@@ -44,15 +36,12 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("Nudge Target")) {
|
||||
if (SceneObject* target = ctx.FindObjectByName(targetName)) {
|
||||
if (SceneObject* target = ctx.ResolveObjectRef(targetName)) {
|
||||
target->position += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Begin(ScriptContext& ctx, float /*deltaTime*/) {
|
||||
}
|
||||
|
||||
void Spec(ScriptContext& ctx, float deltaTime) {
|
||||
ApplyAutoRotate(ctx, deltaTime);
|
||||
}
|
||||
|
||||
@@ -8,101 +8,41 @@
|
||||
#include "ScriptRuntime.h"
|
||||
#include "SceneObject.h"
|
||||
#include "ThirdParty/imgui/imgui.h"
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
bool autoRotate = false;
|
||||
glm::vec3 spinSpeed = glm::vec3(0.0f, 45.0f, 0.0f);
|
||||
glm::vec3 offset = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
char targetName[128] = "MyTarget";
|
||||
int settingsLoadedForId = -1;
|
||||
ScriptComponent* settingsLoadedForScript = nullptr;
|
||||
|
||||
void setSetting(ScriptContext& ctx, const std::string& key, const std::string& value) {
|
||||
if (!ctx.script) return;
|
||||
auto it = std::find_if(ctx.script->settings.begin(), ctx.script->settings.end(),
|
||||
[&](const ScriptSetting& s) { return s.key == key; });
|
||||
if (it != ctx.script->settings.end()) {
|
||||
it->value = value;
|
||||
} else {
|
||||
ctx.script->settings.push_back({key, value});
|
||||
}
|
||||
}
|
||||
|
||||
std::string getSetting(const ScriptContext& ctx, const std::string& key, const std::string& fallback = "") {
|
||||
if (!ctx.script) return fallback;
|
||||
auto it = std::find_if(ctx.script->settings.begin(), ctx.script->settings.end(),
|
||||
[&](const ScriptSetting& s) { return s.key == key; });
|
||||
return (it != ctx.script->settings.end()) ? it->value : fallback;
|
||||
}
|
||||
|
||||
void loadSettings(ScriptContext& ctx) {
|
||||
if (!ctx.script || !ctx.object) return;
|
||||
if (settingsLoadedForId == ctx.object->id && settingsLoadedForScript == ctx.script) return;Segmentation fault (core dumped)
|
||||
settingsLoadedForId = ctx.object->id;
|
||||
settingsLoadedForScript = ctx.script;
|
||||
|
||||
auto parseBool = [](const std::string& v, bool def) {
|
||||
if (v == "1" || v == "true") return true;
|
||||
if (v == "0" || v == "false") return false;
|
||||
return def;
|
||||
};
|
||||
|
||||
auto parseVec3 = [](const std::string& v, const glm::vec3& def) {
|
||||
glm::vec3 out = def;
|
||||
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;
|
||||
};
|
||||
|
||||
autoRotate = parseBool(getSetting(ctx, "autoRotate", autoRotate ? "1" : "0"), autoRotate);
|
||||
spinSpeed = parseVec3(getSetting(ctx, "spinSpeed", ""), spinSpeed);
|
||||
offset = parseVec3(getSetting(ctx, "offset", ""), offset);
|
||||
std::string tgt = getSetting(ctx, "targetName", targetName);
|
||||
if (!tgt.empty()) {
|
||||
std::snprintf(targetName, sizeof(targetName), "%s", tgt.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void persistSettings(ScriptContext& ctx) {
|
||||
setSetting(ctx, "autoRotate", autoRotate ? "1" : "0");
|
||||
setSetting(ctx, "spinSpeed",
|
||||
std::to_string(spinSpeed.x) + "," + std::to_string(spinSpeed.y) + "," + std::to_string(spinSpeed.z));
|
||||
setSetting(ctx, "offset",
|
||||
std::to_string(offset.x) + "," + std::to_string(offset.y) + "," + std::to_string(offset.z));
|
||||
setSetting(ctx, "targetName", targetName);
|
||||
ctx.MarkDirty();
|
||||
void bindSettings(ScriptContext& ctx) {
|
||||
ctx.AutoSetting("autoRotate", autoRotate);
|
||||
ctx.AutoSetting("spinSpeed", spinSpeed);
|
||||
ctx.AutoSetting("offset", offset);
|
||||
ctx.AutoSetting("targetName", targetName, sizeof(targetName));
|
||||
}
|
||||
|
||||
void applyAutoRotate(ScriptContext& ctx, float deltaTime) {
|
||||
if (!autoRotate || !ctx.object) return;
|
||||
if (ctx.HasRigidbody() && !ctx.object->rigidbody.isKinematic) {
|
||||
if (ctx.SetRigidbodyAngularVelocity(glm::radians(spinSpeed))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.SetRotation(ctx.object->rotation + spinSpeed * deltaTime);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
loadSettings(ctx);
|
||||
bindSettings(ctx);
|
||||
|
||||
ImGui::TextUnformatted("SampleInspector");
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Checkbox("Auto Rotate", &autoRotate)) {
|
||||
persistSettings(ctx);
|
||||
}
|
||||
if (ImGui::DragFloat3("Spin Speed (deg/s)", &spinSpeed.x, 1.0f, -360.0f, 360.0f)) {
|
||||
persistSettings(ctx);
|
||||
}
|
||||
if (ImGui::DragFloat3("Offset", &offset.x, 0.1f)) {
|
||||
persistSettings(ctx);
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Auto Rotate", &autoRotate);
|
||||
ImGui::DragFloat3("Spin Speed (deg/s)", &spinSpeed.x, 1.0f, -360.0f, 360.0f);
|
||||
ImGui::DragFloat3("Offset", &offset.x, 0.1f);
|
||||
ImGui::InputText("Target Name", targetName, sizeof(targetName));
|
||||
persistSettings(ctx);
|
||||
|
||||
if (ctx.object) {
|
||||
ImGui::TextDisabled("Attached to: %s (id=%d)", ctx.object->name.c_str(), ctx.object->id);
|
||||
@@ -113,7 +53,7 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
}
|
||||
|
||||
if (ImGui::Button("Nudge Target")) {
|
||||
if (SceneObject* target = ctx.FindObjectByName(targetName)) {
|
||||
if (SceneObject* target = ctx.ResolveObjectRef(targetName)) {
|
||||
target->position += offset;
|
||||
}
|
||||
}
|
||||
@@ -122,7 +62,7 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
// New lifecycle hooks supported by the compiler wrapper. These are optional stubs demonstrating usage.
|
||||
void Begin(ScriptContext& ctx, float /*deltaTime*/) {
|
||||
// Initialize per-script state here.
|
||||
loadSettings(ctx);
|
||||
bindSettings(ctx);
|
||||
}
|
||||
|
||||
void Spec(ScriptContext& ctx, float deltaTime) {
|
||||
|
||||
@@ -8,6 +8,8 @@ struct ControllerState {
|
||||
float pitch = 0.0f;
|
||||
float yaw = 0.0f;
|
||||
float verticalVelocity = 0.0f;
|
||||
glm::vec3 debugVelocity = glm::vec3(0.0f);
|
||||
bool debugGrounded = false;
|
||||
bool initialized = false;
|
||||
};
|
||||
|
||||
@@ -38,23 +40,6 @@ void bindSettings(ScriptContext& ctx) {
|
||||
ctx.AutoSetting("enforceRigidbody", enforceRigidbody);
|
||||
ctx.AutoSetting("showDebug", showDebug);
|
||||
}
|
||||
|
||||
void ensureComponents(ScriptContext& ctx, float height, float radius) {
|
||||
if (!ctx.object) return;
|
||||
if (enforceCollider) {
|
||||
ctx.object->hasCollider = true;
|
||||
ctx.object->collider.enabled = true;
|
||||
ctx.object->collider.type = ColliderType::Capsule;
|
||||
ctx.object->collider.convex = true;
|
||||
ctx.object->collider.boxSize = glm::vec3(radius * 2.0f, height, radius * 2.0f);
|
||||
}
|
||||
if (enforceRigidbody) {
|
||||
ctx.object->hasRigidbody = true;
|
||||
ctx.object->rigidbody.enabled = true;
|
||||
ctx.object->rigidbody.useGravity = true;
|
||||
ctx.object->rigidbody.isKinematic = false;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
@@ -63,19 +48,24 @@ extern "C" void Script_OnInspector(ScriptContext& ctx) {
|
||||
ImGui::TextUnformatted("Standalone Movement Controller");
|
||||
ImGui::Separator();
|
||||
|
||||
bool changed = false;
|
||||
changed |= ImGui::DragFloat3("Walk/Run/Jump", &moveTuning.x, 0.05f, 0.0f, 25.0f, "%.2f");
|
||||
changed |= ImGui::DragFloat2("Look Sens/Clamp", &lookTuning.x, 0.01f, 0.0f, 500.0f, "%.2f");
|
||||
changed |= ImGui::DragFloat3("Height/Radius/Snap", &capsuleTuning.x, 0.02f, 0.0f, 5.0f, "%.2f");
|
||||
changed |= ImGui::DragFloat3("Gravity/Probe/MaxFall", &gravityTuning.x, 0.05f, -50.0f, 50.0f, "%.2f");
|
||||
changed |= ImGui::Checkbox("Enable Mouse Look", &enableMouseLook);
|
||||
changed |= ImGui::Checkbox("Hold RMB to Look", &requireMouseButton);
|
||||
changed |= ImGui::Checkbox("Force Collider", &enforceCollider);
|
||||
changed |= ImGui::Checkbox("Force Rigidbody", &enforceRigidbody);
|
||||
changed |= ImGui::Checkbox("Show Debug", &showDebug);
|
||||
ImGui::DragFloat3("Walk/Run/Jump", &moveTuning.x, 0.05f, 0.0f, 25.0f, "%.2f");
|
||||
ImGui::DragFloat2("Look Sens/Clamp", &lookTuning.x, 0.01f, 0.0f, 500.0f, "%.2f");
|
||||
ImGui::DragFloat3("Height/Radius/Snap", &capsuleTuning.x, 0.02f, 0.0f, 5.0f, "%.2f");
|
||||
ImGui::DragFloat3("Gravity/Probe/MaxFall", &gravityTuning.x, 0.05f, -50.0f, 50.0f, "%.2f");
|
||||
ImGui::Checkbox("Enable Mouse Look", &enableMouseLook);
|
||||
ImGui::Checkbox("Hold RMB to Look", &requireMouseButton);
|
||||
ImGui::Checkbox("Force Collider", &enforceCollider);
|
||||
ImGui::Checkbox("Force Rigidbody", &enforceRigidbody);
|
||||
ImGui::Checkbox("Show Debug", &showDebug);
|
||||
|
||||
if (changed) {
|
||||
ctx.SaveAutoSettings();
|
||||
if (showDebug && ctx.object) {
|
||||
auto it = g_states.find(ctx.object->id);
|
||||
if (it != g_states.end()) {
|
||||
const ControllerState& state = it->second;
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Move (%.2f, %.2f, %.2f)", state.debugVelocity.x, state.debugVelocity.y, state.debugVelocity.z);
|
||||
ImGui::Text("Grounded: %s", state.debugGrounded ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,14 +79,16 @@ void Begin(ScriptContext& ctx, float /*deltaTime*/) {
|
||||
state.verticalVelocity = 0.0f;
|
||||
state.initialized = true;
|
||||
}
|
||||
ensureComponents(ctx, capsuleTuning.x, capsuleTuning.y);
|
||||
if (enforceCollider) ctx.EnsureCapsuleCollider(capsuleTuning.x, capsuleTuning.y);
|
||||
if (enforceRigidbody) ctx.EnsureRigidbody(true, false);
|
||||
}
|
||||
|
||||
void TickUpdate(ScriptContext& ctx, float deltaTime) {
|
||||
if (!ctx.object) return;
|
||||
|
||||
ControllerState& state = getState(ctx.object->id);
|
||||
ensureComponents(ctx, capsuleTuning.x, capsuleTuning.y);
|
||||
if (enforceCollider) ctx.EnsureCapsuleCollider(capsuleTuning.x, capsuleTuning.y);
|
||||
if (enforceRigidbody) ctx.EnsureRigidbody(true, false);
|
||||
|
||||
const float walkSpeed = moveTuning.x;
|
||||
const float runSpeed = moveTuning.y;
|
||||
@@ -125,17 +117,9 @@ void TickUpdate(ScriptContext& ctx, float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat q = glm::quat(glm::radians(glm::vec3(state.pitch, state.yaw, 0.0f)));
|
||||
glm::vec3 forward = glm::normalize(q * glm::vec3(0.0f, 0.0f, -1.0f));
|
||||
glm::vec3 right = glm::normalize(q * glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
glm::vec3 planarForward = glm::normalize(glm::vec3(forward.x, 0.0f, forward.z));
|
||||
glm::vec3 planarRight = glm::normalize(glm::vec3(right.x, 0.0f, right.z));
|
||||
if (!std::isfinite(planarForward.x) || glm::length(planarForward) < 1e-3f) {
|
||||
planarForward = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
}
|
||||
if (!std::isfinite(planarRight.x) || glm::length(planarRight) < 1e-3f) {
|
||||
planarRight = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
glm::vec3 planarForward(0.0f);
|
||||
glm::vec3 planarRight(0.0f);
|
||||
ctx.GetPlanarYawPitchVectors(state.pitch, state.yaw, planarForward, planarRight);
|
||||
|
||||
glm::vec3 move(0.0f);
|
||||
if (ImGui::IsKeyDown(ImGuiKey_W)) move += planarForward;
|
||||
@@ -195,8 +179,8 @@ void TickUpdate(ScriptContext& ctx, float deltaTime) {
|
||||
}
|
||||
|
||||
if (showDebug) {
|
||||
ImGui::Text("Move (%.2f, %.2f, %.2f)", velocity.x, velocity.y, velocity.z);
|
||||
ImGui::Text("Grounded: %s", grounded ? "yes" : "no");
|
||||
state.debugVelocity = velocity;
|
||||
state.debugGrounded = grounded;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user