diff --git a/gameengine/packages/seed/workflows/seed_game.json b/gameengine/packages/seed/workflows/seed_game.json index 2aaeb2e7b..d65d2d6c6 100644 --- a/gameengine/packages/seed/workflows/seed_game.json +++ b/gameengine/packages/seed/workflows/seed_game.json @@ -871,7 +871,8 @@ "color_b": 0.85, "offset_x": 0.15, "offset_y": -0.1, - "offset_z": -0.1 + "offset_z": -0.1, + "aim_distance": 50 } }, { diff --git a/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_setup_step.cpp b/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_setup_step.cpp index f83d20480..8003480ef 100644 --- a/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_setup_step.cpp +++ b/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_setup_step.cpp @@ -1,10 +1,7 @@ #include "services/interfaces/workflow/rendering/workflow_spotlight_setup_step.hpp" #include "services/interfaces/workflow/workflow_step_parameter_resolver.hpp" -#include -#include #include -#include namespace sdl3cpp::services::impl { @@ -16,55 +13,57 @@ std::string WorkflowSpotlightSetupStep::GetPluginId() const { } void WorkflowSpotlightSetupStep::Execute(const WorkflowStepDefinition& step, WorkflowContext& context) { - WorkflowStepParameterResolver params; - - auto getNum = [&](const char* name, float def) -> float { - const auto* p = params.FindParameter(step, name); - return (p && p->type == WorkflowParameterValue::Type::Number) ? static_cast(p->numberValue) : def; - }; - auto getStr = [&](const char* name, const std::string& def) -> std::string { - const auto* p = params.FindParameter(step, name); - return (p && p->type == WorkflowParameterValue::Type::String) ? p->stringValue : def; - }; - - std::string attach = getStr("attach", "camera"); - float inner_cone = getNum("inner_cone", 12.0f); - float outer_cone = getNum("outer_cone", 25.0f); - float intensity = getNum("intensity", 2.5f); - float range = getNum("range", 20.0f); - float color_r = getNum("color_r", 1.0f); - float color_g = getNum("color_g", 0.95f); - float color_b = getNum("color_b", 0.85f); - float offset_x = getNum("offset_x", 0.0f); - float offset_y = getNum("offset_y", 0.0f); - float offset_z = getNum("offset_z", 0.0f); - + // Pass all parameters straight through to context as JSON + // No hardcoded defaults — everything comes from the workflow definition nlohmann::json spotlight; - spotlight["inner_cone"] = inner_cone; - spotlight["outer_cone"] = outer_cone; - spotlight["intensity"] = intensity; - spotlight["range"] = range; - spotlight["color"] = {color_r, color_g, color_b}; - spotlight["attach"] = attach; - spotlight["offset"] = {offset_x, offset_y, offset_z}; - // If attached to camera, position and direction will be filled per-frame - // by the render.prepare step reading camera state. - // For static spotlights, set explicit position/direction params. - if (attach == "camera") { - // Will be updated each frame in render.prepare from camera state - spotlight["position"] = {0, 0, 0}; - spotlight["direction"] = {0, 0, -1}; - } else { - spotlight["position"] = { - getNum("pos_x", 0.0f), - getNum("pos_y", 0.0f), - getNum("pos_z", 0.0f) + for (const auto& [key, param] : step.parameters) { + switch (param.type) { + case WorkflowParameterValue::Type::Number: + spotlight[key] = param.numberValue; + break; + case WorkflowParameterValue::Type::String: + spotlight[key] = param.stringValue; + break; + case WorkflowParameterValue::Type::Bool: + spotlight[key] = param.boolValue; + break; + default: + break; + } + } + + // Build color array from individual components if present + if (spotlight.contains("color_r") || spotlight.contains("color_g") || spotlight.contains("color_b")) { + spotlight["color"] = { + spotlight.value("color_r", 0.0), + spotlight.value("color_g", 0.0), + spotlight.value("color_b", 0.0) }; + } + + // Build offset array from individual components if present + if (spotlight.contains("offset_x") || spotlight.contains("offset_y") || spotlight.contains("offset_z")) { + spotlight["offset"] = { + spotlight.value("offset_x", 0.0), + spotlight.value("offset_y", 0.0), + spotlight.value("offset_z", 0.0) + }; + } + + // Build position/direction arrays for static spotlights + if (spotlight.contains("pos_x") || spotlight.contains("pos_y") || spotlight.contains("pos_z")) { + spotlight["position"] = { + spotlight.value("pos_x", 0.0), + spotlight.value("pos_y", 0.0), + spotlight.value("pos_z", 0.0) + }; + } + if (spotlight.contains("dir_x") || spotlight.contains("dir_y") || spotlight.contains("dir_z")) { spotlight["direction"] = { - getNum("dir_x", 0.0f), - getNum("dir_y", -1.0f), - getNum("dir_z", 0.0f) + spotlight.value("dir_x", 0.0), + spotlight.value("dir_y", 0.0), + spotlight.value("dir_z", 0.0) }; } diff --git a/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_update_step.cpp b/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_update_step.cpp index 5363a02f6..01bb732bb 100644 --- a/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_update_step.cpp +++ b/gameengine/src/services/impl/workflow/rendering/workflow_spotlight_update_step.cpp @@ -21,50 +21,57 @@ void WorkflowSpotlightUpdateStep::Execute(const WorkflowStepDefinition& step, Wo auto fu = context.Get("render.frag_uniforms", rendering::FragmentUniformData{}); - std::string attach = spot->value("attach", "camera"); - auto offset = spot->value("offset", std::vector{0, 0, 0}); - glm::vec3 off(offset.size() > 0 ? offset[0] : 0, - offset.size() > 1 ? offset[1] : 0, - offset.size() > 2 ? offset[2] : 0); + // All values from JSON — no hardcoded defaults in C++ + const std::string attach = spot->value("attach", std::string()); + const auto offset = spot->value("offset", std::vector{}); + const glm::vec3 off(offset.size() > 0 ? offset[0] : 0.0f, + offset.size() > 1 ? offset[1] : 0.0f, + offset.size() > 2 ? offset[2] : 0.0f); glm::vec3 spotPos, spotDir; if (attach == "camera") { - auto viewMatrix = context.Get("render.view_matrix", glm::mat4(1.0f)); - auto cameraPos = context.Get("render.camera_pos", glm::vec3(0.0f)); + const auto viewMatrix = context.Get("render.view_matrix", glm::mat4(1.0f)); + const auto cameraPos = context.Get("render.camera_pos", glm::vec3(0.0f)); - glm::vec3 camRight = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); - glm::vec3 camUp = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); - glm::vec3 camFwd = -glm::vec3(viewMatrix[0][2], viewMatrix[1][2], viewMatrix[2][2]); + const glm::vec3 camRight = glm::vec3(viewMatrix[0][0], viewMatrix[1][0], viewMatrix[2][0]); + const glm::vec3 camUp = glm::vec3(viewMatrix[0][1], viewMatrix[1][1], viewMatrix[2][1]); + const glm::vec3 camFwd = -glm::vec3(viewMatrix[0][2], viewMatrix[1][2], viewMatrix[2][2]); spotPos = cameraPos + camRight * off.x + camUp * off.y + camFwd * (-off.z); - // Aim toward a far point on camera center axis (natural torch aim) - float aimDist = spot->value("aim_distance", 50.0f); - glm::vec3 aimTarget = cameraPos + camFwd * aimDist; - spotDir = glm::normalize(aimTarget - spotPos); + const float aimDist = spot->value("aim_distance", 0.0f); + if (aimDist > 0.0f) { + const glm::vec3 aimTarget = cameraPos + camFwd * aimDist; + spotDir = glm::normalize(aimTarget - spotPos); + } else { + spotDir = camFwd; + } } else { - auto p = spot->value("position", std::vector{0, 0, 0}); - auto d = spot->value("direction", std::vector{0, 0, -1}); - spotPos = glm::vec3(p[0], p[1], p[2]) + off; - spotDir = glm::normalize(glm::vec3(d[0], d[1], d[2])); + const auto p = spot->value("position", std::vector{}); + const auto d = spot->value("direction", std::vector{}); + spotPos = glm::vec3(p.size() > 0 ? p[0] : 0.0f, p.size() > 1 ? p[1] : 0.0f, p.size() > 2 ? p[2] : 0.0f) + off; + spotDir = glm::normalize(glm::vec3(d.size() > 0 ? d[0] : 0.0f, d.size() > 1 ? d[1] : 0.0f, d.size() > 2 ? d[2] : -1.0f)); } + const float innerCone = spot->value("inner_cone", 0.0f); + const float outerCone = spot->value("outer_cone", 0.0f); + const auto col = spot->value("color", std::vector{}); + const float intensity = spot->value("intensity", 0.0f); + const float range = spot->value("range", 0.0f); + fu.flash_pos[0] = spotPos.x; fu.flash_pos[1] = spotPos.y; fu.flash_pos[2] = spotPos.z; - fu.flash_pos[3] = std::cos(glm::radians(spot->value("inner_cone", 12.0f))); + fu.flash_pos[3] = std::cos(glm::radians(innerCone)); fu.flash_dir[0] = spotDir.x; fu.flash_dir[1] = spotDir.y; fu.flash_dir[2] = spotDir.z; - fu.flash_dir[3] = std::cos(glm::radians(spot->value("outer_cone", 25.0f))); - - auto col = spot->value("color", std::vector{1, 1, 1}); - float intensity = spot->value("intensity", 2.5f); - fu.flash_color[0] = (col.size() > 0 ? col[0] : 1.0f) * intensity; - fu.flash_color[1] = (col.size() > 1 ? col[1] : 1.0f) * intensity; - fu.flash_color[2] = (col.size() > 2 ? col[2] : 1.0f) * intensity; - fu.flash_color[3] = spot->value("range", 20.0f); + fu.flash_dir[3] = std::cos(glm::radians(outerCone)); + fu.flash_color[0] = (col.size() > 0 ? col[0] : 0.0f) * intensity; + fu.flash_color[1] = (col.size() > 1 ? col[1] : 0.0f) * intensity; + fu.flash_color[2] = (col.size() > 2 ? col[2] : 0.0f) * intensity; + fu.flash_color[3] = range; context.Set("render.frag_uniforms", fu); }