Skip to content

Developer information and guides

Eknous edited this page Oct 31, 2024 · 2 revisions

(note: this page is a work in progress!)

guides

Adding a UI window

Files to modify:

  • CMakeLists.txt
  • src/gui/doAction.cpp
  • src/gui/gui.cpp
  • src/gui/gui.h
  • src/gui/guiConst.cpp

  1. create a C++ source file in src/gui/ for your window (e.g. src/gui/myWindow.cpp)
  2. add that file to the CMakeLists (starting from line 889, in alphabetical order with the other windows)
...
src/gui/mixer.cpp
src/gui/midiMap.cpp
+ src/gui/myWindow.cpp
src/gui/newSong.cpp
...
  1. in src/gui/gui.h:

    1. add an entry for your window in the FurnaceGUIWindows enum (at the end, before GUI_WINDOW_SPOILER)
    ...
      GUI_WINDOW_CS_PLAYER,
      GUI_WINDOW_USER_PRESETS,
    + GUI_WINDOW_MY_WINDOW,
      GUI_WINDOW_SPOILER
    };
    ...
    1. add an entry for your window in the FurnaceGUIActions enum (last GUI_ACTION_WINDOW_*, before GUI_ACTION_COLLAPSE_WINDOW)
    ...
      GUI_ACTION_WINDOW_CS_PLAYER,
      GUI_ACTION_WINDOW_USER_PRESETS,
    + GUI_ACTION_WINDOW_MY_WINDOW,
    
      GUI_ACTION_COLLAPSE_WINDOW,
    ...
    1. add a boolean for the window open state in the FuranceGUI class (last *Open)
    ...
      bool subSongsOpen, findOpen, spoilerOpen, patManagerOpen, sysManagerOpen, clockOpen, speedOpen;
    - bool groovesOpen, xyOscOpen, memoryOpen, csPlayerOpen, cvOpen, userPresetsOpen;
    + bool groovesOpen, xyOscOpen, memoryOpen, csPlayerOpen, cvOpen, userPresetsOpen, myWindowOpen;
    ...
    1. add the function declaration for drawing your window in the FurnaceGUI class (last void draw*(), before void drawSystemChannelInfo(const DivSysDef* whichDef);)
    ...
      void drawXYOsc();
      void drawUserPresets();
    + void drawMyWindow();
      void drawSystemChannelInfo(const DivSysDef* whichDef);
    ...
  2. in src/gui/doAction.cpp:

    1. add the case for your window's action in the switch in the doAction(int what) function (last case GUI_ACTION_WINDOW_*, before case GUI_ACTION_COLLAPSE_WINDOW)
    ...
        case GUI_ACTION_WINDOW_USER_PRESETS:
          nextWindow=GUI_WINDOW_USER_PRESETS;
          break;
    +   case GUI_ACTION_WINDOW_MY_WINDOW:
    +     nextWindow=GUI_WINDOW_MY_WINDOW;
    +     break;
        
        case GUI_ACTION_COLLAPSE_WINDOW:
    ...
    1. add the case for the action of closing your window in the same function but in the nested switch for the GUI_ACTION_CLOSE_WINDOW case (last case GUI_WINDOW_*, before default:)
    ...
        case GUI_ACTION_CLOSE_WINDOW:
          switch (curWindow) {
    ...
            case GUI_WINDOW_USER_PRESETS:
              userPresetsOpen=false;
    +       case GUI_WINDOW_MY_WINDOW:
    +         myWindowOpen=false;
            default:
    ...
  3. in src/gui/guiConst.cpp add the action definition for your window in the guiAction[GUI_ACTION_MAX] array (last D("WINDOW_*, before D("COLLAPSE_WINDOW...)

    ...
      D("WINDOW_USER_PRESETS", _N("User Presets"), 0),
    + D("WINDOW_MY_WINDOW", _N("My Window"), 0),
    
      D("COLLAPSE_WINDOW", _N("Collapse/expand current window"), 0),
    ...
  4. in src/gui/gui.cpp:

    1. declare your window's metric in the loop() function (last DECLARE_METRIC(*), before DECLARE_METRIC(popup))
    ...
      DECLARE_METRIC(userPresets)
    + DECLARE_METRIC(myWindow)
      DECLARE_METRIC(popup)
    ...
    1. add the IMPORT_CLOSE for your window in the if (pendingLayoutImportStep==0) { statement (last IMPORT_CLOSE(*))
    ...
            IMPORT_CLOSE(csPlayerOpen);
            IMPORT_CLOSE(userPresetsOpen);
    +       IMPORT_CLOSE(myWindowOpen);
          } else if (pendingLayoutImportStep==1) {
    ...
    1. add the menu item for your window
      notes:
      • depending on the type of your window, this may be optional, even unnecessary
      • the location of the menu item also may depend on your window type. for this guide the entry is added at the end, in the "window" menu, not belonging to any category)
    ...
            if (ImGui::MenuItem(_("piano/input pad"),BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen;
    +       if (ImGui::MenuItem(_("my window"),BIND_FOR(GUI_ACTION_MY_WINDOW),myWindowOpen)) myWindowOpen=!myWindowOpen;
            if (spoilerOpen) if (ImGui::MenuItem(_("spoiler"),NULL,spoilerOpen)) spoilerOpen=!spoilerOpen;
    ...
    1. add the metric measurement macros for your window (last MEASURE(*))
      note for mobile ui:
      • if your window belongs to a scene, the MEASURE(...) statement should be inside the case for that scene. for this guide, it does not
    ...
        if (mobileUI) {
    ...
          MEASURE(userPresets,drawUserPresets());
          MEASURE(patManager,drawPatManager());
    +     MEASURE(myWindow,drawMyWindow());
    ...
    ...
        } else {
    ...
          MEASURE(effectList,drawEffectList());
          MEASURE(userPresets,drawUserPresets());
    +     MEASURE(myWindow,drawMyWindow());
    ...
    1. get the state of your window from the config (last *Open=e->getConfBool("*Open",false);
    ...
      spoilerOpen=e->getConfBool("spoilerOpen",false);
      userPresetsOpen=e->getConfBool("userPresetsOpen",false);
    + myWindowOpen=e->getConfBool("myWindowOpen",false);
    ...
    1. set the state of your window in the config (last conf.set("*Open",*Open);)
    ...
      conf.set("spoilerOpen",spoilerOpen);
      conf.set("userPresetsOpen",userPresetsOpen);
    + conf.set("myWindowOpen",myWindowOpen);
    ...
    1. initialize the bool for your window state in the class constructor (last *Open(...))
    ...
      cvOpen(false),
      userPresetsOpen(false),
    + myWindowOpen(false),
    ...
  5. in src/gui/myWindow.cpp:

    1. add this template code for a generic Furnace window
    /**
     * Furnace Tracker - multi-system chiptune tracker
     * Copyright (C) 2021-2024 tildearrow and contributors
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License along
     * with this program; if not, write to the Free Software Foundation, Inc.,
     * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     */
    
    #include "gui.h"
    #include "imgui.h"
    
    void FurnaceGUI::drawMyWindow() {
      if (nextWindow==GUI_WINDOW_MY_WINDOW) {
        myWindowOpen=true;
        ImGui::SetNextWindowFocus();
        nextWindow=GUI_WINDOW_NOTHING;
      }
      if (!myWindowOpen) return;
      if (ImGui::Begin("My Window",&myWindowOpen,globalWinFlags,_("My Window"))) {
        // your window code here
      }
      if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_MY_WINDOW;
      ImGui::End();
    }
    1. modify it to add your stuff!
Clone this wiki locally