#include "InspectorWindow.h" #include // for debugging or printing if needed #include // for strcpy, if needed #include // Required for glm::value_ptr #include extern std::vector g_GameObjects; extern GameObject *g_SelectedObject; // Pointer to the currently selected object void InspectorWindow::Show() { // Increase window/item spacing for a cleaner look ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12, 12)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6, 4)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 10)); if (ImGui::Begin("Inspector")) { // Title label (white text) if (g_SelectedObject) { if (g_SelectedObject == nullptr) { ImGui::Text("No object selected."); return; } // Display object name and component count ImGui::Text("Editing Object: %s", g_SelectedObject->name.c_str()); ImGui::Text("Components: %d", g_SelectedObject->GetComponentCount()); ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); // Begin two-column layout for labels and inputs ImGui::Columns(2, "InspectorColumns", true); // 2 columns, ID "InspectorColumns", border=true ImGui::SetColumnWidth(0, 100.0f); // Optional: Set fixed width for the first column // Label in the first column ImGui::Text("Tag:"); ImGui::NextColumn(); // Move to the second column // Define buffer size const size_t BUFFER_SIZE = 256; // Allocate buffer and copy the current string char buffer[BUFFER_SIZE]; std::strncpy(buffer, g_SelectedObject->name.c_str(), BUFFER_SIZE - 1); buffer[BUFFER_SIZE - 1] = '\0'; // Ensure null-termination // Unique identifier for the InputText to prevent ImGui state conflicts const char *inputLabel = "##TagInput"; // Render InputText widget if (ImGui::InputText(inputLabel, buffer, BUFFER_SIZE)) { // Update the GameObject's name if modified g_SelectedObject->name = buffer; } ImGui::NextColumn(); // Move back to the first column (if adding more fields) // End columns ImGui::Columns(1); ImGui::Spacing(); ImGui::Separator(); ImGui::Spacing(); // =========================== // 1) TRANSFORM // =========================== std::shared_ptr transform = g_SelectedObject->GetComponent(); std::shared_ptr mesh = g_SelectedObject->GetComponent(); // Color the Transform header if (transform && g_SelectedObject) //! Funny: I did not put a null check here and it broke everything. { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); bool transformOpen = ImGui::CollapsingHeader("Transform##Main", ImGuiTreeNodeFlags_DefaultOpen); ImGui::PopStyleColor(); // Transform* transform = &g_SelectedObject->transform; // printf("%p\n", &transform); if (transformOpen) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); ImGui::TextUnformatted("Controls the object's Position, Rotation, and Scale."); ImGui::EndTooltip(); } // ----------------------------------- // Position // ----------------------------------- ImGui::TextUnformatted("Position"); ImGui::Spacing(); { // We'll assign colors for X, Y, Z buttons // (normal, hovered, active) static const ImVec4 colX = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); static const ImVec4 colXHover = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); static const ImVec4 colXActive = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); static const ImVec4 colY = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); static const ImVec4 colYHover = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); static const ImVec4 colYActive = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); static const ImVec4 colZ = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); static const ImVec4 colZHover = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); static const ImVec4 colZActive = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); const char *axisNames[3] = {"X", "Y", "Z"}; // We'll reference transform.position here float *pos = glm::value_ptr(transform->position); ImGui::PushID("PositionRow"); for (int i = 0; i < 3; i++) { // Determine color set ImVec4 col, colH, colA; if (i == 0) { col = colX; colH = colXHover; colA = colXActive; } else if (i == 1) { col = colY; colH = colYHover; colA = colYActive; } else { col = colZ; colH = colZHover; colA = colZActive; } // Push color style for button ImGui::PushStyleColor(ImGuiCol_Button, col); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); // Small button with the axis name if (ImGui::Button(axisNames[i], ImVec2(20, 0))) { // No action on click, but we have a box with color } ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::SetNextItemWidth(60.0f); ImGui::DragFloat((std::string("##Pos") + axisNames[i]).c_str(), &pos[i], 0.1f); if (i < 2) ImGui::SameLine(0, 15); } ImGui::PopID(); } ImGui::Spacing(); ImGui::Separator(); // ----------------------------------- // Rotation // ----------------------------------- ImGui::TextUnformatted("Rotation"); ImGui::Spacing(); { // Same approach, but referencing transform.rotation const char *axisNames[3] = {"X", "Y", "Z"}; float *rot = glm::value_ptr(transform->rotation); // We can reuse the same color sets ImGui::PushID("RotationRow"); for (int i = 0; i < 3; i++) { // Decide color sets for X, Y, Z ImVec4 col, colH, colA; if (i == 0) { col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); } else if (i == 1) { col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); } else { col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); } ImGui::PushStyleColor(ImGuiCol_Button, col); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); if (ImGui::Button(axisNames[i], ImVec2(20, 0))) { // No action } ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::SetNextItemWidth(60.0f); ImGui::DragFloat((std::string("##Rot") + axisNames[i]).c_str(), &rot[i], 0.1f); if (i < 2) ImGui::SameLine(0, 15); } ImGui::PopID(); } ImGui::Spacing(); ImGui::Separator(); // ----------------------------------- // Scale // ----------------------------------- ImGui::TextUnformatted("Scale"); ImGui::Spacing(); { const char *axisNames[3] = {"X", "Y", "Z"}; float *scl = glm::value_ptr(transform->scale); ImGui::PushID("ScaleRow"); for (int i = 0; i < 3; i++) { // same color approach ImVec4 col, colH, colA; if (i == 0) { col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); } else if (i == 1) { col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); } else { col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); } ImGui::PushStyleColor(ImGuiCol_Button, col); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); if (ImGui::Button(axisNames[i], ImVec2(20, 0))) { // No action } ImGui::PopStyleColor(3); ImGui::SameLine(); ImGui::SetNextItemWidth(60.0f); ImGui::DragFloat((std::string("##Scl") + axisNames[i]).c_str(), &scl[i], 0.1f); if (i < 2) ImGui::SameLine(0, 15); } ImGui::PopID(); } ImGui::Spacing(); ImGui::Separator(); } } if (mesh && g_SelectedObject) //! Funny: I did not put a null check here and it broke everything. { // Transform* transform = &g_SelectedObject->transform; ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen); ImGui::PopStyleColor(); // printf("%p\n", &transform); if (meshOpen) { int vao = static_cast(mesh->vao); if (ImGui::InputInt("vao", &vao, 1, 0)) { mesh->vao = static_cast(vao); } int indexCount = static_cast(mesh->indexCount); if (ImGui::InputInt("indexCount", &indexCount, 1, 0)) { mesh->indexCount = static_cast(indexCount); } int textureID = static_cast(mesh->textureID); if (ImGui::InputInt("textureID", &textureID, 1, 0)) { mesh->textureID = static_cast(textureID); } } } ImGui::Spacing(); // =========================== // 2) SCRIPT // =========================== // We keep script text in white // if (ImGui::CollapsingHeader("Script##Main", ImGuiTreeNodeFlags_DefaultOpen)) //{ // if (ImGui::IsItemHovered()) // { // ImGui::BeginTooltip(); // ImGui::TextUnformatted("Attach a script or logic component here."); // ImGui::EndTooltip(); // } // ImGui::TextUnformatted("Script Name:"); // ImGui::SameLine(); // { // char buffer[128]; // std::snprintf(buffer, sizeof(buffer), "%s", script.scriptName.c_str()); // ImGui::SetNextItemWidth(-1); // if (ImGui::InputText("##ScriptName", buffer, sizeof(buffer))) // { // script.scriptName = buffer; // } // } // ImGui::Spacing(); // ImGui::TextUnformatted("Script Enabled:"); // ImGui::SameLine(); // ImGui::Checkbox("##ScriptEnabled", &script.enabled); // ImGui::Spacing(); // ImGui::Separator(); //} } ImGui::End(); } // // Restore style ImGui::PopStyleVar(3); }