code:
#include "Core/EventCommands/Dialog_ChangeEnemyHP.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>
std::tuple<bool, bool> Dialog_ChangeEnemyHP::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeEnemyHP");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 10) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});

  if (ImGui::BeginPopupModal(std::format("{}###ChangeEnemyHP", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_enemy_hp_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox enemyGroupBox(trNOOP("Enemy"), "##change_enemy_hp_enemy_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (enemyGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);

        auto preview = Database::instance()->troopMemberName(m_troopId, m_troopMemberSelection);
        if (m_troopMemberSelection >= 0) {
          preview = std::format("#{} {}", m_troopMemberSelection + 1, preview);
        }

        if (ImGui::BeginCombo("##enemy_recover_all_change_list", preview.c_str())) {
          for (int i = -1; i < 8; ++i) {
            auto name = Database::instance()->troopMemberName(m_troopId, i);
            if (i >= 0) {
              name = std::format("#{} {}", i + 1, name);
            }

            if (ImGui::Selectable(name.c_str(), i == m_troopMemberSelection)) {
              m_troopMemberSelection = i;
            }
          }
          ImGui::EndCombo();
        }
      }
      enemyGroupBox.end();

      GroupBox operationGroupBox(trNOOP("Operation"), "##change_enemy_hp_operation_group", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_hp_operation_group_layout", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Increase"), &m_troopMemberOp, 0);
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Decrease"), &m_troopMemberOp, 1);
          ImGui::Spring(0.33);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_enemy_hp_operand_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_hp_operand_group_layout", {-1, -1});
        {
          ImGui::BeginVertical("##change_enemy_hp_operand_group_source_layout", {-1, -1});
          {
            ImGui::RadioButton("Constant", &m_quantitySource, 0);
            ImGui::RadioButton("Variable", &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::BeginVertical("##change_enemy_hp_operand_group_value_layout", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_enemy_hp_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              m_quantity = std::clamp(m_quantity, 1, 9999);
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_enemy_hp_quant_var");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5f));
      ImGui::BeginHorizontal("##change_enemy_hp_buttons_layout", {-1, -1});
      {
        ImGui::BeginDisabled(m_troopMemberOp == 0);
        ImGui::Checkbox("Allow Knockout", &m_allowKnockout);
        ImGui::EndDisabled();
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_enemy_hp_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;

          m_command->troopMember = m_troopMemberSelection;
          m_command->troopMemberOp = static_cast<QuantityChangeOp>(m_troopMemberOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);
          m_command->allowKnockOut = m_allowKnockout;

          if (m_command->quantitySource == QuantityChangeSource::Variable)
            m_command->quantity = m_quantityVar;
          else
            m_command->quantity = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeEnemyHP::drawPickers() {
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        m_quantityVar = m_variablePicker->selection();
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeEnemyHP.hpp"
#include "Database/Troops.hpp"

struct Dialog_ChangeEnemyHP : IEventDialogController {
  Dialog_ChangeEnemyHP() = delete;
  explicit Dialog_ChangeEnemyHP(const std::string& name, const std::shared_ptr<ChangeEnemyHPCommand>& cmd = nullptr, const int troopId = 0)
  : IEventDialogController(name)
  , m_troopId(troopId)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeEnemyHPCommand());
    }

    m_troopMemberSelection = static_cast<int>(m_command->troopMember);
    m_troopMemberOp = static_cast<int>(m_command->troopMemberOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);
    m_allowKnockout = m_command->allowKnockOut;

    if (m_command->quantitySource == QuantityChangeSource::Variable)
      m_quantityVar = m_command->quantity;
    else
      m_quantity = m_command->quantity;
  }
  void drawPickers();
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  int m_troopId{0};
  int m_troopMemberSelection{0};
  int m_troopMemberOp{0};
  int m_quantitySource{0};
  int m_quantity{1};
  int m_quantityVar{1};
  bool m_allowKnockout{false};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Troop>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeEnemyHPCommand> m_command;
};

repo_name: Antidote/openrpgeditor

license: mit


code:
#include "Core/EventCommands/Dialog_ChangeEnemyMP.hpp"

#include "Database/Database.hpp"
#include "imgui.h"
#include <tuple>

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>
std::tuple<bool, bool> Dialog_ChangeEnemyMP::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeEnemyMP");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 10) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});

  if (ImGui::BeginPopupModal(std::format("{}###ChangeEnemyMP", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_enemy_mp_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox enemyGroupBox(trNOOP("Enemy"), "##change_enemy_mp_enemy_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (enemyGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);

        auto preview = Database::instance()->troopMemberName(m_troopId, m_troopMemberSelection);
        if (m_troopMemberSelection >= 0) {
          preview = std::format("#{} {}", m_troopMemberSelection + 1, preview);
        }

        if (ImGui::BeginCombo("##enemy_recover_all_change_list", preview.c_str())) {
          for (int i = -1; i < 8; ++i) {
            auto name = Database::instance()->troopMemberName(m_troopId, i);
            if (i >= 0) {
              name = std::format("#{} {}", i + 1, name);
            }

            if (ImGui::Selectable(name.c_str(), i == m_troopMemberSelection)) {
              m_troopMemberSelection = i;
            }
          }
          ImGui::EndCombo();
        }
      }
      enemyGroupBox.end();

      GroupBox operationGroupBox(trNOOP("Operation"), "##change_enemy_mp_operation_group", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_mp_operation_group_layout", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Increase"), &m_troopMemberOp, 0);
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Decrease"), &m_troopMemberOp, 1);
          ImGui::Spring(0.33);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_enemy_mp_operand_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_mp_operand_group_layout", {-1, -1});
        {
          ImGui::BeginVertical("##change_enemy_mp_operand_group_source_layout", {-1, -1});
          {
            ImGui::RadioButton("Constant", &m_quantitySource, 0);
            ImGui::RadioButton("Variable", &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::BeginVertical("##change_enemy_mp_operand_group_value_layout", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_enemy_mp_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              m_quantity = std::clamp(m_quantity, 1, 9999);
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_enemy_mp_quant_var");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5f));
      ImGui::BeginHorizontal("##change_enemy_mp_buttons_layout", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_enemy_mp_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;

          m_command->troopMember = m_troopMemberSelection;
          m_command->troopMemberOp = static_cast<QuantityChangeOp>(m_troopMemberOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);

          if (m_command->quantitySource == QuantityChangeSource::Variable)
            m_command->quantity = m_quantityVar;
          else
            m_command->quantity = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeEnemyMP::drawPickers() {
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        m_quantityVar = m_variablePicker->selection();
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeEnemyMP.hpp"
#include "Database/Troops.hpp"

struct Dialog_ChangeEnemyMP : IEventDialogController {
  Dialog_ChangeEnemyMP() = delete;
  explicit Dialog_ChangeEnemyMP(const std::string& name, const std::shared_ptr<ChangeEnemyMPCommand>& cmd = nullptr, const int troopId = 0)
  : IEventDialogController(name)
  , m_troopId(troopId)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeEnemyMPCommand());
    }

    m_troopMemberSelection = m_command->troopMember;
    m_troopMemberOp = static_cast<int>(m_command->troopMemberOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);

    if (m_command->quantitySource == QuantityChangeSource::Variable)
      m_quantityVar = m_command->quantity;
    else
      m_quantity = m_command->quantity;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_troopId{0};
  int m_troopMemberSelection;
  int m_troopMemberOp;
  int m_quantitySource;
  int m_quantity{1};
  int m_quantityVar{1};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Troop>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeEnemyMPCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeEnemyState.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>
#include <tuple>

std::tuple<bool, bool> Dialog_ChangeEnemyState::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeEnemyState");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 9) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});

  if (ImGui::BeginPopupModal(std::format("{}###ChangeEnemyState", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_enemy_state_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox enemyGroupBox(trNOOP("Enemy"), "##change_enemy_tp_enemy_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (enemyGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);

        auto preview = Database::instance()->troopMemberName(m_troopId, m_troopMemberSelection);
        if (m_troopMemberSelection >= 0) {
          preview = std::format("#{} {}", m_troopMemberSelection + 1, preview);
        }

        if (ImGui::BeginCombo("##enemy_recover_all_change_list", preview.c_str())) {
          for (int i = -1; i < 8; ++i) {
            auto name = Database::instance()->troopMemberName(m_troopId, i);
            if (i >= 0) {
              name = std::format("#{} {}", i + 1, name);
            }

            if (ImGui::Selectable(name.c_str(), i == m_troopMemberSelection)) {
              m_troopMemberSelection = i;
            }
          }
          ImGui::EndCombo();
        }
      }
      enemyGroupBox.end();

      GroupBox operationGroupBox(trNOOP("Operation"), "##change_enemy_state_operation_group", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_state_operation_group_layout", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Add"), &m_troopMemberOp, 0);
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Remove"), &m_troopMemberOp, 1);
          ImGui::Spring(0.33);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();

      GroupBox stateGroupBox(trNOOP("State"), "##change_enemy_state_state_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (stateGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);
        std::string text = Database::instance()->stateNameAndId(m_state);
        ImGui::PushID("##change_enemy_state_state_value");
        if (ImGui::EllipsesButton(text.c_str(), ImVec2{-1, 0})) {
          m_statePicker = ObjectPicker(trNOOP("State"), Database::instance()->states.states(), m_state);
          m_statePicker->setOpen(true);
        }
        ImGui::PopID();
      }
      stateGroupBox.end();

      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5f));
      ImGui::BeginHorizontal("##change_enemy_tp_buttons_layout", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_enemy_tp_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;

          m_command->troopMember = m_troopMemberSelection;
          m_command->troopMemberOp = static_cast<PartyMemberOperation>(m_troopMemberOp);
          m_command->state = m_state;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeEnemyState::drawPickers() {
  if (m_statePicker) {
    if (const auto [closed, confirmed] = m_statePicker->draw(); closed) {
      if (confirmed) {
        m_state = m_statePicker->selection();
      }
      m_statePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeEnemyState.hpp"
#include "Database/States.hpp"

struct Dialog_ChangeEnemyState : IEventDialogController {
  Dialog_ChangeEnemyState() = delete;
  explicit Dialog_ChangeEnemyState(const std::string& name, const std::shared_ptr<ChangeEnemyStateCommand>& cmd = nullptr, const int troopId = 0)
  : IEventDialogController(name)
  , m_troopId(troopId)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeEnemyStateCommand());
    }
    m_troopMemberSelection = m_command->troopMember;
    m_troopMemberOp = static_cast<int>(m_command->troopMemberOp);
    m_state = m_command->state;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_troopId;
  int m_troopMemberSelection;
  int m_troopMemberOp; // Party Member Operation
  int m_state;

  bool m_confirmed{false};
  std::optional<ObjectPicker<State>> m_statePicker;
  std::shared_ptr<ChangeEnemyStateCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeEnemyTP.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>
#include <tuple>

std::tuple<bool, bool> Dialog_ChangeEnemyTP::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeEnemyTP");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 10) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});

  if (ImGui::BeginPopupModal(std::format("{}###ChangeEnemyTP", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_enemy_tp_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox enemyGroupBox(trNOOP("Enemy"), "##change_enemy_tp_enemy_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (enemyGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);

        auto preview = Database::instance()->troopMemberName(m_troopId, m_troopMemberSelection);
        if (m_troopMemberSelection >= 0) {
          preview = std::format("#{} {}", m_troopMemberSelection + 1, preview);
        }

        if (ImGui::BeginCombo("##enemy_recover_all_change_list", preview.c_str())) {
          for (int i = -1; i < 8; ++i) {
            auto name = Database::instance()->troopMemberName(m_troopId, i);
            if (i >= 0) {
              name = std::format("#{} {}", i + 1, name);
            }

            if (ImGui::Selectable(name.c_str(), i == m_troopMemberSelection)) {
              m_troopMemberSelection = i;
            }
          }
          ImGui::EndCombo();
        }
      }
      enemyGroupBox.end();

      GroupBox operationGroupBox(trNOOP("Operation"), "##change_enemy_tp_operation_group", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_tp_operation_group_layout", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Increase"), &m_troopMemberOp, 0);
          ImGui::Spring(0.33);
          ImGui::RadioButton(trNOOP("Decrease"), &m_troopMemberOp, 1);
          ImGui::Spring(0.33);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_enemy_tp_operand_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_enemy_tp_operand_group_layout", {-1, -1});
        {
          ImGui::BeginVertical("##change_enemy_tp_operand_group_source_layout", {-1, -1});
          {
            ImGui::RadioButton("Constant", &m_quantitySource, 0);
            ImGui::RadioButton("Variable", &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::BeginVertical("##change_enemy_tp_operand_group_value_layout", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_enemy_tp_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              m_quantity = std::clamp(m_quantity, 1, 9999);
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_enemy_tp_quant_var");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5f));
      ImGui::BeginHorizontal("##change_enemy_tp_buttons_layout", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_enemy_tp_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;

          m_command->troopMember = m_troopMemberSelection;
          m_command->troopMemberOp = static_cast<QuantityChangeOp>(m_troopMemberOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);

          if (m_command->quantitySource == QuantityChangeSource::Variable)
            m_command->quantity = m_quantityVar;
          else
            m_command->quantity = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeEnemyTP::drawPickers() {
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        m_quantityVar = m_variablePicker->selection();
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeEnemyTP.hpp"
#include "Database/Troops.hpp"

struct Dialog_ChangeEnemyTP : IEventDialogController {
  Dialog_ChangeEnemyTP() = delete;
  explicit Dialog_ChangeEnemyTP(const std::string& name, const std::shared_ptr<ChangeEnemyTPCommand>& cmd = nullptr, const int troopId = 0)
  : IEventDialogController(name)
  , m_troopId(troopId)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeEnemyTPCommand());
    }

    m_troopMemberSelection = m_command->troopMember;
    m_troopMemberOp = static_cast<int>(m_command->troopMemberOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);

    if (m_command->quantitySource == QuantityChangeSource::Variable)
      m_quantityVar = m_command->quantity;
    else
      m_quantity = m_command->quantity;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_troopId;
  int m_troopMemberSelection;
  int m_troopMemberOp;
  int m_quantitySource;
  int m_quantity{1};
  int m_quantityVar{1};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Troop>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeEnemyTPCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeEquipment.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeEquipment::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeEquipment");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 9) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeEquipment", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {

    drawPickers();
    ImGui::BeginVertical("##change_equipment_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_equipment_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        ImGui::PushID("##change_equip_actor_selection");
        if (ImGui::EllipsesButton(Database::instance()->actorNameAndId(m_actor).c_str(), ImVec2{-1, 0})) {
          m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_actor);
          m_actorPicker->setOpen(true);
        }
        ImGui::PopID();
      }
      actorGroupBox.end();
      GroupBox equipTypeGroupBox(trNOOP("Equipment Type"), "##change_equipment_equip_type_group", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (equipTypeGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);
        if (ImGui::BeginCombo("##equip_type_list", m_equipmentTypes[m_equipmentType].c_str())) {
          for (int i = 0; const auto& name : m_equipmentTypes) {
            if (ImGui::Selectable(name.c_str(), i == m_equipmentType)) {
              m_equipmentType = i;
              makeEquipableItemList();
            }
            ++i;
          }
          ImGui::EndCombo();
        }
      }
      equipTypeGroupBox.end();
      GroupBox equipGroupBox(trNOOP("Equipment Item"), "##change_equipment_equip_item_group", {-1, 0}, nullptr,
                             ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (equipGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);
        const int etypeId = Database::instance()->slotIdToEquipId(m_actor, m_equipmentType);
        if (ImGui::BeginCombo("##equip_item_list", Database::instance()->itemDisplayName(etypeId <= 1, m_equipmentItem).c_str())) {
          for (const auto item : m_equipableItems) {
            if (ImGui::Selectable(Database::instance()->itemDisplayName(etypeId <= 1, item).c_str(), item == m_equipmentItem)) {
              m_equipmentItem = item;
            }
          }
          ImGui::EndCombo();
        }
      }
      equipGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_level_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_level_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->actorId = m_actor;
          m_command->equipType = m_equipmentType;
          m_command->equipment = m_equipmentItem;
          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeEquipment::makeEquipableItemList() {
  m_equipableItems.clear();
  m_equipableItems.emplace_back(0);

  const int etypeId = Database::instance()->slotIdToEquipId(m_actor, m_equipmentType);
  if (Database::instance()->isEquipTypeSealed(m_actor, etypeId)) {
    return;
  }
  if (etypeId <= 1) {
    for (int i = 1; i < Database::instance()->weapons.weapons().size(); i++) {
      if (Database::instance()->isEquipWeaponTypeOk(m_actor, Database::instance()->weapons.weapon(i)->wtypeId())) {
        m_equipableItems.emplace_back(i);
      }
    }
    return;
  }
  for (int i = 1; i < Database::instance()->armors.armors().size(); i++) {
    if (const auto& armor = Database::instance()->armors.armor(i); armor->etypeId() == etypeId && Database::instance()->isEquipArmorTypeOk(m_actor, armor->atypeId())) {
      m_equipableItems.emplace_back(i);
    }
  }
}

void Dialog_ChangeEquipment::makeEquipTypeList() {
  m_equipmentTypes.clear();
  if (!Database::instance()->actors.actor(m_actor)) {
    m_equipableItems.clear();
    m_equipableItems.emplace_back(0);
    return;
  }

  for (int i = 0; i < Database::instance()->system.equipTypes().size() - 1; ++i) {
    const std::string name = Database::instance()->instance()->equipTypeName(Database::instance()->slotIdToEquipId(m_actor, i));
    m_equipmentTypes.emplace_back(name);
  }
  makeEquipableItemList();
}

void Dialog_ChangeEquipment::drawPickers() {
  if (!m_actorPicker) {
    return;
  }
  if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
    if (confirmed) {
      m_actor = m_actorPicker->selection();
      makeEquipTypeList();
    }
    m_actorPicker.reset();
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/Actor.hpp"
#include "Database/Enemy.hpp"
#include "Database/EventCommands/ChangeEquipment.hpp"

struct Dialog_ChangeEquipment : IEventDialogController {
  Dialog_ChangeEquipment() = delete;
  explicit Dialog_ChangeEquipment(const std::string& name, const std::shared_ptr<ChangeEquipmentCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeEquipmentCommand());
    }
    m_actor = m_command->actorId;
    m_equipmentType = m_command->equipType;
    m_equipmentItem = m_command->equipment;
    makeEquipTypeList();
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  void makeEquipableItemList();
  void makeEquipTypeList();
  int m_equipmentType;
  int m_equipmentItem;
  int m_actor;

  bool m_confirmed{false};
  std::shared_ptr<ChangeEquipmentCommand> m_command;
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::vector<int> m_equipableItems;
  std::vector<std::string> m_equipmentTypes;
};


code:
#include "Core/EventCommands/Dialog_ChangeFormationAccess.hpp"
#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"
#include "imgui.h"
#include "imgui_internal.h"

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeFormationAccess::draw() {
  if (isOpen()) {
    ImGui::OpenPopup(m_name.c_str());
  }

  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 5) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(m_name.c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {

    ImGui::BeginVertical("##change_formation_vert_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox operationGroupBox(trNOOP("Formation Access"), "##change_formation_layout", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_formation_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::RadioButton(trNOOP("OFF"), &isDisabled, 0);
          ImGui::RadioButton(trNOOP("ON"), &isDisabled, 1);
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_formation_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_formation_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {

          command->access = isDisabled == 0 ? AccessMode::Disable : AccessMode::Enable;
          ImGui::CloseCurrentPopup();
          setOpen(false);
          m_confirmed = true;
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();

    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}


code:
#pragma once
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeFormationAccess.hpp"

struct Dialog_ChangeFormationAccess : IEventDialogController {
  Dialog_ChangeFormationAccess() = delete;
  explicit Dialog_ChangeFormationAccess(const std::string& name, const std::shared_ptr<ChangeFormationAccessCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , command(cmd) {
    if (cmd == nullptr) {
      command.reset(new ChangeFormationAccessCommand());
    }
    isDisabled = static_cast<int>(command->access);
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return command; };

private:
  int isDisabled;
  bool m_confirmed{false};
  std::shared_ptr<ChangeFormationAccessCommand> command;
  std::tuple<bool, bool> result;
};


code:
#include "Core/EventCommands/Dialog_ChangeGold.hpp"

#include "Database/Database.hpp"
#include "imgui.h"
#include <tuple>

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include "Database/Database.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeGold::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeGold");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 8) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeGold", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();

    ImGui::BeginVertical("##change_gold_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox operationGroupBox(trNOOP("Operation"), "##change_exp_operation_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_exp_operation_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Increase"), &m_operation, 0);
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Decrease"), &m_operation, 1);
          ImGui::Spring(0.33f);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_exp_operand", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_exp_operand_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_exp_operand_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Constant"), &m_operandSource, 0);
            ImGui::RadioButton(trNOOP("Variable"), &m_operandSource, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_gold_operand_inputs", {-1, -1});
          {
            ImGui::BeginDisabled(m_operandSource != 0);
            ImGui::SetNextItemWidth(-1);
            ImGui::SpinInt("##change_gold_constant_input", &m_constant, 1, 100, m_operandSource == 0 ? nullptr : "");
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_operandSource != 1);
            const std::string text = m_operandSource != 1 ? "##change_gold_variable_empty" : Database::instance()->variableNameOrId(m_variable);
            ImGui::PushID("##change_gold_variable_input");
            if (ImGui::EllipsesButton(text.c_str(), ImVec2{-1, 0})) {
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_variable);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_exp_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_exp_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->operation = static_cast<QuantityChangeOp>(m_operation);
          m_command->operandSource = static_cast<QuantityChangeSource>(m_operandSource);
          if (m_command->operandSource == QuantityChangeSource::Constant) {
            m_command->operand = m_constant;
          } else {
            m_command->operand = m_variable;
          }

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeGold::drawPickers() {
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        m_variable = m_variablePicker->selection();
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeGold.hpp"

struct Dialog_ChangeGold : IEventDialogController {
  Dialog_ChangeGold() = delete;
  explicit Dialog_ChangeGold(const std::string& name, const std::shared_ptr<ChangeGoldCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeGoldCommand());
    }
    m_operation = static_cast<int>(m_command->operation);
    m_operandSource = static_cast<int>(m_command->operandSource);
    m_constant = m_command->operand;
    m_variable = m_command->operand;
  }

  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_operation;
  int m_operandSource;

  int m_constant;
  int m_variable;

  bool m_confirmed{false};
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeGoldCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeHP.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <Database/Database.hpp>

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeHP::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeHP");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 11) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeHP", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_hp_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_hp_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_hp_actor_group_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_hp_actor_group_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Fixed"), &m_comparison, 0);
            ImGui::RadioButton(trNOOP("Variable"), &m_comparison, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_hp_actor_group_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_comparison != 0);
            ImGui::PushID("##change_hp_actor_group_fixed_button");
            if (ImGui::EllipsesButton(m_comparison == 0 ? Database::instance()->actorNameAndId(m_value).c_str() : "", {-1, 0})) {
              m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_value);
              m_actorPicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
            ImGui::BeginDisabled(m_comparison != 1);
            ImGui::PushID("##change_hp_actor_group_var");
            if (ImGui::EllipsesButton(m_comparison == 1 ? Database::instance()->variableNameAndId(m_valueVar).c_str() : "", {-1, 0})) {
              m_isOperand = false;
              m_variablePicker.emplace(trNOOP("Variables"), Database::instance()->system.variables(), m_valueVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      actorGroupBox.end();
      GroupBox operationGroupBox(trNOOP("Operation"), "##change_hp_operation_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_hp_operation_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Increase"), &m_quantityOp, 0);
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Decrease"), &m_quantityOp, 1);
          ImGui::Spring(0.33f);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_hp_operand", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_hp_operand_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_hp_operand_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Constant"), &m_quantitySource, 0);
            ImGui::RadioButton(std::format("{}##operand", tr("Variable")).c_str(), &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_hp_operand_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_hp_operand_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              if (m_quantity > 9999)
                m_quantity = 9999;
              if (m_quantity < 1)
                m_quantity = 1;
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_hp_operand_quantity_variable");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_isOperand = true;
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_hp_dialog_buttons", {-1, -1});
      {
        ImGui::BeginDisabled(m_quantityOp != 1);
        ImGui::Checkbox("Allow Knockout", &m_allowKnockout);
        ImGui::EndDisabled();
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_hp_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->comparison = static_cast<ActorComparisonSource>(m_comparison);
          m_command->quantityOp = static_cast<QuantityChangeOp>(m_quantityOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);
          m_command->allowKnockout = m_allowKnockout;

          if (m_command->comparison == ActorComparisonSource::Variable)
            m_command->value = m_valueVar;
          else
            m_command->value = m_value;

          if (m_command->quantitySource == QuantityChangeSource::Variable)
            m_command->quantity = m_quantityVar;
          else
            m_command->quantity = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeHP::drawPickers() {
  if (m_actorPicker) {
    if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
      if (confirmed) {
        m_value = m_actorPicker->selection();
      }
      m_actorPicker.reset();
    }
  }
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        if (m_isOperand) {
          m_quantityVar = m_variablePicker->selection();
        } else {
          m_valueVar = m_variablePicker->selection();
        }
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/GroupBox.hpp"
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"

#include "Database/Actor.hpp"
#include "Database/EventCommands/ChangeHP.hpp"

struct Dialog_ChangeHP : IEventDialogController {
  Dialog_ChangeHP() = delete;
  explicit Dialog_ChangeHP(const std::string& name, const std::shared_ptr<ChangeHPCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeHPCommand());
    }

    m_comparison = static_cast<int>(m_command->comparison);
    m_quantityOp = static_cast<int>(m_command->quantityOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);
    m_allowKnockout = m_command->allowKnockout;

    if (m_command->comparison == ActorComparisonSource::Variable)
      m_valueVar = m_command->value;
    else
      m_value = m_command->value;

    if (m_command->quantitySource == QuantityChangeSource::Variable)
      m_quantityVar = m_command->quantity;
    else
      m_quantity = m_command->quantity;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();

  int m_comparison;
  int m_value;
  int m_valueVar{1};
  int m_quantityOp;
  int m_quantitySource;
  int m_quantity;
  int m_quantityVar{1};
  bool m_allowKnockout{false};
  bool m_isOperand{false};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeHPCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeItems.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeItems::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeItems");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 10) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});

  if (ImGui::BeginPopupModal(std::format("{}###ChangeItems", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_items_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox itemGroupBox(trNOOP("Item"), "##change_items_item_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (itemGroupBox.begin()) {
        ImGui::PushID("##change_items_item");
        if (ImGui::EllipsesButton(Database::instance()->itemNameAndId(m_item).c_str(), ImVec2{-1, 0})) {
          m_itemPicker = ObjectPicker(trNOOP("Items"), Database::instance()->items.items(), m_item);
          m_itemPicker->setOpen(true);
        }
        ImGui::PopID();
      }
      itemGroupBox.end();

      GroupBox operationGroupBox(trNOOP("Operation"), "##change_items_operation_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_items_operation_layout", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Increase"), &m_operation, 0);
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Decrease"), &m_operation, 1);
          ImGui::Spring(0.33f);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();

      GroupBox operandroupBox(trNOOP("Operand"), "##change_items_operand_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandroupBox.begin()) {
        ImGui::BeginHorizontal("##change_items_operand_layout");
        {
          ImGui::BeginVertical("##change_items_operand_source");
          {
            ImGui::RadioButton(trNOOP("Constant"), &m_operandSource, 0);
            ImGui::RadioButton(trNOOP("Variable"), &m_operandSource, 1);
          }
          ImGui::EndVertical();
          ImGui::BeginVertical("##change_items_operand_value");
          {
            ImGui::BeginDisabled(m_operandSource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("###change_items_constant", &m_quantity, 1, 100, m_operandSource == 0 ? nullptr : "")) {
              m_quantity = std::clamp(m_quantity, 1, 9999);
            }
            ImGui::EndDisabled();
            ImGui::BeginDisabled(m_operandSource != 1);
            ImGui::PushID("###change_items_quant_var");
            if (ImGui::EllipsesButton(m_operandSource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_variablePicker.emplace(trNOOP("Variables"), Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_items_buttons");
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##recover_all_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;

          command->item = m_item;
          command->operation = static_cast<QuantityChangeOp>(m_operation);
          command->operandSource = static_cast<QuantityChangeSource>(m_operandSource);

          if (command->operandSource == QuantityChangeSource::Variable)
            command->operand = m_quantityVar;
          else
            command->operand = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeItems::drawPickers() {
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        m_quantityVar = m_variablePicker->selection();
      }
      m_variablePicker.reset();
    }
  }

  if (m_itemPicker) {
    if (const auto [closed, confirmed] = m_itemPicker->draw(); closed) {
      if (confirmed) {
        m_item = m_itemPicker->selection();
      }
      m_itemPicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeItems.hpp"
#include "Database/Items.hpp"

struct Dialog_ChangeItems : IEventDialogController {
  Dialog_ChangeItems() = delete;
  explicit Dialog_ChangeItems(const std::string& name, const std::shared_ptr<ChangeItemsCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , command(cmd) {
    if (cmd == nullptr) {
      command.reset(new ChangeItemsCommand());
    }

    m_item = static_cast<int>(command->item);
    m_operation = static_cast<int>(command->operation);
    m_operandSource = static_cast<int>(command->operandSource);

    if (command->operandSource == QuantityChangeSource::Variable)
      m_quantityVar = command->operand;
    else
      m_quantity = command->operand;
  }
  void drawPickers();
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return command; };

private:
  int m_item;
  int m_operation;
  int m_operandSource;
  int m_quantity{1};
  int m_quantityVar{1};
  bool m_includeEquipment{false};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Item>> m_itemPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeItemsCommand> command;
  std::tuple<bool, bool> result;
};


code:
#include "Core/EventCommands/Dialog_ChangeLevel.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <Database/Database.hpp>

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeLevel::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeLevel");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 11) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeLevel", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_level_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_level_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_level_actor_group_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_level_actor_group_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Fixed"), &m_comparison, 0);
            ImGui::RadioButton(trNOOP("Variable"), &m_comparison, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_level_actor_group_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_comparison != 0);
            ImGui::PushID("##change_level_actor_group_fixed_button");
            if (ImGui::EllipsesButton(m_comparison == 0 ? Database::instance()->actorNameAndId(m_value).c_str() : "", {-1, 0})) {
              m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_value);
              m_actorPicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
            ImGui::BeginDisabled(m_comparison != 1);
            ImGui::PushID("##change_level_actor_group_var");
            if (ImGui::EllipsesButton(m_comparison == 1 ? Database::instance()->variableNameAndId(m_value).c_str() : "", {-1, 0})) {
              m_isOperand = false;
              m_variablePicker.emplace(trNOOP("Variables"), Database::instance()->system.variables(), m_value);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      actorGroupBox.end();
      GroupBox operationGroupBox(trNOOP("Operation"), "##change_level_operation_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_level_operation_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Increase"), &m_quantityOp, 0);
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Decrease"), &m_quantityOp, 1);
          ImGui::Spring(0.33f);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_level_operand", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_level_operand_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_level_operand_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Constant"), &m_quantitySource, 0);
            ImGui::RadioButton(std::format("{}##operand", tr("Variable")).c_str(), &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_level_operand_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_level_operand_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              if (m_quantity > 100)
                m_quantity = 100;
              if (m_quantity < 1)
                m_quantity = 1;
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_level_operand_quantity_variable");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_isOperand = true;
              m_variablePicker.emplace(trNOOP("Variables"), Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_level_dialog_buttons", {-1, -1});
      {
        ImGui::BeginDisabled(m_quantityOp != 0);
        ImGui::Checkbox(trNOOP("Show Level Up"), &m_showLevelUp);
        ImGui::EndDisabled();
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_level_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->comparison = static_cast<ActorComparisonSource>(m_comparison);
          m_command->quantityOp = static_cast<QuantityChangeOp>(m_quantityOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);
          if (m_command->comparison == ActorComparisonSource::Fixed) {
            m_command->value = m_value;
          } else {
            m_command->value = m_valueVar;
          }
          if (m_command->quantitySource == QuantityChangeSource::Constant) {
            m_command->quantity = m_quantity;
          } else {
            m_command->quantity = m_quantityVar;
          }

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeLevel::drawPickers() {
  if (m_actorPicker) {
    if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
      if (confirmed) {
        m_value = m_actorPicker->selection();
      }
      m_actorPicker.reset();
    }
  }
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        if (m_isOperand) {
          m_quantityVar = m_variablePicker->selection();
        } else {
          m_valueVar = m_variablePicker->selection();
        }
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/Actor.hpp"
#include "Database/EventCommands/ChangeHP.hpp"
#include "Database/EventCommands/ChangeLevel.hpp"
#include "Database/Skills.hpp"

struct Dialog_ChangeLevel : IEventDialogController {
  Dialog_ChangeLevel() = delete;
  explicit Dialog_ChangeLevel(const std::string& name, const std::shared_ptr<ChangeLevelCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeLevelCommand());
    }

    m_comparison = static_cast<int>(m_command->comparison);
    m_quantityOp = static_cast<int>(m_command->quantityOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);
    m_showLevelUp = m_command->showLevelUp;

    if (m_command->comparison == ActorComparisonSource::Variable)
      m_valueVar = m_command->value;
    else
      m_value = m_command->value;

    if (m_command->quantitySource == QuantityChangeSource::Variable)
      m_quantityVar = m_command->quantity;
    else
      m_quantity = m_command->quantity;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_comparison;
  int m_value;
  int m_valueVar{1};
  int m_quantityOp;
  int m_quantitySource;
  int m_quantity;
  int m_quantityVar{1};
  bool m_showLevelUp{false};
  bool m_isOperand{false};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeLevelCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeMP.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"
#include "Database/Database.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeMP::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeMP");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 11) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeMP", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();
    ImGui::BeginVertical("##change_mp_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_mp_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_mp_actor_group_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_mp_actor_group_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Fixed"), &m_comparison, 0);
            ImGui::RadioButton(trNOOP("Variable"), &m_comparison, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_mp_actor_group_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_comparison != 0);
            ImGui::PushID("##change_mp_actor_group_fixed_button");
            if (ImGui::EllipsesButton(m_comparison == 0 ? Database::instance()->actorNameAndId(m_value).c_str() : "", {-1, 0})) {
              m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_value);
              m_actorPicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
            ImGui::BeginDisabled(m_comparison != 1);
            ImGui::PushID("##change_mp_actor_group_var");
            if (ImGui::EllipsesButton(m_comparison == 1 ? Database::instance()->variableNameAndId(m_value).c_str() : "", {-1, 0})) {
              m_isOperand = false;
              m_variablePicker.emplace(trNOOP("Variables"), Database::instance()->system.variables(), m_value);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      actorGroupBox.end();
      GroupBox operationGroupBox(trNOOP("Operation"), "##change_mp_operation_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_mp_operation_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Increase"), &m_quantityOp, 0);
          ImGui::Spring(0.33f);
          ImGui::RadioButton(trNOOP("Decrease"), &m_quantityOp, 1);
          ImGui::Spring(0.33f);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      GroupBox operandGroupBox(trNOOP("Operand"), "##change_mp_operand", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operandGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_mp_operand_horizontal", {-1, -1});
        {
          ImGui::BeginVertical("##change_mp_operand_radios", {-1, -1});
          {
            ImGui::RadioButton(trNOOP("Constant"), &m_quantitySource, 0);
            ImGui::RadioButton(std::format("{}##operand", tr("Variable")).c_str(), &m_quantitySource, 1);
          }
          ImGui::EndVertical();
          ImGui::Spring();
          ImGui::BeginVertical("##change_mp_operand_buttons", {-1, -1});
          {
            ImGui::BeginDisabled(m_quantitySource != 0);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##change_mp_operand_constant", &m_quantity, 1, 100, m_quantitySource == 0 ? nullptr : "")) {
              m_quantity = std::clamp(m_quantity, 1, 9999);
            }
            ImGui::EndDisabled();

            ImGui::BeginDisabled(m_quantitySource != 1);
            ImGui::PushID("##change_mp_operand_quantity_variable");
            if (ImGui::EllipsesButton(m_quantitySource == 1 ? Database::instance()->variableNameAndId(m_quantityVar).c_str() : "", ImVec2{-1, 0})) {
              m_isOperand = true;
              m_variablePicker.emplace("Variables", Database::instance()->system.variables(), m_quantityVar);
              m_variablePicker->setOpen(true);
            }
            ImGui::PopID();
            ImGui::EndDisabled();
          }
          ImGui::EndVertical();
        }
        ImGui::EndHorizontal();
      }
      operandGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_mp_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_mp_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->comparison = static_cast<ActorComparisonSource>(m_comparison);
          m_command->quantityOp = static_cast<QuantityChangeOp>(m_quantityOp);
          m_command->quantitySource = static_cast<QuantityChangeSource>(m_quantitySource);

          if (m_command->comparison == ActorComparisonSource::Variable)
            m_command->value = m_valueVar;
          else
            m_command->value = m_value;

          if (m_command->quantitySource == QuantityChangeSource::Variable)
            m_command->quantity = m_quantityVar;
          else
            m_command->quantity = m_quantity;

          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeMP::drawPickers() {
  if (m_actorPicker) {
    if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
      if (confirmed) {
        m_value = m_actorPicker->selection();
      }
      m_actorPicker.reset();
    }
  }
  if (m_variablePicker) {
    if (const auto [closed, confirmed] = m_variablePicker->draw(); closed) {
      if (confirmed) {
        if (m_isOperand) {
          m_quantityVar = m_variablePicker->selection();
        } else {
          m_valueVar = m_variablePicker->selection();
        }
      }
      m_variablePicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/CommonUI/VariableSwitchPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"

#include "Database/Actor.hpp"
#include "Database/EventCommands/ChangeMP.hpp"

struct Dialog_ChangeMP : IEventDialogController {
  Dialog_ChangeMP() = delete;
  explicit Dialog_ChangeMP(const std::string& name, const std::shared_ptr<ChangeMPCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeMPCommand());
    }

    m_comparison = static_cast<int>(m_command->comparison);
    m_quantityOp = static_cast<int>(m_command->quantityOp);
    m_quantitySource = static_cast<int>(m_command->quantitySource);

    if (m_command->comparison == ActorComparisonSource::Fixed) {
      m_value = m_command->value;
    } else {
      m_valueVar = m_command->value;
    }
    if (m_command->quantitySource == QuantityChangeSource::Constant) {
      m_quantity = m_command->quantity;
    } else {
      m_quantityVar = m_command->quantity;
    }
  }
  void drawPickers();
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  int m_comparison;
  int m_value{1};
  int m_valueVar{1};
  int m_quantityOp;
  int m_quantitySource;
  int m_quantity{1};
  int m_quantityVar{1};
  bool m_isOperand{false};

  bool m_confirmed{false};
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::optional<VariableSwitchPicker> m_variablePicker;
  std::shared_ptr<ChangeMPCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeMapDisplayName.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"
#include "imgui.h"
#include "imgui_internal.h"

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeMapDisplayName::draw() {
  if (isOpen()) {
    ImGui::OpenPopup(m_name.c_str());
  }
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 5) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(m_name.c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {

    ImGui::BeginVertical("##change_map_display_vert_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox operationGroupBox(trNOOP("Map Name Display"), "##change_map_display_layout", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_map_display_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::RadioButton(trNOOP("ON"), &m_checkIfOn, 0);
          ImGui::RadioButton(trNOOP("OFF"), &m_checkIfOn, 1);
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_map_display_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_map_display_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {

          command->checkIfOn = m_checkIfOn == 0 ? ValueControl::ON : ValueControl::OFF;
          ImGui::CloseCurrentPopup();
          setOpen(false);
          m_confirmed = true;
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}


code:
#pragma once
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeMapDisplayName.hpp"

struct Dialog_ChangeMapDisplayName : IEventDialogController {
  Dialog_ChangeMapDisplayName() = delete;
  explicit Dialog_ChangeMapDisplayName(const std::string& name, const std::shared_ptr<ChangeMapNameDisplayCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , command(cmd) {
    if (cmd == nullptr) {
      command.reset(new ChangeMapNameDisplayCommand());
    }
    m_checkIfOn = static_cast<int>(command->checkIfOn);
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return command; };

private:
  int m_checkIfOn;
  bool m_confirmed{false};
  std::shared_ptr<ChangeMapNameDisplayCommand> command;
  std::tuple<bool, bool> result;
};


code:
#include "Core/EventCommands/Dialog_ChangeMenuAccess.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"
#include "imgui.h"
#include "imgui_internal.h"

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeMenuAccess::draw() {
  if (isOpen()) {
    ImGui::OpenPopup(m_name.c_str());
  }

  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 5) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(m_name.c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {

    ImGui::BeginVertical("##change_menu_access_vert_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox operationGroupBox(trNOOP("Menu Access"), "##change_menu_access_layout", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_menu_access_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::RadioButton(trNOOP("OFF"), &isDisabled, 0);
          ImGui::RadioButton(trNOOP("ON"), &isDisabled, 1);
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_menu_access_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_menu_access_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {

          command->access = isDisabled == 0 ? AccessMode::Disable : AccessMode::Enable;
          ImGui::CloseCurrentPopup();
          setOpen(false);
          m_confirmed = true;
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}


code:
#pragma once
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeMenuAccess.hpp"

struct Dialog_ChangeMenuAccess : IEventDialogController {
  Dialog_ChangeMenuAccess() = delete;
  explicit Dialog_ChangeMenuAccess(const std::string& name, const std::shared_ptr<ChangeMenuAccessCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , command(cmd) {
    if (cmd == nullptr) {
      command.reset(new ChangeMenuAccessCommand());
    }
    isDisabled = static_cast<int>(command->access);
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return command; };

private:
  int isDisabled;
  bool m_confirmed{false};
  std::shared_ptr<ChangeMenuAccessCommand> command;
  std::tuple<bool, bool> result;
};


code:
#include "Core/EventCommands/Dialog_ChangeName.hpp"

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeName::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeName");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 7) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeName", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();

    ImGui::BeginVertical("##change_name_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_name_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        // Actor Button
        ImGui::PushID("##name_selection_actor");
        if (ImGui::EllipsesButton(Database::instance()->actorNameAndId(m_actor).c_str(), ImVec2{-1, 0})) {
          m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_actor);
          m_actorPicker->setOpen(true);
        }
        ImGui::PopID();
      }
      actorGroupBox.end();

      GroupBox nameGroupBox(trNOOP("Name"), "##change_name_name_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (nameGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);
        ImGui::InputText("##name_input", &m_actorName);
      }
      nameGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_name_buttons", {-1, 0});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_name_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->actor = m_actor;
          m_command->name = m_actorName;
          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeName::drawPickers() {
  if (m_actorPicker) {
    if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
      if (confirmed) {
        m_actor = m_actorPicker->selection();
      }
      m_actorPicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"

#include "Database/Actor.hpp"
#include "Database/EventCommands/ChangeName.hpp"

struct Dialog_ChangeName : IEventDialogController {
  Dialog_ChangeName() = delete;
  explicit Dialog_ChangeName(const std::string& name, const std::shared_ptr<ChangeNameCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeNameCommand());
    }
    m_actor = m_command->actor;
    m_actorName = m_command->name;
  }
  void drawPickers();
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  int m_actor;
  std::string m_actorName;

  bool m_confirmed{false};
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::shared_ptr<ChangeNameCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeNickname.hpp"

#include "Database/Database.hpp"
#include "imgui.h"
#include <tuple>

#include "Database/Database.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"

#include <imgui.h>
#include <imgui_internal.h>

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeNickname::draw() {
  if (isOpen()) {
    ImGui::OpenPopup("###ChangeNickname");
  }
  ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 7) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(std::format("{}###ChangeNickname", m_name).c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    drawPickers();

    ImGui::BeginVertical("##change_nickname_main_layout", ImGui::GetContentRegionAvail());
    {
      GroupBox actorGroupBox(trNOOP("Actor"), "##change_nickname_actor_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (actorGroupBox.begin()) {
        // Actor Button
        ImGui::PushID("##name_selection_actor");
        if (ImGui::EllipsesButton(Database::instance()->actorNameAndId(m_actor).c_str(), ImVec2{-1, 0})) {
          m_actorPicker = ObjectPicker(trNOOP("Actor"), Database::instance()->actors.actorList(), m_actor);
          m_actorPicker->setOpen(true);
        }
        ImGui::PopID();
      }
      actorGroupBox.end();

      GroupBox nameGroupBox(trNOOP("Nickname"), "##change_nickname_nickname_group", {-1, 0}, nullptr, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (nameGroupBox.begin()) {
        ImGui::SetNextItemWidth(-1);
        ImGui::InputText("##name_input", &m_actorNickname);
      }
      nameGroupBox.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_nickname_buttons", {-1, 0});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_nickname_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {
          m_confirmed = true;
          m_command->actor = m_actor;
          m_command->nick = m_actorNickname;
          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}

void Dialog_ChangeNickname::drawPickers() {
  if (m_actorPicker) {
    if (const auto [closed, confirmed] = m_actorPicker->draw(); closed) {
      if (confirmed) {
        m_actor = m_actorPicker->selection();
      }
      m_actorPicker.reset();
    }
  }
}


code:
#pragma once
#include "Core/CommonUI/ObjectPicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/Actor.hpp"

#include "Database/EventCommands/ChangeNickname.hpp"

struct Dialog_ChangeNickname : IEventDialogController {
  Dialog_ChangeNickname() = delete;
  explicit Dialog_ChangeNickname(const std::string& name, const std::shared_ptr<ChangeNicknameCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , m_command(cmd) {
    if (cmd == nullptr) {
      m_command.reset(new ChangeNicknameCommand());
    }
    m_actor = m_command->actor;
    m_actorNickname = m_command->nick;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return m_command; };

private:
  void drawPickers();
  int m_actor = 1;
  std::string m_actorNickname;

  bool m_confirmed{false};
  std::optional<ObjectPicker<Actor>> m_actorPicker;
  std::shared_ptr<ChangeNicknameCommand> m_command;
};


code:
#include "Core/EventCommands/Dialog_ChangeParallax.hpp"

#include "Core/CommonUI/GroupBox.hpp"
#include "Core/ImGuiExt/ImGuiUtils.hpp"
#include "Database/Database.hpp"
#include "imgui.h"
#include "imgui_internal.h"

#include <tuple>

std::tuple<bool, bool> Dialog_ChangeParallax::draw() {
  if (isOpen()) {
    ImGui::OpenPopup(m_name.c_str());
  }
  const auto maxSize =
      ImVec2{ImGui::CalcTextSize("#############################").x + (ImGui::GetStyle().FramePadding.x * 2), (ImGui::GetFrameHeightWithSpacing() * 10) + (ImGui::GetStyle().FramePadding.y * 2)};
  ImGui::SetNextWindowSize(maxSize, ImGuiCond_Appearing);
  ImGui::SetNextWindowSizeConstraints(maxSize, {FLT_MAX, FLT_MAX});
  if (ImGui::BeginPopupModal(m_name.c_str(), &m_open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) {
    if (m_imagePicker) {
      if (const auto [closed, confirmed] = m_imagePicker->draw(); closed) {
        if (confirmed) {
          m_imagePicker->accept();
          m_image = m_imagePicker->selectedImage();
        }
      }
    }

    ImGui::BeginVertical("##change_parallax_main_layout", ImGui::GetContentRegionAvail());
    {
      // Parallax Background Image Group
      GroupBox operationGroupBox(trNOOP("Parallax Background Image"), "##change_parallax_layout", {-1, 0}, nullptr,
                                 ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (operationGroupBox.begin()) {
        ImGui::BeginHorizontal("##change_parallax_group_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::PushID("#parallax_image_selection");
          if (ImGui::EllipsesButton(m_image.c_str(), ImVec2{-1, 0})) {
            if (!m_imagePicker) {
              m_imagePicker.emplace(ImagePicker::PickerMode::Parallax, m_image);
            }
            m_imagePicker->setImageInfo(m_image);
            m_imagePicker->setOpen(true);
          }
          ImGui::PopID();
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      operationGroupBox.end();
      // Loop Horizontally Group
      GroupBox loopHorzGroup(trNOOP("Loop Horizontally"), "##loop_horz_layout", {-1, 0}, &m_loopHorizontally,
                             ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (loopHorzGroup.begin()) {
        ImGui::BeginHorizontal("##loop_horizontal", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::BeginChild("##loop_horz_child", {-1, 0}, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_NavFlattened,
                            ImGuiWindowFlags_NoBackground);
          {
            ImGui::SetNextItemWidth(-1);
            ImGui::BeginDisabled(!m_loopHorizontally);
            if (ImGui::SpinInt("##parallax_x", &m_scrollX, 1, 100, m_loopHorizontally ? nullptr : "")) {
              m_scrollX = std::clamp(m_scrollX, -32, 32);
            }
            ImGui::EndDisabled();
          }
          ImGui::EndChild();
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      loopHorzGroup.end();
      // Loop Vertically Group
      GroupBox loopVertGroup(trNOOP("Loop Vertically"), "##loop_vert_layout", {-1, 0}, &m_loopVertically, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize);
      if (loopVertGroup.begin()) {
        ImGui::BeginHorizontal("##loop_vertical", {ImGui::GetContentRegionAvail().x, -1});
        {
          ImGui::Spring(.5);
          ImGui::BeginChild("##loop_vert_child", {-1, 0}, ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_NavFlattened,
                            ImGuiWindowFlags_NoBackground);
          {
            ImGui::BeginDisabled(!m_loopVertically);
            ImGui::SetNextItemWidth(-1);
            if (ImGui::SpinInt("##parallax_y", &m_scrollY, 1, 100, m_loopVertically ? nullptr : "")) {
              m_scrollY = std::clamp(m_scrollY, -32, 32);
            }
            ImGui::EndDisabled();
          }
          ImGui::EndChild();
          ImGui::Spring(.5);
        }
        ImGui::EndHorizontal();
      }
      loopVertGroup.end();
      ImGui::Spring();
      ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal, ImGui::GetDPIScaledValue(1.5));
      ImGui::BeginHorizontal("##change_tileset_dialog_buttons", {-1, -1});
      {
        ImGui::Spring();
        if (const auto ret = ImGui::ButtonGroup("##change_tileset_dialog_buttons", {trNOOP("OK"), trNOOP("Cancel")}); ret == 0) {

          m_confirmed = true;
          command->image = m_image;
          command->loopVertically = m_loopVertically;
          command->loopHorizontally = m_loopHorizontally;
          command->scrollX = m_scrollX;
          command->scrollY = m_scrollY;
          ImGui::CloseCurrentPopup();
          setOpen(false);
        } else if (ret == 1) {
          ImGui::CloseCurrentPopup();
          setOpen(false);
        }
      }
      ImGui::EndHorizontal();
    }
    ImGui::EndVertical();
    ImGui::EndPopup();
  }

  return std::make_tuple(!m_open, m_confirmed);
}


code:
#pragma once
#include "Core/CommonUI/ImagePicker.hpp"
#include "Core/EventCommands/IEventDialogController.hpp"
#include "Database/EventCommands/ChangeParallax.hpp"

struct Dialog_ChangeParallax : IEventDialogController {
  Dialog_ChangeParallax() = delete;
  explicit Dialog_ChangeParallax(const std::string& name, const std::shared_ptr<ChangeParallaxCommand>& cmd = nullptr)
  : IEventDialogController(name)
  , command(cmd) {
    if (cmd == nullptr) {
      command.reset(new ChangeParallaxCommand());
    }
    m_image = command->image;
    m_loopHorizontally = command->loopHorizontally;
    m_loopVertically = command->loopVertically;
    m_scrollX = command->scrollX;
    m_scrollY = command->scrollY;
  }
  std::tuple<bool, bool> draw() override;

  std::shared_ptr<IEventCommand> getCommand() override { return command; };

private:
  std::string m_image;
  bool m_loopHorizontally;
  bool m_loopVertically;
  int m_scrollX;
  int m_scrollY;

  int m_image_selection{0};
  std::optional<ImagePicker> m_imagePicker;

  bool m_confirmed{false};
  std::shared_ptr<ChangeParallaxCommand> command;
  std::tuple<bool, bool> result;
};