#ifdef ENABLE_EDITOR
#include "editor.h"
#include "core/math_rtm.h"
#include "passes/debug/debug_draw.h"
#include "renderer.h"
#include "scene/scene.h"
#include "shaders/renderer_types.h"
namespace editor {
void apply_debug_settings(const Editor &e, DebugDraw &draw) {
draw.force_xray = e.force_xray;
u32 mask = 0;
if (e.show_cat_default) {
mask |= DebugDraw::category_bit(DEBUG_CAT_DEFAULT);
}
if (e.show_cat_grid) {
mask |= DebugDraw::category_bit(DEBUG_CAT_GRID);
}
if (e.show_cat_proxy) {
mask |= DebugDraw::category_bit(DEBUG_CAT_PROXY);
}
if (e.show_cat_selection) {
mask |= DebugDraw::category_bit(DEBUG_CAT_SELECTION);
}
if (e.show_cat_light) {
mask |= DebugDraw::category_bit(DEBUG_CAT_LIGHT);
}
if (e.show_cat_ddgi) {
mask |= DebugDraw::category_bit(DEBUG_CAT_DDGI);
}
if (e.show_cat_gizmo) {
mask |= DebugDraw::category_bit(DEBUG_CAT_GIZMO);
}
draw.category_mask = mask;
}
void debug_draw_selection(DebugDraw &draw, const Scene &scene, const RenderData &rd, int selected_node) {
if (selected_node < 0 || (u32)selected_node >= scene.scene_graph.node_count) {
return;
}
if (!scene.scene_graph.is_node_alive((u32)selected_node)) {
return;
}
u32 node = (u32)selected_node;
const SceneGraph &sg = scene.scene_graph;
const mat4 base_world = sg.worlds[node];
const u32 inst_count = sg.instance_count[node];
const u32 inst_base = sg.instance_base[node];
bool drew = false;
for (const RenderItemGPU &item : rd.render_items) {
// entity_id is node+1 (see create_render_data); match selection.
if (item.entity_id != node + 1) {
continue;
}
if (item.submesh_index >= rd.submeshes.size()) {
continue;
}
// Per-instance world (Scene::instance_world, same composition as
// upload_transforms); node base when not instanced.
mat4 world = base_world;
if (inst_count > 0) {
if (item.instance_id < inst_base) {
continue;
}
u32 k = item.instance_id - inst_base;
if (k >= inst_count) {
continue;
}
world = scene.instance_world(node, k);
}
const SubmeshGPU &sm = rd.submeshes[item.submesh_index];
vec3 mn = sm.local_aabb_min;
vec3 mx = sm.local_aabb_max;
auto xform = [](vec3 p, const mat4 &m) {
vec4 h = transform_point(p, m);
return vec3(h.x, h.y, h.z);
};
// 8 corners of the local AABB into world -> world AABB (conservative).
vec3 wmn = vec3(1e30f);
vec3 wmx = vec3(-1e30f);
for (u32 c = 0; c < 8; ++c) {
vec3 corner = vec3((c & 1) ? mx.x : mn.x, (c & 2) ? mx.y : mn.y, (c & 4) ? mx.z : mn.z);
vec3 w = xform(corner, world);
wmn.x = wmn.x < w.x ? wmn.x : w.x;
wmn.y = wmn.y < w.y ? wmn.y : w.y;
wmn.z = wmn.z < w.z ? wmn.z : w.z;
wmx.x = wmx.x > w.x ? wmx.x : w.x;
wmx.y = wmx.y > w.y ? wmx.y : w.y;
wmx.z = wmx.z > w.z ? wmx.z : w.z;
}
draw.aabb(wmn, wmx, vec4(4.0f, 1.4f, 0.4f, 1.0f), DEBUG_CAT_SELECTION, DEBUG_DEPTH_TEST, 3.0f);
drew = true;
}
if (!drew) {
// Node without mesh (light/camera/empty): small cross at its origin.
vec4 h = transform_point(vec3(0.0f), base_world);
draw.sphere(
vec3(h.x, h.y, h.z), 0.3f, vec4(4.0f, 1.4f, 0.4f, 1.0f), DEBUG_CAT_SELECTION, DEBUG_DEPTH_TEST, 3.0f
);
}
}
} // namespace editor
#endif // ENABLE_EDITOR