#ifdef ENABLE_EDITOR
#define IMGUI_DEFINE_MATH_OPERATORS
#include "editor.h"
#include <imgui.h>
#include <algorithm>
#include "backend/imgui_backend.h"
#include "quick_submit.h"
#include "renderer.h"
namespace editor {
void draw_viewport_central(Editor &e, RenderData &rd) {
if (!rhi::valid(rd.display)) {
return;
}
rhi::Image &img = rd.display;
if (!rhi::valid(img)) {
return;
}
static rhi::ImageView live{};
if (rhi::valid(live)) {
rhi::destroy_image_view(*e.device, live);
live = {};
}
rhi::ImageView view{};
if (!rhi::create_image_view(*e.device, {.image = &img, .aspect = rhi::ImageAspect::Color, .mip_count = 1}, view)) {
return;
}
u64 slot = imgui_backend::texture(view);
if (slot == UINT64_MAX) {
rhi::destroy_image_view(*e.device, view);
return;
}
live = view;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("Viewport", nullptr);
ImVec2 viewport_size = ImGui::GetContentRegionAvail();
if (viewport_size.x > 0.0f && viewport_size.y > 0.0f) {
ImVec2 image_start_pos = ImGui::GetCursorPos();
ImGui::Image((ImTextureID)(u64)slot, viewport_size);
e.gizmo_view_min = ImGui::GetItemRectMin();
e.gizmo_view_size = viewport_size;
static ImVec2 overlay_min = {0, 0};
static ImVec2 overlay_max = {0, 0};
bool clicking_overlay = ImGui::IsMouseHoveringRect(overlay_min, overlay_max, false);
// block click passthrough to viewport if its on the overlay window, compared to bounds grabbed on inti
if (!clicking_overlay && ImGui::IsItemHovered() && ImGui::IsItemClicked(ImGuiMouseButton_Left) &&
!e.gizmo_dragging && e.gizmo_hover_axis < 0 && rhi::valid(rd.id_blit)) {
rhi::Image &id_img = rd.id_blit;
ImVec2 rel = {
ImGui::GetMousePos().x - ImGui::GetItemRectMin().x, ImGui::GetMousePos().y - ImGui::GetItemRectMin().y
};
i64 tx = (i64)(rel.x * (f32)id_img.desc.width / viewport_size.x);
i64 ty = (i64)(rel.y * (f32)id_img.desc.height / (viewport_size.y));
ty = id_img.desc.height - 1 - ty; // Flip Vulkan viewport
rhi::ImageView id_view{};
if (rhi::create_image_view(
*e.device, {.image = &id_img, .aspect = rhi::ImageAspect::Color, .mip_count = 1}, id_view
)) {
u32 raw = 0;
if (e.qs != nullptr && readback_texel_raw(*e.device, *e.qs, id_view, 0, 0, tx, ty, &raw, sizeof(raw)) &&
raw > 0) {
e.selected_node = (int)raw - 1;
} else {
e.selected_node = -1;
}
rhi::destroy_image_view(*e.device, id_view);
} else {
e.selected_node = -1;
}
}
ImGui::SetCursorPos(ImVec2(image_start_pos.x + 10.0f, image_start_pos.y + 10.0f));
if (ImGui::BeginChild(
"##GizmoOverlay",
ImVec2(0.0f, 38.0f),
ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_AutoResizeX,
ImGuiWindowFlags_NoScrollbar
)) {
// need to track the bounds of this window, to decipher if its a viewport click or this window click
overlay_min = ImGui::GetWindowPos();
overlay_max = ImVec2(overlay_min.x + ImGui::GetWindowSize().x, overlay_min.y + ImGui::GetWindowSize().y);
if (ImGui::RadioButton("Move", e.gizmo_tool == GIZMO_TOOL_MOVE)) {
e.gizmo_tool = GIZMO_TOOL_MOVE;
e.gizmo_dragging = false;
}
ImGui::SameLine();
if (ImGui::RadioButton("Rot", e.gizmo_tool == GIZMO_TOOL_ROTATE)) {
e.gizmo_tool = GIZMO_TOOL_ROTATE;
e.gizmo_dragging = false;
}
ImGui::SameLine();
if (ImGui::RadioButton("Scale", e.gizmo_tool == GIZMO_TOOL_SCALE)) {
e.gizmo_tool = GIZMO_TOOL_SCALE;
e.gizmo_dragging = false;
}
ImGui::SameLine();
if (ImGui::Button(e.gizmo_world ? "World" : "Local")) {
e.gizmo_world = !e.gizmo_world;
}
ImGui::SameLine();
ImGui::Checkbox("Snap", &e.gizmo_snap);
if (e.gizmo_snap) {
ImGui::SameLine();
ImGui::SetNextItemWidth(128.0f);
if (e.gizmo_tool == GIZMO_TOOL_ROTATE) {
ImGui::DragFloat("##snapangle", &e.gizmo_snap_angle, 0.5f, 0.1f, 90.0f, "%.1f deg");
} else if (e.gizmo_tool == GIZMO_TOOL_SCALE) {
ImGui::DragFloat("##snapscale", &e.gizmo_snap_scale, 0.01f, 0.01f, 1.0f, "%.2f");
} else {
ImGui::DragFloat("##snapstep", &e.gizmo_snap_step, 0.01f, 0.01f, 10.0f, "%.2f");
}
}
}
ImGui::EndChild();
}
u32 nw = (u32)(viewport_size.x + 0.5f), nh = (u32)(viewport_size.y + 0.5f);
if (nw > 0 && nh > 0 && (nw != e.viewport_width || nh != e.viewport_height)) {
e.viewport_width = nw;
e.viewport_height = nh;
e.viewport_resized = true;
}
ImGui::End();
ImGui::PopStyleVar();
}
} // namespace editor
#endif // ENABLE_EDITOR