267GUI::vec3Control(
const std::string& label,
float* values,
float resetValue,
float columnWidth,
bool displayAsDegrees) {
268 ImGuiIO& io = ImGui::GetIO();
269 auto boldFont = io.Fonts->Fonts[0];
270 float displayValues[3] = { values[0], values[1], values[2] };
271 if (displayAsDegrees) {
272 displayValues[0] = RadToDeg(values[0]);
273 displayValues[1] = RadToDeg(values[1]);
274 displayValues[2] = RadToDeg(values[2]);
277 ImGui::PushID(label.c_str());
278 if (!ImGui::BeginTable((
"##Vec3Table" + label).c_str(), 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerV)) {
283 ImGui::TableSetupColumn(
"Label", ImGuiTableColumnFlags_WidthFixed, columnWidth);
284 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
285 ImGui::TableNextRow();
286 ImGui::TableSetColumnIndex(0);
287 ImGui::AlignTextToFramePadding();
288 ImGui::TextDisabled(
"%s", label.c_str());
289 ImGui::TableSetColumnIndex(1);
290 ImGui::PushItemWidth(-1.0f);
292 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{ 3.0f, 4.0f });
293 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
294 float lineHeight = GImGui->Font->FontSize + GImGui->Style.FramePadding.y * 2.0f;
295 ImVec2 buttonSize = { lineHeight, lineHeight };
296 const float spacing = ImGui::GetStyle().ItemSpacing.x;
297 const float availableWidth = ImGui::GetContentRegionAvail().x;
298 const float dragWidth = (availableWidth - (buttonSize.x * 3.0f) - (spacing * 5.0f)) / 3.0f;
299 const float safeDragWidth = dragWidth > 24.0f ? dragWidth : 24.0f;
300 const float dragSpeed = displayAsDegrees ? 1.0f : 0.1f;
301 const char* dragFormat = displayAsDegrees ?
"%.1f deg" :
"%.2f";
303 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f });
304 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.9f, 0.2f, 0.2f, 1.0f });
305 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.8f, 0.1f, 0.15f, 1.0f });
306 ImGui::PushFont(boldFont);
307 if (ImGui::Button(
"X", buttonSize)) {
308 values[0] = resetValue;
309 displayValues[0] = displayAsDegrees ? RadToDeg(resetValue) : resetValue;
312 ImGui::PopStyleColor(3);
315 ImGui::SetNextItemWidth(safeDragWidth);
316 if (ImGui::DragFloat(
"##X", &displayValues[0], dragSpeed, 0.0f, 0.0f, dragFormat)) {
317 values[0] = displayAsDegrees ? DegToRad(displayValues[0]) : displayValues[0];
321 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f });
322 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.3f, 0.8f, 0.3f, 1.0f });
323 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.2f, 0.7f, 0.2f, 1.0f });
324 ImGui::PushFont(boldFont);
325 if (ImGui::Button(
"Y", buttonSize)) {
326 values[1] = resetValue;
327 displayValues[1] = displayAsDegrees ? RadToDeg(resetValue) : resetValue;
330 ImGui::PopStyleColor(3);
333 ImGui::SetNextItemWidth(safeDragWidth);
334 if (ImGui::DragFloat(
"##Y", &displayValues[1], dragSpeed, 0.0f, 0.0f, dragFormat)) {
335 values[1] = displayAsDegrees ? DegToRad(displayValues[1]) : displayValues[1];
339 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f });
340 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4{ 0.2f, 0.35f, 0.9f, 1.0f });
341 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4{ 0.1f, 0.25f, 0.8f, 1.0f });
342 ImGui::PushFont(boldFont);
343 if (ImGui::Button(
"Z", buttonSize)) {
344 values[2] = resetValue;
345 displayValues[2] = displayAsDegrees ? RadToDeg(resetValue) : resetValue;
348 ImGui::PopStyleColor(3);
351 ImGui::SetNextItemWidth(safeDragWidth);
352 if (ImGui::DragFloat(
"##Z", &displayValues[2], dragSpeed, 0.0f, 0.0f, dragFormat)) {
353 values[2] = displayAsDegrees ? DegToRad(displayValues[2]) : displayValues[2];
356 ImGui::PopStyleVar(2);
357 ImGui::PopItemWidth();
369 ImGuiStyle& style = ImGui::GetStyle();
370 ImVec4* colors = style.Colors;
373 style.WindowRounding = 14.0f;
374 style.ChildRounding = 14.0f;
375 style.PopupRounding = 14.0f;
376 style.FrameRounding = 10.0f;
377 style.GrabRounding = 10.0f;
378 style.ScrollbarRounding = 12.0f;
379 style.TabRounding = 10.0f;
381 style.WindowBorderSize = 1.0f;
382 style.FrameBorderSize = 0.0f;
383 style.PopupBorderSize = 1.0f;
384 style.TabBorderSize = 0.0f;
386 style.WindowPadding = ImVec2(14, 12);
387 style.FramePadding = ImVec2(12, 8);
388 style.ItemSpacing = ImVec2(8, 8);
389 style.ItemInnerSpacing = ImVec2(8, 6);
391 const float o = opacity;
392 const ImVec4 txt = ImVec4(1, 1, 1, 0.95f);
393 const ImVec4 pane = ImVec4(0.16f, 0.16f, 0.18f, o);
394 const ImVec4 paneHi = ImVec4(0.20f, 0.20f, 0.22f, o);
395 const ImVec4 paneLo = ImVec4(0.13f, 0.13f, 0.15f, o * 0.85f);
398 colors[ImGuiCol_Text] = txt;
399 colors[ImGuiCol_TextDisabled] = ImVec4(1, 1, 1, 0.45f);
400 colors[ImGuiCol_WindowBg] = pane;
401 colors[ImGuiCol_ChildBg] = paneLo;
402 colors[ImGuiCol_PopupBg] = paneHi;
403 colors[ImGuiCol_Border] = ImVec4(1, 1, 1, 0.10f);
404 colors[ImGuiCol_BorderShadow] = ImVec4(0, 0, 0, 0.0f);
406 colors[ImGuiCol_FrameBg] = paneLo;
407 colors[ImGuiCol_FrameBgHovered] = pane;
408 colors[ImGuiCol_FrameBgActive] = paneHi;
410 colors[ImGuiCol_TitleBg] = pane;
411 colors[ImGuiCol_TitleBgActive] = paneHi;
412 colors[ImGuiCol_TitleBgCollapsed] = paneLo;
414 colors[ImGuiCol_MenuBarBg] = pane;
416 colors[ImGuiCol_ScrollbarBg] = ImVec4(0, 0, 0, 0.0f);
417 colors[ImGuiCol_ScrollbarGrab] = ImVec4(1, 1, 1, 0.10f);
418 colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(1, 1, 1, 0.18f);
419 colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1, 1, 1, 0.26f);
422 colors[ImGuiCol_CheckMark] = accent;
423 colors[ImGuiCol_SliderGrab] = accent;
424 colors[ImGuiCol_SliderGrabActive] = ImVec4(accent.x, accent.y, accent.z, 1.0f);
426 colors[ImGuiCol_Button] = paneLo;
427 colors[ImGuiCol_ButtonHovered] = pane;
428 colors[ImGuiCol_ButtonActive] = paneHi;
430 colors[ImGuiCol_Header] = paneLo;
431 colors[ImGuiCol_HeaderHovered] = pane;
432 colors[ImGuiCol_HeaderActive] = paneHi;
434 colors[ImGuiCol_Separator] = ImVec4(1, 1, 1, 0.10f);
435 colors[ImGuiCol_SeparatorHovered] = ImVec4(1, 1, 1, 0.18f);
436 colors[ImGuiCol_SeparatorActive] = ImVec4(1, 1, 1, 0.30f);
438 colors[ImGuiCol_Tab] = paneLo;
439 colors[ImGuiCol_TabHovered] = pane;
440 colors[ImGuiCol_TabActive] = paneHi;
441 colors[ImGuiCol_TabUnfocused] = paneLo;
442 colors[ImGuiCol_TabUnfocusedActive] = pane;
444 colors[ImGuiCol_DockingPreview] = ImVec4(accent.x, accent.y, accent.z, 0.35f);
445 colors[ImGuiCol_DockingEmptyBg] = ImVec4(0, 0, 0, 0.0f);
447 colors[ImGuiCol_TableHeaderBg] = pane;
448 colors[ImGuiCol_TableBorderStrong] = ImVec4(1, 1, 1, 0.08f);
449 colors[ImGuiCol_TableBorderLight] = ImVec4(1, 1, 1, 0.04f);
450 colors[ImGuiCol_TableRowBg] = ImVec4(1, 1, 1, 0.03f);
451 colors[ImGuiCol_TableRowBgAlt] = ImVec4(1, 1, 1, 0.06f);
453 colors[ImGuiCol_TextSelectedBg] = ImVec4(accent.x, accent.y, accent.z, 0.35f);
454 colors[ImGuiCol_NavHighlight] = ImVec4(accent.x, accent.y, accent.z, 0.50f);
455 colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1, 1, 1, 0.30f);
456 colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0, 0, 0, 0.20f);
457 colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0, 0, 0, 0.35f);
542 ImGui::Begin(
"Inspector");
544 ImGui::Dummy(ImVec2(0.0f, 12.0f));
545 ImGui::TextDisabled(
"No actor selected");
546 ImGui::TextWrapped(
"Select an actor in the Hierarchy to inspect transforms, materials, lights and renderer data.");
551 static char objectName[128] = {};
552 static Actor* cachedActor =
nullptr;
553 if (cachedActor != actor.
get()) {
554 cachedActor = actor.
get();
555 strncpy_s(objectName, actor->getName().c_str(), _TRUNCATE);
560 auto transform = actor->getComponent<
Transform>();
561 const bool hasMeshRenderer = !meshRenderer.isNull();
562 const bool hasLightComponent = !lightComponent.isNull();
563 const bool hasTransform = !transform.isNull();
564 const ImVec4 accentColor = GetActorTypeColor(actor);
565 const char* actorTypeLabel = GetActorTypeLabel(actor);
567 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 6.0f);
568 ImGui::BeginChild(
"##InspectorHeader", ImVec2(0.0f, 104.0f),
true);
569 ImDrawList* drawList = ImGui::GetWindowDrawList();
570 ImVec2 headerMin = ImGui::GetWindowPos();
571 ImVec2 headerMax = ImVec2(headerMin.x + ImGui::GetWindowSize().x, headerMin.y + ImGui::GetWindowSize().y);
572 drawList->AddRectFilled(headerMin, ImVec2(headerMax.x, headerMin.y + 4.0f), AccentU32(accentColor), 6.0f, ImDrawFlags_RoundCornersTop);
574 ImGui::TextDisabled(
"Details");
575 ImGui::Text(
"Selected Actor");
577 ImGui::TextDisabled(
"| %s", actorTypeLabel);
578 ImGui::SetNextItemWidth(-1.0f);
579 if (ImGui::InputText(
"##ObjectName", objectName, IM_ARRAYSIZE(objectName))) {
580 actor->setName(objectName);
583 DrawInspectorComponentChips(hasTransform, hasMeshRenderer, hasLightComponent);
585 ImGui::TextDisabled(
"Component details, rendering data and editable properties");
587 ImGui::PopStyleVar();
590 if (BeginInspectorSection(
"Identity")) {
591 if (BeginInspectorPropertyTable(
"##IdentityProperties")) {
592 DrawPropertyValueText(
"Name", actor->getName().c_str());
593 DrawPropertyValueText(
"Type", actorTypeLabel);
594 DrawPropertyValueBool(
"Transform", hasTransform);
595 DrawPropertyValueBool(
"Renderer", hasMeshRenderer);
596 DrawPropertyValueBool(
"Light", hasLightComponent);
602 if (hasTransform && BeginInspectorSection(
"Transform")) {
606 if (hasMeshRenderer) {
607 const std::vector<MaterialInstance*>& materialInstances = meshRenderer->getMaterialInstances();
608 Mesh* mesh = meshRenderer->getMesh();
610 if (BeginInspectorSection(
"Renderer")) {
611 const int submeshCount = mesh ?
static_cast<int>(mesh->
getSubmeshes().size()) : 0;
612 const int materialCount =
static_cast<int>(materialInstances.size());
613 if (BeginInspectorPropertyTable(
"##RendererProperties")) {
614 bool isVisible = meshRenderer->isVisible();
615 DrawPropertyToggle(
"Visible",
"##RendererVisible", &isVisible);
616 meshRenderer->setVisible(isVisible);
618 bool castShadow = meshRenderer->canCastShadow();
619 DrawPropertyToggle(
"Cast Shadow",
"##RendererCastShadow", &castShadow);
620 meshRenderer->setCastShadow(castShadow);
622 char countBuffer[32] = {};
623 sprintf_s(countBuffer,
"%d", submeshCount);
624 DrawPropertyValueText(
"Submeshes", countBuffer);
626 sprintf_s(countBuffer,
"%d", materialCount);
627 DrawPropertyValueText(
"Material Slots", countBuffer);
632 if (!materialInstances.empty() && BeginInspectorSection(
"Materials")) {
633 for (
size_t i = 0; i < materialInstances.size(); ++i) {
635 if (!materialInstance) {
641 std::string header =
"Material Slot " + std::to_string(i);
642 if (ImGui::TreeNodeEx(header.c_str(), ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth)) {
644 if (BeginInspectorPropertyTable((
"##MaterialMeta" + std::to_string(i)).c_str())) {
645 DrawPropertyValueText(
"Domain", GetMaterialDomainLabel(material->
getDomain()));
647 DrawPropertyValueText(
"Blend", GetBlendModeLabel(material->
getBlendMode()));
652 static const char* kMaterialDomains[] = {
"Opaque",
"Masked",
"Transparent" };
653 int currentDomain =
static_cast<int>(material->
getDomain());
654 if (BeginInspectorPropertyTable((
"##MaterialEditor" + std::to_string(i)).c_str())) {
655 DrawPropertyLabel(
"Domain");
656 if (ImGui::Combo((
"##Domain" + std::to_string(i)).c_str(), ¤tDomain, kMaterialDomains, IM_ARRAYSIZE(kMaterialDomains))) {
661 static const char* kBlendModes[] = {
"Opaque",
"Alpha",
"Additive",
"Premultiplied" };
662 int currentBlendMode =
static_cast<int>(material->
getBlendMode());
663 DrawPropertyLabel(
"Blend Mode");
664 if (ImGui::Combo((
"##BlendMode" + std::to_string(i)).c_str(), ¤tBlendMode, kBlendModes, IM_ARRAYSIZE(kBlendModes))) {
669 DrawPropertyLabel(
"Base Color");
670 ImGui::ColorEdit4((
"##BaseColor" + std::to_string(i)).c_str(), ¶ms.
baseColor.x);
671 DrawPropertyLabel(
"Metallic");
672 ImGui::SliderFloat((
"##Metallic" + std::to_string(i)).c_str(), ¶ms.
metallic, 0.0f, 1.0f);
673 DrawPropertyLabel(
"Roughness");
674 ImGui::SliderFloat((
"##Roughness" + std::to_string(i)).c_str(), ¶ms.
roughness, 0.0f, 1.0f);
675 DrawPropertyLabel(
"Ambient Occlusion");
676 ImGui::SliderFloat((
"##AO" + std::to_string(i)).c_str(), ¶ms.
ao, 0.0f, 1.0f);
677 DrawPropertyLabel(
"Normal Scale");
678 ImGui::SliderFloat((
"##NormalScale" + std::to_string(i)).c_str(), ¶ms.
normalScale, 0.0f, 2.0f);
680 DrawPropertyLabel(
"Emissive Strength");
681 ImGui::SliderFloat((
"##EmissiveStrength" + std::to_string(i)).c_str(), ¶ms.
emissiveStrength, 0.0f, 8.0f);
684 DrawPropertyLabel(
"Alpha Cutoff");
685 ImGui::SliderFloat((
"##AlphaCutoff" + std::to_string(i)).c_str(), ¶ms.
alphaCutoff, 0.0f, 1.0f);
696 if (hasLightComponent && BeginInspectorSection(
"Light")) {
697 LightData& light = lightComponent->getLightData();
698 if (BeginInspectorPropertyTable(
"##LightProperties")) {
699 DrawPropertyValueText(
"Type", GetLightTypeLabel(light.
type));
701 DrawPropertyToggle(
"Cast Shadow",
"##LightCastShadow", &castShadow);
703 DrawPropertyLabel(
"Color");
704 ImGui::ColorEdit3(
"##LightColor", &light.
color.
x);
705 DrawPropertyLabel(
"Intensity");
706 ImGui::SliderFloat(
"##LightIntensity", &light.
intensity, 0.0f, 10.0f);
708 DrawPropertyLabel(
"Direction");
709 ImGui::SliderFloat3(
"##LightDirection", &light.
direction.
x, -1.0f, 1.0f);
712 DrawPropertyLabel(
"Range");
713 ImGui::SliderFloat(
"##LightRange", &light.
range, 0.0f, 100.0f);
734 ImGui::Begin(
"Hierarchy");
736 ImGui::TextDisabled(
"Scene");
737 static ImGuiTextFilter filter;
738 filter.Draw(
"Search...", -1.0f);
746 for (
int i = 0; i < static_cast<int>(actors.size()); ++i) {
747 const auto& actor = actors[i];
748 std::string actorName = actor ? actor->getName() :
"Actor";
749 const char* actorTypeLabel = GetActorTypeLabel(actor);
750 ImVec4 actorTypeColor = GetActorTypeColor(actor);
751 std::string filterLabel = actorName +
" " + actorTypeLabel;
752 if (!filter.PassFilter(filterLabel.c_str())) {
758 const bool hasMeshRenderer = !meshRenderer.isNull();
759 const bool hasLightComponent = !lightComponent.isNull();
764 ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.18f, 0.32f, 0.58f, 0.70f));
765 ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.22f, 0.38f, 0.66f, 0.85f));
766 ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.24f, 0.42f, 0.72f, 0.95f));
769 ImVec2 rowSize(ImGui::GetContentRegionAvail().x, 42.0f);
770 if (ImGui::Selectable(
"##actorRow", isSelected, ImGuiSelectableFlags_SpanAvailWidth, rowSize)) {
774 ImVec2 min = ImGui::GetItemRectMin();
775 ImVec2 max = ImGui::GetItemRectMax();
776 ImDrawList* drawList = ImGui::GetWindowDrawList();
777 drawList->AddText(ImVec2(min.x + 12.0f, min.y + 6.0f), ImGui::GetColorU32(ImGuiCol_Text), actorName.c_str());
778 drawList->AddText(ImVec2(min.x + 12.0f, min.y + 23.0f), AccentU32(actorTypeColor), actorTypeLabel);
780 float badgeX = max.x - 84.0f;
781 if (hasMeshRenderer) {
782 drawList->AddRectFilled(ImVec2(badgeX, min.y + 12.0f), ImVec2(badgeX + 28.0f, min.y + 30.0f), IM_COL32(68, 118, 180, 180), 6.0f);
783 drawList->AddText(ImVec2(badgeX + 9.0f, min.y + 14.0f), IM_COL32(240, 244, 255, 255),
"M");
786 if (hasLightComponent) {
787 drawList->AddRectFilled(ImVec2(badgeX, min.y + 12.0f), ImVec2(badgeX + 28.0f, min.y + 30.0f), IM_COL32(180, 142, 52, 180), 6.0f);
788 drawList->AddText(ImVec2(badgeX + 9.0f, min.y + 14.0f), IM_COL32(255, 248, 232, 255),
"L");
792 ImGui::PopStyleColor(3);
802 if (actor.
isNull())
return;
803 auto transform = actor->getComponent<
Transform>();
804 if (transform.isNull())
return;
811 if (rectW < 64.0f || rectH < 64.0f)
817 float* pos =
const_cast<float*
>(transform->getPosition().data());
818 float* rot =
const_cast<float*
>(transform->getRotation().data());
819 float* sca =
const_cast<float*
>(transform->getScale().data());
820 float gizmoRotation[3] = {
827 ImGuizmo::RecomposeMatrixFromComponents(pos, gizmoRotation, sca, mArr);
829 float vArr[16], pArr[16];
833 ImGuizmo::SetOrthographic(
false);
839 ImGuizmo::SetDrawlist(ImGui::GetForegroundDrawList());
842 ImGuizmo::SetGizmoSizeClipSpace(0.12f);
843 ImGuizmo::AllowAxisFlip(
true);
844 ImGuizmo::SetRect(rectX, rectY, rectW, rectH);
846 float snapValue = 25.0f;
850 float snap[3] = { snapValue, snapValue, snapValue };
851 bool useSnap = ImGui::GetIO().KeyCtrl;
854 activeGizmoMode = ImGuizmo::LOCAL;
857 ImGuizmo::Manipulate(
864 useSnap ? snap : nullptr
871 float newPos[3], newRot[3], newSca[3];
872 ImGuizmo::DecomposeMatrixToComponents(mArr, newPos, newRot, newSca);
874 transform->setPosition(
EU::Vector3(newPos[0], newPos[1], newPos[2]));
875 transform->setRotation(
EU::Vector3(DegToRad(newRot[0]), DegToRad(newRot[1]), DegToRad(newRot[2])));
876 transform->setScale(
EU::Vector3(newSca[0], newSca[1], newSca[2]));
942 ImGuiViewport* viewport = ImGui::GetMainViewport();
944 const float menuBarHeight = 24.0f;
945 const float ribbonHeight = 72.0f;
946 const float totalHeight = menuBarHeight + ribbonHeight;
951 ImGui::SetNextWindowPos(viewport->Pos, ImGuiCond_Always);
952 ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, menuBarHeight), ImGuiCond_Always);
954 ImGuiWindowFlags menuFlags =
955 ImGuiWindowFlags_NoDecoration |
956 ImGuiWindowFlags_NoMove |
957 ImGuiWindowFlags_NoSavedSettings |
958 ImGuiWindowFlags_NoScrollWithMouse |
959 ImGuiWindowFlags_NoScrollbar |
960 ImGuiWindowFlags_MenuBar;
962 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
963 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f, 4.0f));
964 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.10f, 0.11f, 0.14f, 1.0f));
966 if (ImGui::Begin(
"##StudioMenuBar",
nullptr, menuFlags))
968 if (ImGui::BeginMenuBar())
970 if (ImGui::BeginMenu(
"File"))
972 ImGui::MenuItem(
"New Place");
973 ImGui::MenuItem(
"Open Place");
974 if (ImGui::MenuItem(
"Save",
"Ctrl+S"))
979 if (ImGui::MenuItem(
"Exit"))
986 if (ImGui::BeginMenu(
"Edit"))
988 ImGui::MenuItem(
"Undo");
989 ImGui::MenuItem(
"Redo");
991 ImGui::MenuItem(
"Cut");
992 ImGui::MenuItem(
"Copy");
993 ImGui::MenuItem(
"Paste");
997 if (ImGui::BeginMenu(
"View"))
999 ImGui::MenuItem(
"Explorer");
1000 ImGui::MenuItem(
"Properties");
1001 ImGui::MenuItem(
"Toolbox");
1005 if (ImGui::BeginMenu(
"Plugins"))
1007 ImGui::MenuItem(
"Manage Plugins");
1008 ImGui::MenuItem(
"Plugin Folder");
1012 if (ImGui::BeginMenu(
"Test"))
1014 ImGui::MenuItem(
"Play");
1015 ImGui::MenuItem(
"Pause");
1016 ImGui::MenuItem(
"Stop");
1020 if (ImGui::BeginMenu(
"Window"))
1022 ImGui::MenuItem(
"Reset Layout");
1026 if (ImGui::BeginMenu(
"Help"))
1028 ImGui::MenuItem(
"Documentation");
1029 ImGui::MenuItem(
"About");
1033 ImGui::EndMenuBar();
1038 ImGui::PopStyleColor();
1039 ImGui::PopStyleVar(2);
1044 ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + menuBarHeight), ImGuiCond_Always);
1045 ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, ribbonHeight), ImGuiCond_Always);
1047 ImGuiWindowFlags ribbonFlags =
1048 ImGuiWindowFlags_NoDecoration |
1049 ImGuiWindowFlags_NoMove |
1050 ImGuiWindowFlags_NoSavedSettings |
1051 ImGuiWindowFlags_NoScrollWithMouse |
1052 ImGuiWindowFlags_NoScrollbar;
1054 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
1055 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f));
1056 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.0f, 6.0f));
1057 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.08f, 0.09f, 0.12f, 1.0f));
1058 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.14f, 0.15f, 0.19f, 1.0f));
1059 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.20f, 0.22f, 0.28f, 1.0f));
1060 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.24f, 0.26f, 0.34f, 1.0f));
1062 if (ImGui::Begin(
"##StudioRibbon",
nullptr, ribbonFlags))
1064 auto ribbonButton = [&](
const char* id,
const char* topText,
const char* bottomText, ImVec2 size,
bool active =
false) ->
bool
1067 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.24f, 0.34f, 0.58f, 1.0f));
1069 bool pressed = ImGui::Button(
id, size);
1071 ImVec2 min = ImGui::GetItemRectMin();
1072 ImVec2 max = ImGui::GetItemRectMax();
1075 ImDrawList* drawList = ImGui::GetWindowDrawList();
1077 ImVec2 topSize = ImGui::CalcTextSize(topText);
1078 ImVec2 bottomSize = ImGui::CalcTextSize(bottomText);
1080 float centerX = (min.x + max.x) * 0.5f;
1083 ImVec2(centerX - topSize.x * 0.5f, min.y + 10.0f),
1084 ImGui::GetColorU32(ImGuiCol_Text),
1089 ImVec2(centerX - bottomSize.x * 0.5f, min.y + 34.0f),
1090 ImGui::GetColorU32(ImGuiCol_TextDisabled),
1095 ImGui::PopStyleColor();
1100 auto separatorGroup = [&]()
1103 ImGui::Dummy(ImVec2(6.0f, 1.0f));
1106 ImVec2 p = ImGui::GetCursorScreenPos();
1107 ImDrawList* draw = ImGui::GetWindowDrawList();
1110 ImVec2(p.x, p.y + 48.0f),
1111 IM_COL32(80, 80, 90, 255),
1115 ImGui::Dummy(ImVec2(8.0f, 48.0f));
1119 const ImVec2 btnSize(72.0f, 52.0f);
1122 if (ribbonButton(
"##Select",
"Select",
"Cursor", btnSize,
false))
1146 if (ribbonButton(
"##Transform",
"Transform",
"Tool", btnSize,
false))
1154 if (ribbonButton(
"##Part",
"Part",
"Mesh", btnSize,
false))
1160 if (ribbonButton(
"##Terrain",
"Terrain",
"Edit", btnSize,
false))
1166 if (ribbonButton(
"##Material",
"Material",
"Editor", btnSize,
false))
1172 if (ribbonButton(
"##Color",
"Color",
"Picker", btnSize,
false))
1180 if (ribbonButton(
"##Explorer",
"Explorer",
"Panel", btnSize,
false))
1186 if (ribbonButton(
"##Properties",
"Properties",
"Panel", btnSize,
false))
1192 if (ribbonButton(
"##Toolbox",
"Toolbox",
"Assets", btnSize,
false))
1199 ImGui::PopStyleColor(4);
1200 ImGui::PopStyleVar(3);
1205 ImGuiWindowFlags flags =
1206 ImGuiWindowFlags_NoScrollbar |
1207 ImGuiWindowFlags_NoScrollWithMouse |
1209 ImGuiWindowFlags_NoCollapse;
1211 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
1213 if (ImGui::Begin(
"Viewport",
nullptr, flags))
1217 ImVec2 panelMin = ImGui::GetCursorScreenPos();
1218 ImVec2 panelSize = ImGui::GetContentRegionAvail();
1220 if (panelSize.x < 1.0f) panelSize.x = 1.0f;
1221 if (panelSize.y < 1.0f) panelSize.y = 1.0f;
1225 ImGui::Image((ImTextureID)viewportSRV, panelSize);
1229 ImGui::InvisibleButton(
"##ViewportSurface", panelSize);
1230 ImVec2 itemMin = ImGui::GetItemRectMin();
1231 ImVec2 itemMax = ImGui::GetItemRectMax();
1232 ImDrawList* drawList = ImGui::GetWindowDrawList();
1234 drawList->AddRectFilled(itemMin, itemMax, IM_COL32(20, 20, 25, 255));
1236 ImVec2(itemMin.x + 12.0f, itemMin.y + 12.0f),
1237 IM_COL32(220, 220, 220, 255),
1238 "Viewport sin textura"
1242 ImVec2 itemMin = ImGui::GetItemRectMin();
1243 ImVec2 itemMax = ImGui::GetItemRectMax();
1245 m_viewportSize = ImVec2(itemMax.x - itemMin.x, itemMax.y - itemMin.y);
1250 m_viewportFocused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
1254 ImGui::PopStyleVar();
1258 ID3D11ShaderResourceView* finalViewportSRV,
1259 ID3D11ShaderResourceView* shadowMapSRV)
1261 ImGui::Begin(
"Render Debug");
1263 struct DebugViewItem {
1265 ID3D11ShaderResourceView* srv;
1268 DebugViewItem items[] = {
1269 {
"Pre-Shadow", preShadowSRV },
1270 {
"Scene Final", finalViewportSRV },
1271 {
"Shadow Map", shadowMapSRV }
1274 static int selectedView = 0;
1275 const float thumbnailHeight = 120.0f;
1277 ImGui::TextDisabled(
"Generated pass textures");
1280 for (
int i = 0; i < IM_ARRAYSIZE(items); ++i) {
1282 if (ImGui::Selectable(items[i].label, selectedView == i, 0, ImVec2(0.0f, 20.0f))) {
1287 const float thumbnailWidth = thumbnailHeight * 1.6f;
1288 ImGui::Image((ImTextureID)items[i].srv, ImVec2(thumbnailWidth, thumbnailHeight));
1291 ImGui::Dummy(ImVec2(thumbnailHeight * 1.6f, thumbnailHeight));
1292 ImGui::SameLine(0.0f, 0.0f);
1293 ImGui::TextDisabled(
"Unavailable");
1296 if (i + 1 < IM_ARRAYSIZE(items)) {
1303 ImGui::Text(
"Focused View: %s", items[selectedView].label);
1305 ImVec2 available = ImGui::GetContentRegionAvail();
1306 if (items[selectedView].srv && available.x > 16.0f && available.y > 16.0f) {
1307 ImGui::Image((ImTextureID)items[selectedView].srv, available);
1310 ImGui::Dummy(available);
1311 ImGui::SameLine(0.0f, 0.0f);
1312 ImGui::TextDisabled(
"No texture bound for this view");
1320 ImGuiViewport* mainViewport = ImGui::GetMainViewport();
1323 const float topOffset = 96.0f;
1325 ImVec2 dockPos = ImVec2(mainViewport->Pos.x, mainViewport->Pos.y + topOffset);
1326 ImVec2 dockSize = ImVec2(mainViewport->Size.x, mainViewport->Size.y - topOffset);
1328 ImGuiWindowFlags window_flags =
1329 ImGuiWindowFlags_NoTitleBar |
1330 ImGuiWindowFlags_NoCollapse |
1331 ImGuiWindowFlags_NoResize |
1332 ImGuiWindowFlags_NoMove |
1333 ImGuiWindowFlags_NoBringToFrontOnFocus |
1334 ImGuiWindowFlags_NoNavFocus |
1335 ImGuiWindowFlags_NoBackground |
1336 ImGuiWindowFlags_NoDecoration |
1337 ImGuiWindowFlags_NoSavedSettings |
1338 ImGuiWindowFlags_MenuBar;
1340 ImGui::SetNextWindowPos(dockPos, ImGuiCond_Always);
1341 ImGui::SetNextWindowSize(dockSize, ImGuiCond_Always);
1342 ImGui::SetNextWindowViewport(mainViewport->ID);
1344 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
1345 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
1346 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
1348 ImGui::Begin(
"##MainEditorDockspace",
nullptr, window_flags);
1350 ImGuiID dockspace_id = ImGui::GetID(
"##EditorDockspace");
1351 ImGuiDockNodeFlags dockspace_flags =
1352 ImGuiDockNodeFlags_None |
1353 ImGuiDockNodeFlags_PassthruCentralNode;
1355 ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
1359 ImGui::PopStyleVar(3);
Declara la API de DeviceContext dentro del subsistema Core.