This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <studio/studio.hpp>
|
#include <studio/undocommand.hpp>
|
||||||
|
|
||||||
#include <nostalgia/gfx/palette.hpp>
|
#include <nostalgia/gfx/palette.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -78,15 +78,16 @@ PaletteEditorImGui::PaletteEditorImGui(studio::Context &sctx, ox::StringParam pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PaletteEditorImGui::draw(studio::Context&) noexcept {
|
void PaletteEditorImGui::draw(studio::Context&) noexcept {
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
auto const paneSize = ImGui::GetContentRegionAvail();
|
auto const paneSize = ImGui::GetContentRegionAvail();
|
||||||
{
|
{
|
||||||
ImGui::BeginChild("Pages", {280, paneSize.y}, true);
|
ImGui::BeginChild("Pages", {scale * 280, paneSize.y}, true);
|
||||||
drawPagesEditor();
|
drawPagesEditor();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
{
|
{
|
||||||
ImGui::BeginChild("Colors", {-1, paneSize.y}, true);
|
ImGui::BeginChild("Colors", {scale * -1, paneSize.y}, true);
|
||||||
drawColorsEditor();
|
drawColorsEditor();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
@@ -165,7 +166,7 @@ void PaletteEditorImGui::drawColorsEditor() noexcept {
|
|||||||
static constexpr auto toolbarHeight = 40;
|
static constexpr auto toolbarHeight = 40;
|
||||||
{
|
{
|
||||||
auto constexpr sz = ImVec2{70, 24};
|
auto constexpr sz = ImVec2{70, 24};
|
||||||
if (ImGui::Button("Add", sz)) {
|
if (ig::PushButton("Add", sz)) {
|
||||||
auto const colorSz = colorCnt(m_pal, m_page);
|
auto const colorSz = colorCnt(m_pal, m_page);
|
||||||
constexpr Color16 c = 0;
|
constexpr Color16 c = 0;
|
||||||
std::ignore = pushCommand<AddColorCommand>(m_pal, c, colorSz);
|
std::ignore = pushCommand<AddColorCommand>(m_pal, c, colorSz);
|
||||||
@@ -173,7 +174,7 @@ void PaletteEditorImGui::drawColorsEditor() noexcept {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginDisabled(m_selectedColorRow >= colorCnt(m_pal, m_page));
|
ImGui::BeginDisabled(m_selectedColorRow >= colorCnt(m_pal, m_page));
|
||||||
{
|
{
|
||||||
if (ImGui::Button("Remove", sz)) {
|
if (ig::PushButton("Remove", sz)) {
|
||||||
std::ignore = pushCommand<RemoveColorCommand>(m_pal, m_selectedColorRow);
|
std::ignore = pushCommand<RemoveColorCommand>(m_pal, m_selectedColorRow);
|
||||||
m_selectedColorRow = ox::min(colorCnt(m_pal, m_page) - 1, m_selectedColorRow);
|
m_selectedColorRow = ox::min(colorCnt(m_pal, m_page) - 1, m_selectedColorRow);
|
||||||
colorEditor = m_selectedColorRow < colorCnt(m_pal, m_page);
|
colorEditor = m_selectedColorRow < colorCnt(m_pal, m_page);
|
||||||
@@ -183,17 +184,18 @@ void PaletteEditorImGui::drawColorsEditor() noexcept {
|
|||||||
}
|
}
|
||||||
auto const tblWidth = (colorsSz.x - static_cast<float>(colorEditorWidth) - 8.f)
|
auto const tblWidth = (colorsSz.x - static_cast<float>(colorEditorWidth) - 8.f)
|
||||||
* static_cast<float>(colorEditor);
|
* static_cast<float>(colorEditor);
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
ImGui::BeginTable(
|
ImGui::BeginTable(
|
||||||
"Colors",
|
"Colors",
|
||||||
6,
|
6,
|
||||||
tableFlags,
|
tableFlags,
|
||||||
{tblWidth, colorsSz.y - (toolbarHeight + 5)});
|
{tblWidth * scale, colorsSz.y - (toolbarHeight + 5) * scale});
|
||||||
{
|
{
|
||||||
ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25);
|
ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25 * scale);
|
||||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 100);
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 100 * scale);
|
||||||
ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 40);
|
ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 40 * scale);
|
||||||
ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 40);
|
ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 40 * scale);
|
||||||
ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 40);
|
ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 40 * scale);
|
||||||
ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_NoHide);
|
ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_NoHide);
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
if (m_page < m_pal.pages.size()) {
|
if (m_page < m_pal.pages.size()) {
|
||||||
@@ -236,10 +238,11 @@ void PaletteEditorImGui::drawColorsEditor() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PaletteEditorImGui::drawPagesEditor() noexcept {
|
void PaletteEditorImGui::drawPagesEditor() noexcept {
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
constexpr auto tableFlags = ImGuiTableFlags_RowBg;
|
constexpr auto tableFlags = ImGuiTableFlags_RowBg;
|
||||||
auto const paneSz = ImGui::GetContentRegionAvail();
|
auto const paneSz = ImGui::GetContentRegionAvail();
|
||||||
constexpr auto toolbarHeight = 40;
|
constexpr auto toolbarHeight = 40;
|
||||||
auto const btnSz = ImVec2{paneSz.x / 4 - 5.5f, 24};
|
auto const btnSz = ImVec2{paneSz.x / 4 - 5.5f * scale, 24 * scale};
|
||||||
if (ImGui::Button("Add", btnSz)) {
|
if (ImGui::Button("Add", btnSz)) {
|
||||||
if (m_pal.pages.empty()) {
|
if (m_pal.pages.empty()) {
|
||||||
std::ignore = pushCommand<AddPageCommand>(m_pal);
|
std::ignore = pushCommand<AddPageCommand>(m_pal);
|
||||||
@@ -265,7 +268,7 @@ void PaletteEditorImGui::drawPagesEditor() noexcept {
|
|||||||
"PageSelect",
|
"PageSelect",
|
||||||
2,
|
2,
|
||||||
tableFlags,
|
tableFlags,
|
||||||
{paneSz.x, paneSz.y - (toolbarHeight + 5)});
|
{paneSz.x, paneSz.y - (toolbarHeight + 5) * scale});
|
||||||
{
|
{
|
||||||
ImGui::TableSetupColumn("Page", ImGuiTableColumnFlags_WidthFixed, 60);
|
ImGui::TableSetupColumn("Page", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 200);
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 200);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ struct SubSheetRef {
|
|||||||
TileSheet::SubSheetIdx subsheet{};
|
TileSheet::SubSheetIdx subsheet{};
|
||||||
};
|
};
|
||||||
|
|
||||||
OX_MODEL_BEGIN(SubSheetRef)
|
static OX_MODEL_BEGIN(SubSheetRef)
|
||||||
OX_MODEL_FIELD(subsheet)
|
OX_MODEL_FIELD(subsheet)
|
||||||
OX_MODEL_END()
|
OX_MODEL_END()
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ struct TileSheetEditorConfig {
|
|||||||
TileSheet::SubSheetIdx activeSubsheet{};
|
TileSheet::SubSheetIdx activeSubsheet{};
|
||||||
};
|
};
|
||||||
|
|
||||||
OX_MODEL_BEGIN(TileSheetEditorConfig)
|
static OX_MODEL_BEGIN(TileSheetEditorConfig)
|
||||||
OX_MODEL_FIELD_RENAME(activeSubsheet, active_subsheet)
|
OX_MODEL_FIELD_RENAME(activeSubsheet, active_subsheet)
|
||||||
OX_MODEL_END()
|
OX_MODEL_END()
|
||||||
|
|
||||||
@@ -149,27 +149,30 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
|||||||
if (ImGui::IsKeyDown(ImGuiKey_ModCtrl) && !m_palPathFocused) {
|
if (ImGui::IsKeyDown(ImGuiKey_ModCtrl) && !m_palPathFocused) {
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_A)) {
|
if (ImGui::IsKeyPressed(ImGuiKey_A)) {
|
||||||
auto const &img = m_model.activeSubSheet();
|
auto const &img = m_model.activeSubSheet();
|
||||||
m_model.setSelection({{}, {img.columns * TileWidth - 1, img.rows * TileHeight - 1}});
|
m_model.setSelection({
|
||||||
|
{},
|
||||||
|
{img.columns * TileWidth - 1, img.rows * TileHeight - 1}});
|
||||||
} else if (ImGui::IsKeyPressed(ImGuiKey_G)) {
|
} else if (ImGui::IsKeyPressed(ImGuiKey_G)) {
|
||||||
m_model.clearSelection();
|
m_model.clearSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
auto const paneSize = ImGui::GetContentRegionAvail();
|
auto const paneSize = ImGui::GetContentRegionAvail();
|
||||||
auto const tileSheetParentSize = ImVec2{paneSize.x - s_palViewWidth, paneSize.y};
|
auto const tileSheetParentSize = ImVec2{paneSize.x - s_palViewWidth * scale, paneSize.y};
|
||||||
auto const fbSize = ox::Vec2{tileSheetParentSize.x - 16, tileSheetParentSize.y - 16};
|
auto const fbSize = ox::Vec2{tileSheetParentSize.x - 16 * scale, tileSheetParentSize.y - 16 * scale};
|
||||||
ImGui::BeginChild("TileSheetView", tileSheetParentSize, true);
|
ImGui::BeginChild("TileSheetView", tileSheetParentSize, true);
|
||||||
{
|
{
|
||||||
drawTileSheet(fbSize);
|
drawTileSheet(fbSize);
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginChild("Controls", {s_palViewWidth - 8, paneSize.y}, true);
|
ImGui::BeginChild("Controls", {(s_palViewWidth - 8) * scale, paneSize.y}, true);
|
||||||
{
|
{
|
||||||
auto const controlsSize = ImGui::GetContentRegionAvail();
|
auto const controlsSize = ImGui::GetContentRegionAvail();
|
||||||
ImGui::BeginChild("ToolBox", {0, 32}, true);
|
ImGui::BeginChild("ToolBox", {0, 32 * scale}, true);
|
||||||
{
|
{
|
||||||
auto const btnSz = ImVec2{45, 14};
|
auto const btnSz = ImVec2{45 * scale, 14 * scale};
|
||||||
if (ImGui::Selectable("Select", m_tool == TileSheetTool::Select, 0, btnSz)) {
|
if (ImGui::Selectable("Select", m_tool == TileSheetTool::Select, 0, btnSz)) {
|
||||||
m_tool = TileSheetTool::Select;
|
m_tool = TileSheetTool::Select;
|
||||||
}
|
}
|
||||||
@@ -193,7 +196,7 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
|||||||
//ig::ComboBox("##Operations", ox::Array<ox::CStringView, 1>{"Operations"}, i);
|
//ig::ComboBox("##Operations", ox::Array<ox::CStringView, 1>{"Operations"}, i);
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::BeginChild("OperationsBox", {0, 35}, ImGuiWindowFlags_NoTitleBar);
|
ImGui::BeginChild("OperationsBox", {0, 35 * scale}, ImGuiWindowFlags_NoTitleBar);
|
||||||
{
|
{
|
||||||
if (ImGui::BeginCombo("##Operations", "Operations", 0)) {
|
if (ImGui::BeginCombo("##Operations", "Operations", 0)) {
|
||||||
if (ImGui::Selectable("Flip X", false)) {
|
if (ImGui::Selectable("Flip X", false)) {
|
||||||
@@ -214,17 +217,17 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
auto const ySize = controlsSize.y - (38 + ig::BtnSz.y + 21);
|
auto const ySize = controlsSize.y - (38 + ig::BtnSz.y + 21) * scale;
|
||||||
// draw palette/color picker
|
// draw palette/color picker
|
||||||
ImGui::BeginChild("Palette", {s_palViewWidth - 24, ySize / 2.f}, true);
|
ImGui::BeginChild("Palette", {(s_palViewWidth - 24) * scale, ySize / 2.f}, true);
|
||||||
{
|
{
|
||||||
drawPaletteMenu();
|
drawPaletteMenu();
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::BeginChild("SubSheets", {s_palViewWidth - 24, ySize / 2.f}, true);
|
ImGui::BeginChild("SubSheets", {(s_palViewWidth - 24) * scale, ySize / 2.f}, true);
|
||||||
{
|
{
|
||||||
static constexpr auto btnHeight = ig::BtnSz.y;
|
auto constexpr btnHeight = ig::BtnSz.y;
|
||||||
auto constexpr btnSize = ImVec2{btnHeight, btnHeight};
|
auto const btnSize = ImVec2{btnHeight, btnHeight};
|
||||||
if (ig::PushButton("+", btnSize)) {
|
if (ig::PushButton("+", btnSize)) {
|
||||||
auto insertOnIdx = m_model.activeSubSheetIdx();
|
auto insertOnIdx = m_model.activeSubSheetIdx();
|
||||||
auto const &parent = m_model.activeSubSheet();
|
auto const &parent = m_model.activeSubSheet();
|
||||||
@@ -247,16 +250,16 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
|||||||
if (ig::PushButton("Export")) {
|
if (ig::PushButton("Export")) {
|
||||||
m_exportMenu.show();
|
m_exportMenu.show();
|
||||||
}
|
}
|
||||||
TileSheet::SubSheetIdx path;
|
|
||||||
static constexpr auto flags =
|
static constexpr auto flags =
|
||||||
ImGuiTableFlags_RowBg |
|
ImGuiTableFlags_RowBg |
|
||||||
ImGuiTableFlags_NoBordersInBody |
|
ImGuiTableFlags_NoBordersInBody |
|
||||||
ImGuiTableFlags_ScrollY;
|
ImGuiTableFlags_ScrollY;
|
||||||
if (ImGui::BeginTable("Subsheets", 4, flags)) {
|
if (ImGui::BeginTable("Subsheets", 4, flags)) {
|
||||||
|
TileSheet::SubSheetIdx path;
|
||||||
ImGui::TableSetupColumn("Subsheet", ImGuiTableColumnFlags_NoHide);
|
ImGui::TableSetupColumn("Subsheet", ImGuiTableColumnFlags_NoHide);
|
||||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 25);
|
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 25 * scale);
|
||||||
ImGui::TableSetupColumn("Columns", ImGuiTableColumnFlags_WidthFixed, 50);
|
ImGui::TableSetupColumn("Columns", ImGuiTableColumnFlags_WidthFixed, 50 * scale);
|
||||||
ImGui::TableSetupColumn("Rows", ImGuiTableColumnFlags_WidthFixed, 50);
|
ImGui::TableSetupColumn("Rows", ImGuiTableColumnFlags_WidthFixed, 50 * scale);
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
drawSubsheetSelector(m_view.img().subsheet, path);
|
drawSubsheetSelector(m_view.img().subsheet, path);
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
@@ -445,10 +448,11 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const &fbSize) noexcept {
|
|||||||
|
|
||||||
void TileSheetEditorImGui::drawPaletteMenu() noexcept {
|
void TileSheetEditorImGui::drawPaletteMenu() noexcept {
|
||||||
ig::IDStackItem const idStackItem{"PaletteMenu"};
|
ig::IDStackItem const idStackItem{"PaletteMenu"};
|
||||||
auto constexpr comboWidthSub = 62;
|
auto const scale = ig::dpiScale();
|
||||||
|
auto const comboWidthSub = 62 * scale;
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub);
|
||||||
auto constexpr palTags = ImGuiInputTextFlags_ReadOnly;
|
auto constexpr palFlags = ImGuiInputTextFlags_ReadOnly;
|
||||||
if (ig::InputTextWithHint("##Palette", "Path to Palette", m_model.palPath(), palTags)) {
|
if (ig::InputTextWithHint("##Palette", "Path to Palette", m_model.palPath(), palFlags)) {
|
||||||
oxLogError(m_model.setPalette(m_model.palPath()));
|
oxLogError(m_model.setPalette(m_model.palPath()));
|
||||||
}
|
}
|
||||||
m_palPathFocused = ImGui::IsItemFocused();
|
m_palPathFocused = ImGui::IsItemFocused();
|
||||||
@@ -571,7 +575,7 @@ void TileSheetEditorImGui::SubSheetEditor::draw(turbine::Context &tctx) noexcept
|
|||||||
ImGui::InputInt("Columns", &m_cols);
|
ImGui::InputInt("Columns", &m_cols);
|
||||||
ImGui::InputInt("Rows", &m_rows);
|
ImGui::InputInt("Rows", &m_rows);
|
||||||
}
|
}
|
||||||
if (ig::PopupControlsOkCancel(popupWidth, m_show) == ig::PopupResponse::OK) {
|
if (ig::PopupControlsOkCancel(m_show) == ig::PopupResponse::OK) {
|
||||||
inputSubmitted.emit(m_name, m_cols, m_rows);
|
inputSubmitted.emit(m_name, m_cols, m_rows);
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
@@ -593,13 +597,13 @@ void TileSheetEditorImGui::ExportMenu::draw(turbine::Context &tctx) noexcept {
|
|||||||
if (!m_show) {
|
if (!m_show) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
constexpr auto popupWidth = 235.f;
|
auto constexpr popupWidth = 235.f;
|
||||||
constexpr auto popupHeight = 85.f;
|
auto constexpr popupHeight = 85.f;
|
||||||
constexpr auto popupSz = ImVec2{popupWidth, popupHeight};
|
auto constexpr popupSz = ImVec2{popupWidth, popupHeight};
|
||||||
if (ig::BeginPopup(tctx, popupName, m_show, popupSz)) {
|
if (ig::BeginPopup(tctx, popupName, m_show, popupSz)) {
|
||||||
ImGui::InputInt("Scale", &m_scale);
|
ImGui::InputInt("Scale", &m_scale);
|
||||||
m_scale = ox::clamp(m_scale, 1, 135);
|
m_scale = ox::clamp(m_scale, 1, 135);
|
||||||
if (ig::PopupControlsOkCancel(popupWidth, m_show) == ig::PopupResponse::OK) {
|
if (ig::PopupControlsOkCancel(m_show) == ig::PopupResponse::OK) {
|
||||||
inputSubmitted.emit(m_scale);
|
inputSubmitted.emit(m_scale);
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "subcommands/change-format/change-format.hpp"
|
#include "subcommands/change-format/change-format.hpp"
|
||||||
|
|
||||||
#include "configfile.hpp"
|
#include "configfile.hpp"
|
||||||
|
#include "font.hpp"
|
||||||
#include "studioui.hpp"
|
#include "studioui.hpp"
|
||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
@@ -129,7 +130,7 @@ static ox::Error run(
|
|||||||
if (m->id() == moduleId) {
|
if (m->id() == moduleId) {
|
||||||
for (auto const &c : m->commands()) {
|
for (auto const &c : m->commands()) {
|
||||||
if (c.name == subCmd) {
|
if (c.name == subCmd) {
|
||||||
auto kctx = keel::init(
|
auto const kctx = keel::init(
|
||||||
ox::make_unique<ox::PassThroughFS>(projectDir),
|
ox::make_unique<ox::PassThroughFS>(projectDir),
|
||||||
c.name);
|
c.name);
|
||||||
if (kctx.error) {
|
if (kctx.error) {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void AboutPopup::draw(Context &sctx) noexcept {
|
|||||||
if (ImGui::BeginPopupModal("About", &open, modalFlags)) {
|
if (ImGui::BeginPopupModal("About", &open, modalFlags)) {
|
||||||
ImGui::Text("%s\n\nBuild date: %s", m_text.c_str(), __DATE__);
|
ImGui::Text("%s\n\nBuild date: %s", m_text.c_str(), __DATE__);
|
||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
ImGui::Dummy({148.0f, 0.0f});
|
ig::Dummy({148.0f, 0.0f});
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ig::PushButton("Close")) {
|
if (ig::PushButton("Close")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
|||||||
@@ -79,13 +79,14 @@ void FileInfo::draw(Context &sctx) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FileInfo::drawTable() const noexcept {
|
void FileInfo::drawTable() const noexcept {
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
ig::IDStackItem const idStackItem{"FileInfo"};
|
ig::IDStackItem const idStackItem{"FileInfo"};
|
||||||
ImGui::Text("%s", m_filePath.c_str());
|
ImGui::Text("%s", m_filePath.c_str());
|
||||||
if (m_fileInfo && ImGui::BeginTable(
|
if (m_fileInfo && ImGui::BeginTable(
|
||||||
"Table", 2,
|
"Table", 2,
|
||||||
ImGuiTableFlags_Borders |
|
ImGuiTableFlags_Borders |
|
||||||
ImGuiTableFlags_RowBg)) {
|
ImGuiTableFlags_RowBg)) {
|
||||||
ImGui::TableSetupColumn("Field", ImGuiTableColumnFlags_WidthFixed, 70);
|
ImGui::TableSetupColumn("Field", ImGuiTableColumnFlags_WidthFixed, 70 * scale);
|
||||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
|
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
|
||||||
// asset id
|
// asset id
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
|||||||
@@ -37,9 +37,10 @@ void MakeCopyPopup::draw(Context &ctx) noexcept {
|
|||||||
m_stage = Stage::Open;
|
m_stage = Stage::Open;
|
||||||
m_open = true;
|
m_open = true;
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case Stage::Open:
|
case Stage::Open: {
|
||||||
|
auto const scale = ig::dpiScale();
|
||||||
ig::centerNextWindow(ctx.tctx);
|
ig::centerNextWindow(ctx.tctx);
|
||||||
ImGui::SetNextWindowSize({250, 0});
|
ImGui::SetNextWindowSize({250 * scale, 0});
|
||||||
constexpr auto modalFlags =
|
constexpr auto modalFlags =
|
||||||
ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoCollapse |
|
||||||
ImGuiWindowFlags_NoMove |
|
ImGuiWindowFlags_NoMove |
|
||||||
@@ -68,6 +69,7 @@ void MakeCopyPopup::draw(Context &ctx) noexcept {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeCopyPopup::accept(Context const &ctx) noexcept {
|
void MakeCopyPopup::accept(Context const &ctx) noexcept {
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ StudioUI::StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexc
|
|||||||
m_sctx{*this, tctx},
|
m_sctx{*this, tctx},
|
||||||
m_projectDataDir{std::move(projectDataDir)} {
|
m_projectDataDir{std::move(projectDataDir)} {
|
||||||
{
|
{
|
||||||
|
auto const scale = turbine::isWayland() ? 1.f : turbine::scale(m_tctx);
|
||||||
ImFontConfig fontCfg;
|
ImFontConfig fontCfg;
|
||||||
fontCfg.FontDataOwnedByAtlas = false;
|
fontCfg.FontDataOwnedByAtlas = false;
|
||||||
auto const &io = ImGui::GetIO();
|
auto const &io = ImGui::GetIO();
|
||||||
@@ -132,7 +133,11 @@ StudioUI::StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexc
|
|||||||
// that it will still be treated as const.
|
// that it will still be treated as const.
|
||||||
// ImGui documentation recognizes that this is a bad design,
|
// ImGui documentation recognizes that this is a bad design,
|
||||||
// and hopefully it will change at some point.
|
// and hopefully it will change at some point.
|
||||||
io.Fonts->AddFontFromMemoryTTF(const_cast<uint8_t*>(font.data()), static_cast<int>(font.size()), 13, &fontCfg);
|
io.Fonts->AddFontFromMemoryTTF(
|
||||||
|
const_cast<uint8_t*>(font.data()),
|
||||||
|
static_cast<int>(font.size()),
|
||||||
|
13 * scale,
|
||||||
|
&fontCfg);
|
||||||
}
|
}
|
||||||
auto &kctx = keelCtx(m_tctx);
|
auto &kctx = keelCtx(m_tctx);
|
||||||
kctx.converters.emplace_back(keel::Converter::make<convertStudioConfigV1ToStudioConfigV2>());
|
kctx.converters.emplace_back(keel::Converter::make<convertStudioConfigV1ToStudioConfigV2>());
|
||||||
@@ -197,6 +202,11 @@ void StudioUI::handleNavigationChange(ox::StringParam path, ox::StringParam navA
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StudioUI::draw() noexcept {
|
void StudioUI::draw() noexcept {
|
||||||
|
if (!turbine::isWayland()) {
|
||||||
|
ig::setDpiScale(ImGui::GetWindowDpiScale());
|
||||||
|
} else {
|
||||||
|
ig::setDpiScale(1.f);
|
||||||
|
}
|
||||||
glutils::clearScreen();
|
glutils::clearScreen();
|
||||||
drawMenu();
|
drawMenu();
|
||||||
auto const &viewport = *ImGui::GetMainViewport();
|
auto const &viewport = *ImGui::GetMainViewport();
|
||||||
@@ -215,7 +225,7 @@ void StudioUI::draw() noexcept {
|
|||||||
ImGuiFocusedFlags_RootAndChildWindows | ImGuiFocusedFlags_NoPopupHierarchy);
|
ImGuiFocusedFlags_RootAndChildWindows | ImGuiFocusedFlags_NoPopupHierarchy);
|
||||||
if (m_showProjectExplorer) {
|
if (m_showProjectExplorer) {
|
||||||
auto const v = ImGui::GetContentRegionAvail();
|
auto const v = ImGui::GetContentRegionAvail();
|
||||||
m_projectExplorer.draw(m_sctx, {300, v.y});
|
m_projectExplorer.draw(m_sctx, {300 * ig::dpiScale(), v.y});
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
drawTabBar();
|
drawTabBar();
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ namespace studio::ig {
|
|||||||
|
|
||||||
inline constexpr auto BtnSz = ImVec2{52, 22};
|
inline constexpr auto BtnSz = ImVec2{52, 22};
|
||||||
|
|
||||||
|
void setDpiScale(float scale) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
float dpiScale() noexcept;
|
||||||
|
|
||||||
constexpr ImTextureID toImTextureID(ox::Unsigned_c auto id) noexcept
|
constexpr ImTextureID toImTextureID(ox::Unsigned_c auto id) noexcept
|
||||||
requires(sizeof(id) <= sizeof(ox::Uint<sizeof(ImTextureID)*8>)) {
|
requires(sizeof(id) <= sizeof(ox::Uint<sizeof(ImTextureID)*8>)) {
|
||||||
@@ -133,7 +137,7 @@ auto dragDropTarget(auto const &cb) noexcept {
|
|||||||
|
|
||||||
class ChildStackItem {
|
class ChildStackItem {
|
||||||
public:
|
public:
|
||||||
explicit ChildStackItem(ox::CStringViewCR id, ImVec2 const &sz = {}) noexcept;
|
explicit ChildStackItem(ox::CStringViewCR id, ImVec2 sz = {}) noexcept;
|
||||||
~ChildStackItem() noexcept;
|
~ChildStackItem() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,6 +159,11 @@ class IndentStackItem {
|
|||||||
|
|
||||||
void centerNextWindow(turbine::Context &ctx) noexcept;
|
void centerNextWindow(turbine::Context &ctx) noexcept;
|
||||||
|
|
||||||
|
inline void Dummy(ImVec2 const &sz) noexcept {
|
||||||
|
auto const scale = dpiScale();
|
||||||
|
ImGui::Dummy({sz.x * scale, sz.y * scale});
|
||||||
|
}
|
||||||
|
|
||||||
bool PushButton(ox::CStringViewCR lbl, ImVec2 const &btnSz = BtnSz) noexcept;
|
bool PushButton(ox::CStringViewCR lbl, ImVec2 const &btnSz = BtnSz) noexcept;
|
||||||
|
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
@@ -173,10 +182,10 @@ TextInput<ox::IString<MaxChars>> InputText(
|
|||||||
ox::StringViewCR currentText,
|
ox::StringViewCR currentText,
|
||||||
ImGuiInputTextFlags const flags = 0,
|
ImGuiInputTextFlags const flags = 0,
|
||||||
ImGuiInputTextCallback const callback = nullptr,
|
ImGuiInputTextCallback const callback = nullptr,
|
||||||
void *user_data = nullptr) noexcept {
|
void *const userData = nullptr) noexcept {
|
||||||
TextInput<ox::IString<MaxChars>> out = {.text = currentText};
|
TextInput<ox::IString<MaxChars>> out = {.text = currentText};
|
||||||
out.changed = ImGui::InputText(
|
out.changed = ImGui::InputText(
|
||||||
label.c_str(), out.text.data(), MaxChars + 1, flags, callback, user_data);
|
label.c_str(), out.text.data(), MaxChars + 1, flags, callback, userData);
|
||||||
if (out.changed) {
|
if (out.changed) {
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||||
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
|
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
|
||||||
@@ -192,10 +201,10 @@ TextInput<ox::IString<MaxChars>> InputTextWithHint(
|
|||||||
ox::StringViewCR currentText,
|
ox::StringViewCR currentText,
|
||||||
ImGuiInputTextFlags const flags = 0,
|
ImGuiInputTextFlags const flags = 0,
|
||||||
ImGuiInputTextCallback const callback = nullptr,
|
ImGuiInputTextCallback const callback = nullptr,
|
||||||
void *user_data = nullptr) noexcept {
|
void *userData = nullptr) noexcept {
|
||||||
TextInput<ox::IString<MaxChars>> out = {.text = currentText};
|
TextInput<ox::IString<MaxChars>> out = {.text = currentText};
|
||||||
out.changed = ImGui::InputTextWithHint(
|
out.changed = ImGui::InputTextWithHint(
|
||||||
label.c_str(), hint.c_str(), out.text.data(), MaxChars + 1, flags, callback, user_data);
|
label.c_str(), hint.c_str(), out.text.data(), MaxChars + 1, flags, callback, userData);
|
||||||
if (out.changed) {
|
if (out.changed) {
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||||
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
|
std::ignore = out.text.unsafeResize(ox::strlen(out.text.c_str()));
|
||||||
@@ -210,9 +219,9 @@ bool InputText(
|
|||||||
ox::IString<StrCap> &text,
|
ox::IString<StrCap> &text,
|
||||||
ImGuiInputTextFlags const flags = 0,
|
ImGuiInputTextFlags const flags = 0,
|
||||||
ImGuiInputTextCallback const callback = nullptr,
|
ImGuiInputTextCallback const callback = nullptr,
|
||||||
void *user_data = nullptr) noexcept {
|
void *userData = nullptr) noexcept {
|
||||||
auto const out = ImGui::InputText(
|
auto const out = ImGui::InputText(
|
||||||
label.c_str(), text.data(), StrCap + 1, flags, callback, user_data);
|
label.c_str(), text.data(), StrCap + 1, flags, callback, userData);
|
||||||
if (out) {
|
if (out) {
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||||
std::ignore = text.unsafeResize(ox::strlen(text.c_str()));
|
std::ignore = text.unsafeResize(ox::strlen(text.c_str()));
|
||||||
@@ -243,7 +252,7 @@ PopupResponse PopupControlsOk(
|
|||||||
ox::CStringViewCR ok);
|
ox::CStringViewCR ok);
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const &sz = {285, 0});
|
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 sz = {285, 0});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -290,7 +299,7 @@ bool ListBox(
|
|||||||
std::function<ox::CStringView(size_t)> const &f,
|
std::function<ox::CStringView(size_t)> const &f,
|
||||||
size_t strCnt,
|
size_t strCnt,
|
||||||
size_t &selIdx,
|
size_t &selIdx,
|
||||||
ImVec2 const &sz = {0, 0}) noexcept;
|
ImVec2 sz = {0, 0}) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <turbine/turbine.hpp>
|
||||||
|
|
||||||
#include <studio/imguiutil.hpp>
|
#include <studio/imguiutil.hpp>
|
||||||
|
|
||||||
#include <studio/filepickerpopup.hpp>
|
#include <studio/filepickerpopup.hpp>
|
||||||
@@ -83,9 +85,10 @@ ox::Optional<ox::String> FilePickerPopup::draw(Context &ctx) noexcept {
|
|||||||
if (!m_open) {
|
if (!m_open) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
auto const scale = turbine::scale(ctx.tctx);
|
||||||
if (ig::BeginPopup(ctx.tctx, m_name, m_open, {380, 340})) {
|
if (ig::BeginPopup(ctx.tctx, m_name, m_open, {380, 340})) {
|
||||||
auto const vp = ImGui::GetContentRegionAvail();
|
auto const vp = ImGui::GetContentRegionAvail();
|
||||||
m_explorer.draw(ctx, {vp.x, vp.y - 30});
|
m_explorer.draw(ctx, {vp.x, vp.y - 30 * scale});
|
||||||
if (ig::PopupControlsOkCancel(m_open) == ig::PopupResponse::OK || m_explorer.opened) {
|
if (ig::PopupControlsOkCancel(m_open) == ig::PopupResponse::OK || m_explorer.opened) {
|
||||||
out = handlePick();
|
out = handlePick();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,25 @@
|
|||||||
|
|
||||||
namespace studio::ig {
|
namespace studio::ig {
|
||||||
|
|
||||||
ChildStackItem::ChildStackItem(ox::CStringViewCR id, ImVec2 const &sz) noexcept {
|
static constexpr void scaleSz(ImVec2 &sz) noexcept {
|
||||||
|
auto const scale = dpiScale();
|
||||||
|
sz.x *= scale;
|
||||||
|
sz.y *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local float g_dpiScale = 1.f;
|
||||||
|
|
||||||
|
void setDpiScale(float scale) noexcept {
|
||||||
|
g_dpiScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
float dpiScale() noexcept {
|
||||||
|
return g_dpiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChildStackItem::ChildStackItem(ox::CStringViewCR id, ImVec2 sz) noexcept {
|
||||||
|
scaleSz(sz);
|
||||||
ImGui::BeginChild(id.c_str(), sz);
|
ImGui::BeginChild(id.c_str(), sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +51,7 @@ IDStackItem::~IDStackItem() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IndentStackItem::IndentStackItem(float indent) noexcept: m_indent(indent) {
|
IndentStackItem::IndentStackItem(float id) noexcept: m_indent(id) {
|
||||||
ImGui::Indent(m_indent);
|
ImGui::Indent(m_indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,16 +60,18 @@ IndentStackItem::~IndentStackItem() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void centerNextWindow(turbine::Context &ctx) noexcept {
|
void centerNextWindow(turbine::Context&) noexcept {
|
||||||
auto const sz = turbine::getScreenSize(ctx);
|
auto const &io = ImGui::GetIO();
|
||||||
auto const screenW = static_cast<float>(sz.width);
|
auto const sz = io.DisplaySize;
|
||||||
auto const screenH = static_cast<float>(sz.height);
|
ImGui::SetNextWindowPos(
|
||||||
auto const mod = ImGui::GetWindowDpiScale() * 2;
|
{sz.x * 0.5f, sz.y * 0.5f},
|
||||||
ImGui::SetNextWindowPos(ImVec2(screenW / mod, screenH / mod), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
ImGuiCond_Always,
|
||||||
|
{0.5f, 0.5f});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PushButton(ox::CStringViewCR lbl, ImVec2 const &btnSz) noexcept {
|
bool PushButton(ox::CStringViewCR lbl, ImVec2 const &btnSz) noexcept {
|
||||||
return ImGui::Button(lbl.c_str(), btnSz);
|
auto const scale = dpiScale();
|
||||||
|
return ImGui::Button(lbl.c_str(), {btnSz.x * scale, btnSz.y * scale});
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupResponse PopupControlsOkCancel(
|
PopupResponse PopupControlsOkCancel(
|
||||||
@@ -60,9 +80,10 @@ PopupResponse PopupControlsOkCancel(
|
|||||||
ox::CStringViewCR ok,
|
ox::CStringViewCR ok,
|
||||||
ox::CStringViewCR cancel) {
|
ox::CStringViewCR cancel) {
|
||||||
auto out = PopupResponse::None;
|
auto out = PopupResponse::None;
|
||||||
constexpr auto btnSz = ImVec2{50, BtnSz.y};
|
auto const scale = dpiScale();
|
||||||
|
auto const btnSz = ImVec2{50 * scale, BtnSz.y * scale};
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::SetCursorPosX(popupWidth - 118);
|
ImGui::SetCursorPosX(popupWidth - 118 * scale);
|
||||||
if (ImGui::Button(ok.c_str(), btnSz)) {
|
if (ImGui::Button(ok.c_str(), btnSz)) {
|
||||||
popupOpen = false;
|
popupOpen = false;
|
||||||
out = PopupResponse::OK;
|
out = PopupResponse::OK;
|
||||||
@@ -79,16 +100,18 @@ PopupResponse PopupControlsOkCancel(
|
|||||||
bool &popupOpen,
|
bool &popupOpen,
|
||||||
ox::CStringViewCR ok,
|
ox::CStringViewCR ok,
|
||||||
ox::CStringViewCR cancel) {
|
ox::CStringViewCR cancel) {
|
||||||
return PopupControlsOkCancel(ImGui::GetContentRegionAvail().x + 17, popupOpen, ok, cancel);
|
auto const scale = dpiScale();
|
||||||
|
return PopupControlsOkCancel(ImGui::GetContentRegionAvail().x + 17 * scale, popupOpen, ok, cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupResponse PopupControlsOk(
|
PopupResponse PopupControlsOk(
|
||||||
bool &popupOpen,
|
bool &popupOpen,
|
||||||
ox::CStringViewCR ok) {
|
ox::CStringViewCR ok) {
|
||||||
|
auto const scale = dpiScale();
|
||||||
auto out = PopupResponse::None;
|
auto out = PopupResponse::None;
|
||||||
constexpr auto btnSz = ImVec2{50, BtnSz.y};
|
auto const btnSz = ImVec2{50 * scale, BtnSz.y * scale};
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 42);
|
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 42 * scale);
|
||||||
if (ImGui::Button(ok.c_str(), btnSz)) {
|
if (ImGui::Button(ok.c_str(), btnSz)) {
|
||||||
popupOpen = false;
|
popupOpen = false;
|
||||||
out = PopupResponse::OK;
|
out = PopupResponse::OK;
|
||||||
@@ -101,7 +124,8 @@ PopupResponse PopupControlsOk(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const &sz) {
|
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 sz) {
|
||||||
|
scaleSz(sz);
|
||||||
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||||
centerNextWindow(ctx);
|
centerNextWindow(ctx);
|
||||||
ImGui::OpenPopup(popupName.c_str());
|
ImGui::OpenPopup(popupName.c_str());
|
||||||
@@ -110,14 +134,14 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ComboBox(
|
bool ComboBox(
|
||||||
ox::CStringView const &lbl,
|
ox::CStringViewCR lbl,
|
||||||
ox::SpanView<ox::CStringView> const list,
|
ox::SpanView<ox::CStringView> const list,
|
||||||
size_t &selectedIdx) noexcept {
|
size_t &selectedIdx) noexcept {
|
||||||
bool out{};
|
bool out{};
|
||||||
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
|
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
|
||||||
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
||||||
for (auto i = 0u; i < list.size(); ++i) {
|
for (auto i = 0u; i < list.size(); ++i) {
|
||||||
auto const selected = (selectedIdx == i);
|
auto const selected = selectedIdx == i;
|
||||||
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
|
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
|
||||||
selectedIdx = i;
|
selectedIdx = i;
|
||||||
out = true;
|
out = true;
|
||||||
@@ -129,14 +153,14 @@ bool ComboBox(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ComboBox(
|
bool ComboBox(
|
||||||
ox::CStringView const &lbl,
|
ox::CStringViewCR lbl,
|
||||||
ox::Span<ox::String const> const list,
|
ox::Span<ox::String const> const list,
|
||||||
size_t &selectedIdx) noexcept {
|
size_t &selectedIdx) noexcept {
|
||||||
bool out{};
|
bool out{};
|
||||||
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
|
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
|
||||||
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
|
||||||
for (auto i = 0u; i < list.size(); ++i) {
|
for (auto i = 0u; i < list.size(); ++i) {
|
||||||
auto const selected = (selectedIdx == i);
|
auto const selected = selectedIdx == i;
|
||||||
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
|
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
|
||||||
selectedIdx = i;
|
selectedIdx = i;
|
||||||
out = true;
|
out = true;
|
||||||
@@ -181,12 +205,14 @@ bool ListBox(
|
|||||||
std::function<ox::CStringView(size_t)> const &f,
|
std::function<ox::CStringView(size_t)> const &f,
|
||||||
size_t const strCnt,
|
size_t const strCnt,
|
||||||
size_t &selIdx,
|
size_t &selIdx,
|
||||||
ImVec2 const &sz) noexcept {
|
ImVec2 sz) noexcept {
|
||||||
|
auto const scale = dpiScale();
|
||||||
|
sz = {sz.x * scale, sz.y * scale};
|
||||||
auto out = false;
|
auto out = false;
|
||||||
if (ImGui::BeginListBox(name.c_str(), sz)) {
|
if (ImGui::BeginListBox(name.c_str(), sz)) {
|
||||||
for (size_t i = 0; i < strCnt; ++i) {
|
for (size_t i = 0; i < strCnt; ++i) {
|
||||||
auto str = f(i);
|
auto const str = f(i);
|
||||||
ig::IDStackItem const idStackItem2(static_cast<int>(i));
|
IDStackItem const idStackItem2(static_cast<int>(i));
|
||||||
if (ImGui::Selectable(str.c_str(), selIdx == i)) {
|
if (ImGui::Selectable(str.c_str(), selIdx == i)) {
|
||||||
if (i != selIdx) {
|
if (i != selIdx) {
|
||||||
selIdx = i;
|
selIdx = i;
|
||||||
@@ -200,13 +226,13 @@ bool ListBox(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::String> const &list, size_t &selIdx) noexcept {
|
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::String> const &list, size_t &selIdx) noexcept {
|
||||||
return ListBox(name, [list](size_t i) -> ox::CStringView {
|
return ListBox(name, [list](size_t const i) -> ox::CStringView {
|
||||||
return list[i];
|
return list[i];
|
||||||
}, list.size(), selIdx);
|
}, list.size(), selIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::CStringView> const &list, size_t &selIdx) noexcept {
|
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::CStringView> const &list, size_t &selIdx) noexcept {
|
||||||
return ListBox(name, [list](size_t i) -> ox::CStringView {
|
return ListBox(name, [list](size_t const i) -> ox::CStringView {
|
||||||
return list[i];
|
return list[i];
|
||||||
}, list.size(), selIdx);
|
}, list.size(), selIdx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace studio {
|
|||||||
|
|
||||||
void Popup::drawWindow(turbine::Context &ctx, bool &open, std::function<void()> const &drawContents) {
|
void Popup::drawWindow(turbine::Context &ctx, bool &open, std::function<void()> const &drawContents) {
|
||||||
ig::centerNextWindow(ctx);
|
ig::centerNextWindow(ctx);
|
||||||
ImGui::SetNextWindowSize(static_cast<ImVec2>(m_size));
|
ImGui::SetNextWindowSize(static_cast<ImVec2>(m_size * ig::dpiScale()));
|
||||||
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
|
||||||
if (ImGui::BeginPopupModal(m_title.c_str(), &open, modalFlags)) {
|
if (ImGui::BeginPopupModal(m_title.c_str(), &open, modalFlags)) {
|
||||||
drawContents();
|
drawContents();
|
||||||
|
|||||||
@@ -112,4 +112,10 @@ void setShutdownHandler(Context &ctx, ShutdownHandler handler) noexcept;
|
|||||||
// sleep time is a minimum of ~16 milliseconds.
|
// sleep time is a minimum of ~16 milliseconds.
|
||||||
void setUpdateHandler(Context &ctx, UpdateHandler) noexcept;
|
void setUpdateHandler(Context &ctx, UpdateHandler) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
float scale(Context const &ctx) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool isWayland() noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class Context {
|
|||||||
uint64_t draws = 0;
|
uint64_t draws = 0;
|
||||||
bool running{};
|
bool running{};
|
||||||
ShutdownHandler shutdownHandler{};
|
ShutdownHandler shutdownHandler{};
|
||||||
|
float scale{};
|
||||||
|
|
||||||
Context() noexcept = default;
|
Context() noexcept = default;
|
||||||
|
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ ox::Result<ox::UPtr<Context>> init(
|
|||||||
setMandatoryRefreshPeriod(*ctx, ticksMs(*ctx) + config::MandatoryRefreshPeriod);
|
setMandatoryRefreshPeriod(*ctx, ticksMs(*ctx) + config::MandatoryRefreshPeriod);
|
||||||
// init GLFW context
|
// init GLFW context
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
|
||||||
glfwSetErrorCallback(handleGlfwError);
|
glfwSetErrorCallback(handleGlfwError);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
@@ -373,6 +374,12 @@ ox::Result<ox::UPtr<Context>> init(
|
|||||||
ImGui_ImplOpenGL3_Init();
|
ImGui_ImplOpenGL3_Init();
|
||||||
io.IniFilename = nullptr;
|
io.IniFilename = nullptr;
|
||||||
themeImgui();
|
themeImgui();
|
||||||
|
float xscale{}, yscale{};
|
||||||
|
glfwGetWindowContentScale(ctx->window, &xscale, &yscale);
|
||||||
|
ctx->scale = isWayland() ? 1.f : ox::max(xscale, yscale);
|
||||||
|
io.DisplayFramebufferScale = ImVec2{ctx->scale, ctx->scale};
|
||||||
|
auto &style = ImGui::GetStyle();
|
||||||
|
style.ScaleAllSizes(ctx->scale);
|
||||||
#endif
|
#endif
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
@@ -471,4 +478,12 @@ KeyEventHandler keyEventHandler(Context const &ctx) noexcept {
|
|||||||
return ctx.keyEventHandler;
|
return ctx.keyEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float scale(Context const &ctx) noexcept {
|
||||||
|
return ctx.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isWayland() noexcept {
|
||||||
|
return glfwGetPlatform() == GLFW_PLATFORM_WAYLAND;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user