新增脚本参数系统:声明式参数 + Inspector 自动控件 + 场景序列化
DeclareParams/ParamBuilder 声明字段,运行时反射读写; Inspector 按类型生成控件,SceneSerializer 直通存取; 动画系统接入参数化裁剪;新增 OrbitMove 示例脚本
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "Engine/Renderer/MaterialAsset.h" // 材质覆盖槽(.material 资产)
|
||||
#include "Engine/Physics/PhysicsWorld.h" // Apply Impulse 调试(GetPhysics 门面)
|
||||
#include "Engine/Scripting/Script.h" // 脚本下拉(ScriptRegistry::Names)
|
||||
#include "Engine/Scripting/ScriptRuntime.h" // 参数编辑 → RefreshParams
|
||||
#include "Engine/Core/Log.h" // Create Override 失败告警
|
||||
|
||||
#include <imgui.h>
|
||||
@@ -38,6 +39,28 @@ namespace
|
||||
// 材质槽循环索引用(u32 定义于 namespace Engine,App 层显式引入)
|
||||
using Engine::u32;
|
||||
|
||||
// 脚本参数对齐 schema:缺失 → 声明默认补齐;类型不符 → 重置默认
|
||||
//(换脚本类/手编档防呆)。返回对齐后的参数项指针(每帧幂等)
|
||||
Engine::Scripting::ScriptParam* EnsureParam(
|
||||
Engine::ECS::ScriptComponent::Item& item,
|
||||
const Engine::Scripting::ParamBuilder::Desc& d)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
item.params.begin(), item.params.end(),
|
||||
[&](const Engine::Scripting::ScriptParam& p)
|
||||
{ return p.name == d.name; });
|
||||
if (it == item.params.end())
|
||||
{
|
||||
item.params.push_back({d.name, d.def});
|
||||
return &item.params.back();
|
||||
}
|
||||
if (it->value.Type() != d.type)
|
||||
{
|
||||
it->value = d.def;
|
||||
}
|
||||
return &*it;
|
||||
}
|
||||
|
||||
// 递归收集 assets/ 下模型容器文件(模型槽与动画 attach 槽共用;
|
||||
// 无法从扩展名区分"模型 fbx"与"纯动画 fbx",一并列出)。
|
||||
// 会话级缓存:目录条目几十量级,避免每帧递归扫描
|
||||
@@ -1156,6 +1179,7 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
ImGui::SeparatorText("Movement");
|
||||
ImGui::DragFloat("Max Slope (deg)", &cc->maxSlopeAngle, 1.0f, 1.0f, 89.0f);
|
||||
ImGui::DragFloat("Step Height", &cc->stepHeight, 0.02f, 0.0f, 2.0f);
|
||||
ImGui::DragFloat("Gravity Scale", &cc->gravityScale, 0.1f, 0.0f, 10.0f);
|
||||
|
||||
// ---- Debug:遥测(只读,运行时状态在 PhysicsWorld)----
|
||||
if (auto& phy = ctx.app->GetPhysics(); phy.IsEnabled())
|
||||
@@ -1249,6 +1273,102 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
{
|
||||
removeIdx = i;
|
||||
}
|
||||
// ---- 参数区(按脚本 schema 自动生成;缺省补齐 + 类型
|
||||
// 防呆;编辑 → RefreshParams 重灌实例成员,PIE 当帧生效)----
|
||||
if (!item.name.empty() &&
|
||||
!Engine::Scripting::ScriptRegistry::Schema(item.name)
|
||||
.empty())
|
||||
{
|
||||
const auto& schema =
|
||||
Engine::Scripting::ScriptRegistry::Schema(item.name);
|
||||
ImGui::Indent();
|
||||
bool anyEdited = false;
|
||||
for (const auto& d : schema)
|
||||
{
|
||||
auto* p = EnsureParam(item, d);
|
||||
bool changed = false;
|
||||
// 局部变量禁用 f32(glm::f32 歧义前科),用 float
|
||||
switch (d.type)
|
||||
{
|
||||
case Engine::Scripting::ParamType::F32:
|
||||
{
|
||||
float v = std::get<float>(p->value.v);
|
||||
if (ImGui::DragFloat(d.name.c_str(), &v, 0.1f))
|
||||
{
|
||||
p->value = Engine::Scripting::ParamValue{v};
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Engine::Scripting::ParamType::I32:
|
||||
{
|
||||
int v = std::get<Engine::i32>(p->value.v);
|
||||
if (ImGui::DragInt(d.name.c_str(), &v))
|
||||
{
|
||||
p->value = Engine::Scripting::ParamValue{
|
||||
static_cast<Engine::i32>(v)};
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Engine::Scripting::ParamType::Bool:
|
||||
changed = ImGui::Checkbox(
|
||||
d.name.c_str(), &std::get<bool>(p->value.v));
|
||||
break;
|
||||
case Engine::Scripting::ParamType::String:
|
||||
{
|
||||
char buf[256] = {};
|
||||
std::snprintf(buf, sizeof(buf), "%s",
|
||||
std::get<std::string>(p->value.v)
|
||||
.c_str());
|
||||
if (ImGui::InputText(d.name.c_str(), buf,
|
||||
sizeof(buf)))
|
||||
{
|
||||
p->value = Engine::Scripting::ParamValue{
|
||||
std::string(buf)};
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Engine::Scripting::ParamType::Vec2:
|
||||
{
|
||||
const glm::vec2 g =
|
||||
std::get<glm::vec2>(p->value.v);
|
||||
float v[2] = {g.x, g.y};
|
||||
if (ImGui::DragFloat2(d.name.c_str(), v, 0.1f))
|
||||
{
|
||||
p->value = Engine::Scripting::ParamValue{
|
||||
glm::vec2(v[0], v[1])};
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Engine::Scripting::ParamType::Vec3:
|
||||
{
|
||||
const glm::vec3 g =
|
||||
std::get<glm::vec3>(p->value.v);
|
||||
float v[3] = {g.x, g.y, g.z};
|
||||
if (ImGui::DragFloat3(d.name.c_str(), v, 0.1f))
|
||||
{
|
||||
p->value = Engine::Scripting::ParamValue{
|
||||
glm::vec3(v[0], v[1], v[2])};
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
anyEdited = true;
|
||||
}
|
||||
}
|
||||
if (anyEdited)
|
||||
{
|
||||
ctx.app->GetScripts().RefreshParams(
|
||||
static_cast<uint32_t>(entt::to_integral(selected)));
|
||||
}
|
||||
ImGui::Unindent();
|
||||
}
|
||||
ImGui::PopID();
|
||||
// 已填名但注册表查无此类:场景加载早于脚本注册/改名都会走到这
|
||||
if (!item.name.empty() && cur == 0)
|
||||
|
||||
Reference in New Issue
Block a user