adding and integrating ImGuizmo
This commit is contained in:
@@ -2,18 +2,37 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <sophia/components.hpp>
|
||||
#include <string>
|
||||
|
||||
void SceneHierarchyPanel::onUpdate(const sophia::FrameInfo&) {
|
||||
drawSceneSelector();
|
||||
ImGui::Separator();
|
||||
|
||||
if (!context.hasScene()) {
|
||||
ImGui::TextDisabled("No scene open");
|
||||
return;
|
||||
}
|
||||
|
||||
sophia::Scene& scene = context.getScene();
|
||||
sophia::Entity& selected = context.selected;
|
||||
|
||||
if (ImGui::Button("+ Sprite")) {
|
||||
selected = scene.createEntity("Sprite");
|
||||
selected.addComponent<sophia::SpriteComponent>();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("+ Cube")) {
|
||||
selected = scene.createEntity("Cube");
|
||||
selected.addComponent<sophia::MeshComponent>(
|
||||
sophia::MeshComponent{.handle = cubeMesh});
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Flat for now: there is no parent/child component yet.
|
||||
scene.forEachEntity([this](sophia::Entity entity) {
|
||||
scene.forEachEntity([&selected](sophia::Entity entity) {
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf |
|
||||
ImGuiTreeNodeFlags_NoTreePushOnOpen |
|
||||
ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||
@@ -30,3 +49,86 @@ void SceneHierarchyPanel::onUpdate(const sophia::FrameInfo&) {
|
||||
ImGui::PopID();
|
||||
});
|
||||
}
|
||||
|
||||
namespace {
|
||||
// See SceneHierarchyPanel::renameFocusFrames.
|
||||
constexpr int RENAME_FOCUS_FRAMES = 2;
|
||||
} // namespace
|
||||
|
||||
void SceneHierarchyPanel::drawSceneSelector() {
|
||||
// Leave room for the button: its label, its padding, and the gap to it.
|
||||
constexpr const char* ADD_SCENE_LABEL = "Add Scene";
|
||||
const ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImGui::SetNextItemWidth(-(ImGui::CalcTextSize(ADD_SCENE_LABEL).x +
|
||||
style.FramePadding.x * 2.f + style.ItemSpacing.x));
|
||||
|
||||
const std::string* current = context.getSceneName(context.getSceneHandle());
|
||||
bool startRename = false;
|
||||
|
||||
if (renamingScene && current) {
|
||||
drawSceneRename();
|
||||
} else {
|
||||
renamingScene = false;
|
||||
if (ImGui::BeginCombo("##scene", current ? current->c_str() : "No scene")) {
|
||||
for (const EditorContext::OpenScene& open : context.getOpenScenes()) {
|
||||
ImGui::PushID(static_cast<int>(open.handle.index));
|
||||
bool isCurrent = open.handle == context.getSceneHandle();
|
||||
if (ImGui::Selectable(open.name.c_str(), isCurrent) && !isCurrent) {
|
||||
context.setScene(open.handle);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (current && ImGui::BeginPopupContextItem("##sceneMenu")) {
|
||||
startRename = ImGui::MenuItem("Rename", "F2");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
startRename = startRename || (current && ImGui::IsWindowFocused() &&
|
||||
!ImGui::GetIO().WantTextInput &&
|
||||
ImGui::IsKeyPressed(ImGuiKey_F2));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ADD_SCENE_LABEL)) {
|
||||
std::string name = "Untitled " + std::to_string(++this->untitledSceneCount);
|
||||
context.setScene(context.createScene(std::move(name)));
|
||||
startRename = false;
|
||||
}
|
||||
|
||||
if (startRename) {
|
||||
renamingScene = true;
|
||||
renameFocusFrames = RENAME_FOCUS_FRAMES;
|
||||
std::snprintf(renameBuffer.data(), renameBuffer.size(), "%s",
|
||||
current->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneHierarchyPanel::drawSceneRename() {
|
||||
if (renameFocusFrames == RENAME_FOCUS_FRAMES) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
}
|
||||
|
||||
ImGui::InputText("##sceneName", renameBuffer.data(), renameBuffer.size(),
|
||||
ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
bool active = ImGui::IsItemActive();
|
||||
if (active) {
|
||||
renameFocusFrames = 0;
|
||||
} else if (renameFocusFrames > 0) {
|
||||
renameFocusFrames--;
|
||||
return;
|
||||
}
|
||||
|
||||
// Escape reverts the text before deactivating, so committing whatever is
|
||||
// left when the field closes covers Enter, clicking away and Escape alike.
|
||||
if (!active) {
|
||||
std::string name = renameBuffer.data();
|
||||
// Keep the old name rather than leave the scene nameless.
|
||||
if (name.find_first_not_of(' ') != std::string::npos) {
|
||||
context.renameScene(context.getSceneHandle(), std::move(name));
|
||||
}
|
||||
renamingScene = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user