2021-12-11 07:10:09 +00:00
|
|
|
#include "../engine/engine.h"
|
2021-12-28 23:23:57 +00:00
|
|
|
#include "SDL_keycode.h"
|
2021-12-11 08:11:40 +00:00
|
|
|
#include "imgui.h"
|
|
|
|
#include "imgui_impl_sdl.h"
|
|
|
|
#include "imgui_impl_sdlrenderer.h"
|
|
|
|
#include <SDL.h>
|
2021-12-24 23:27:55 +00:00
|
|
|
#include <deque>
|
2021-12-14 22:45:37 +00:00
|
|
|
#include <map>
|
2021-12-11 07:10:09 +00:00
|
|
|
|
2021-12-13 22:09:46 +00:00
|
|
|
enum FurnaceGUIColors {
|
|
|
|
GUI_COLOR_BACKGROUND=0,
|
|
|
|
GUI_COLOR_FRAME_BACKGROUND,
|
|
|
|
GUI_COLOR_HEADER,
|
|
|
|
GUI_COLOR_ITEM_BACKGROUND,
|
|
|
|
GUI_COLOR_ITEM_FOREGROUND,
|
2022-01-19 23:10:42 +00:00
|
|
|
GUI_COLOR_EDITING,
|
2021-12-29 04:10:30 +00:00
|
|
|
GUI_COLOR_INSTR_FM,
|
|
|
|
GUI_COLOR_INSTR_STD,
|
2022-01-09 22:48:09 +00:00
|
|
|
GUI_COLOR_INSTR_GB,
|
|
|
|
GUI_COLOR_INSTR_C64,
|
|
|
|
GUI_COLOR_INSTR_AMIGA,
|
2022-01-14 01:44:45 +00:00
|
|
|
GUI_COLOR_INSTR_PCE,
|
|
|
|
GUI_COLOR_INSTR_AY,
|
2022-01-14 05:02:10 +00:00
|
|
|
GUI_COLOR_INSTR_AY8930,
|
2022-01-14 20:21:57 +00:00
|
|
|
GUI_COLOR_INSTR_TIA,
|
2022-01-15 04:26:22 +00:00
|
|
|
GUI_COLOR_INSTR_SAA1099,
|
2022-01-09 22:48:09 +00:00
|
|
|
GUI_COLOR_INSTR_UNKNOWN,
|
2021-12-23 16:29:11 +00:00
|
|
|
GUI_COLOR_CHANNEL_FM,
|
|
|
|
GUI_COLOR_CHANNEL_PULSE,
|
|
|
|
GUI_COLOR_CHANNEL_NOISE,
|
|
|
|
GUI_COLOR_CHANNEL_WAVE,
|
|
|
|
GUI_COLOR_CHANNEL_PCM,
|
2021-12-23 22:09:33 +00:00
|
|
|
GUI_COLOR_CHANNEL_OP,
|
|
|
|
GUI_COLOR_CHANNEL_MUTED,
|
2021-12-23 16:29:11 +00:00
|
|
|
GUI_COLOR_PATTERN_CURSOR,
|
|
|
|
GUI_COLOR_PATTERN_CURSOR_HOVER,
|
|
|
|
GUI_COLOR_PATTERN_CURSOR_ACTIVE,
|
|
|
|
GUI_COLOR_PATTERN_SELECTION,
|
|
|
|
GUI_COLOR_PATTERN_SELECTION_HOVER,
|
|
|
|
GUI_COLOR_PATTERN_SELECTION_ACTIVE,
|
2021-12-13 22:09:46 +00:00
|
|
|
GUI_COLOR_PATTERN_HI_1,
|
|
|
|
GUI_COLOR_PATTERN_HI_2,
|
|
|
|
GUI_COLOR_PATTERN_ROW_INDEX,
|
|
|
|
GUI_COLOR_PATTERN_ACTIVE,
|
|
|
|
GUI_COLOR_PATTERN_INACTIVE,
|
|
|
|
GUI_COLOR_PATTERN_INS,
|
|
|
|
GUI_COLOR_PATTERN_VOLUME_MAX,
|
|
|
|
GUI_COLOR_PATTERN_VOLUME_HALF,
|
|
|
|
GUI_COLOR_PATTERN_VOLUME_MIN,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_INVALID,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_PITCH,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_VOLUME,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_PANNING,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_SONG,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_TIME,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_SPEED,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY,
|
|
|
|
GUI_COLOR_PATTERN_EFFECT_MISC,
|
2021-12-21 00:46:49 +00:00
|
|
|
GUI_COLOR_EE_VALUE,
|
2021-12-21 07:30:09 +00:00
|
|
|
GUI_COLOR_PLAYBACK_STAT,
|
2021-12-13 22:09:46 +00:00
|
|
|
GUI_COLOR_MAX
|
|
|
|
};
|
|
|
|
|
2021-12-14 22:45:37 +00:00
|
|
|
enum FurnaceGUIWindows {
|
|
|
|
GUI_WINDOW_NOTHING=0,
|
2021-12-15 22:32:08 +00:00
|
|
|
GUI_WINDOW_EDIT_CONTROLS,
|
2021-12-14 22:45:37 +00:00
|
|
|
GUI_WINDOW_SONG_INFO,
|
|
|
|
GUI_WINDOW_ORDERS,
|
|
|
|
GUI_WINDOW_INS_LIST,
|
|
|
|
GUI_WINDOW_PATTERN,
|
2021-12-16 08:09:18 +00:00
|
|
|
GUI_WINDOW_INS_EDIT,
|
|
|
|
GUI_WINDOW_WAVE_LIST,
|
|
|
|
GUI_WINDOW_WAVE_EDIT,
|
|
|
|
GUI_WINDOW_SAMPLE_LIST,
|
2022-01-13 06:03:57 +00:00
|
|
|
GUI_WINDOW_SAMPLE_EDIT,
|
|
|
|
GUI_WINDOW_MIXER
|
2021-12-14 22:45:37 +00:00
|
|
|
};
|
|
|
|
|
2021-12-17 08:33:12 +00:00
|
|
|
enum FurnaceGUIFileDialogs {
|
|
|
|
GUI_FILE_OPEN,
|
|
|
|
GUI_FILE_SAVE,
|
2022-01-19 08:15:20 +00:00
|
|
|
GUI_FILE_INS_OPEN,
|
|
|
|
GUI_FILE_INS_SAVE,
|
|
|
|
GUI_FILE_WAVE_OPEN,
|
|
|
|
GUI_FILE_WAVE_SAVE,
|
2021-12-17 08:33:12 +00:00
|
|
|
GUI_FILE_SAMPLE_OPEN,
|
2022-01-18 04:34:29 +00:00
|
|
|
GUI_FILE_SAMPLE_SAVE,
|
|
|
|
GUI_FILE_EXPORT_AUDIO_ONE,
|
|
|
|
GUI_FILE_EXPORT_AUDIO_PER_SYS,
|
|
|
|
GUI_FILE_EXPORT_AUDIO_PER_CHANNEL,
|
|
|
|
GUI_FILE_EXPORT_VGM,
|
|
|
|
GUI_FILE_EXPORT_ROM
|
2021-12-17 08:33:12 +00:00
|
|
|
};
|
|
|
|
|
2021-12-30 23:52:36 +00:00
|
|
|
enum FurnaceGUIWarnings {
|
|
|
|
GUI_WARN_QUIT,
|
|
|
|
GUI_WARN_NEW,
|
|
|
|
GUI_WARN_OPEN
|
|
|
|
};
|
|
|
|
|
2021-12-14 09:45:44 +00:00
|
|
|
struct SelectionPoint {
|
|
|
|
int xCoarse, xFine;
|
|
|
|
int y;
|
2021-12-14 22:45:37 +00:00
|
|
|
SelectionPoint():
|
|
|
|
xCoarse(0), xFine(0), y(0) {}
|
2021-12-14 09:45:44 +00:00
|
|
|
};
|
|
|
|
|
2021-12-22 22:59:19 +00:00
|
|
|
enum ActionType {
|
2021-12-26 23:05:18 +00:00
|
|
|
GUI_ACTION_CHANGE_ORDER,
|
2021-12-24 23:27:55 +00:00
|
|
|
GUI_ACTION_PATTERN_EDIT,
|
|
|
|
GUI_ACTION_PATTERN_DELETE,
|
|
|
|
GUI_ACTION_PATTERN_PULL,
|
|
|
|
GUI_ACTION_PATTERN_PUSH,
|
|
|
|
GUI_ACTION_PATTERN_CUT,
|
|
|
|
GUI_ACTION_PATTERN_PASTE
|
2021-12-22 22:59:19 +00:00
|
|
|
};
|
|
|
|
|
2021-12-26 23:05:18 +00:00
|
|
|
struct UndoPatternData {
|
|
|
|
int chan, pat, row, col;
|
|
|
|
short oldVal, newVal;
|
|
|
|
UndoPatternData(int c, int p, int r, int co, short v1, short v2):
|
|
|
|
chan(c),
|
|
|
|
pat(p),
|
|
|
|
row(r),
|
2021-12-26 23:28:06 +00:00
|
|
|
col(co),
|
2021-12-26 23:05:18 +00:00
|
|
|
oldVal(v1),
|
|
|
|
newVal(v2) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct UndoOrderData {
|
|
|
|
int chan, ord;
|
|
|
|
unsigned char oldVal, newVal;
|
|
|
|
UndoOrderData(int c, int o, unsigned char v1, unsigned char v2):
|
|
|
|
chan(c),
|
|
|
|
ord(o),
|
|
|
|
oldVal(v1),
|
|
|
|
newVal(v2) {}
|
2021-12-22 22:59:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct UndoStep {
|
|
|
|
ActionType type;
|
2021-12-26 23:05:18 +00:00
|
|
|
SelectionPoint cursor, selStart, selEnd;
|
|
|
|
int order;
|
|
|
|
bool nibble;
|
|
|
|
int oldOrdersLen, newOrdersLen;
|
|
|
|
int oldPatLen, newPatLen;
|
|
|
|
std::vector<UndoOrderData> ord;
|
|
|
|
std::vector<UndoPatternData> pat;
|
2021-12-22 22:59:19 +00:00
|
|
|
};
|
|
|
|
|
2021-12-11 07:10:09 +00:00
|
|
|
class FurnaceGUI {
|
|
|
|
DivEngine* e;
|
|
|
|
|
2021-12-11 08:11:40 +00:00
|
|
|
SDL_Window* sdlWin;
|
|
|
|
SDL_Renderer* sdlRend;
|
|
|
|
|
2021-12-30 23:52:36 +00:00
|
|
|
String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName;
|
2021-12-15 05:37:27 +00:00
|
|
|
|
2022-01-18 04:34:29 +00:00
|
|
|
bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting;
|
2021-12-17 08:33:12 +00:00
|
|
|
|
|
|
|
FurnaceGUIFileDialogs curFileDialog;
|
2021-12-30 23:52:36 +00:00
|
|
|
FurnaceGUIWarnings warnAction;
|
2021-12-11 08:11:40 +00:00
|
|
|
|
|
|
|
int scrW, scrH;
|
|
|
|
|
|
|
|
double dpiScale;
|
|
|
|
|
2021-12-19 04:03:50 +00:00
|
|
|
int aboutScroll, aboutSin;
|
|
|
|
float aboutHue;
|
|
|
|
|
2021-12-11 08:11:40 +00:00
|
|
|
ImFont* mainFont;
|
2021-12-21 05:30:55 +00:00
|
|
|
ImFont* iconFont;
|
2021-12-11 08:11:40 +00:00
|
|
|
ImFont* patFont;
|
2021-12-19 04:03:50 +00:00
|
|
|
ImFont* bigFont;
|
2021-12-13 22:09:46 +00:00
|
|
|
ImVec4 uiColors[GUI_COLOR_MAX];
|
|
|
|
ImVec4 volColors[128];
|
2021-12-11 08:11:40 +00:00
|
|
|
|
2022-01-16 22:25:43 +00:00
|
|
|
struct Settings {
|
|
|
|
int mainFontSize, patFontSize, iconSize;
|
|
|
|
int audioEngine;
|
2022-01-16 22:38:52 +00:00
|
|
|
int audioQuality;
|
2022-01-16 22:25:43 +00:00
|
|
|
int arcadeCore;
|
|
|
|
int mainFont;
|
|
|
|
int patFont;
|
|
|
|
int audioRate;
|
|
|
|
int audioBufSize;
|
2022-01-19 23:04:07 +00:00
|
|
|
int patRowsBase;
|
|
|
|
int orderRowsBase;
|
2022-01-20 07:28:55 +00:00
|
|
|
int soloAction;
|
2022-01-20 07:53:59 +00:00
|
|
|
int pullDeleteBehavior;
|
2022-01-20 18:15:37 +00:00
|
|
|
int wrapHorizontal;
|
|
|
|
int wrapVertical;
|
2022-01-16 22:25:43 +00:00
|
|
|
unsigned int maxUndoSteps;
|
|
|
|
String mainFontPath;
|
|
|
|
String patFontPath;
|
|
|
|
|
|
|
|
Settings():
|
|
|
|
mainFontSize(18),
|
|
|
|
patFontSize(18),
|
|
|
|
iconSize(16),
|
|
|
|
audioEngine(DIV_AUDIO_SDL),
|
2022-01-16 22:38:52 +00:00
|
|
|
audioQuality(0),
|
2022-01-16 22:25:43 +00:00
|
|
|
arcadeCore(0),
|
|
|
|
mainFont(0),
|
|
|
|
patFont(0),
|
|
|
|
audioRate(44100),
|
|
|
|
audioBufSize(1024),
|
2022-01-19 23:04:07 +00:00
|
|
|
patRowsBase(0),
|
|
|
|
orderRowsBase(1),
|
2022-01-20 07:28:55 +00:00
|
|
|
soloAction(0),
|
2022-01-20 07:53:59 +00:00
|
|
|
pullDeleteBehavior(1),
|
2022-01-20 18:15:37 +00:00
|
|
|
wrapHorizontal(0),
|
|
|
|
wrapVertical(0),
|
2022-01-16 22:25:43 +00:00
|
|
|
maxUndoSteps(100),
|
|
|
|
mainFontPath(""),
|
|
|
|
patFontPath("") {}
|
|
|
|
} settings;
|
2021-12-20 03:51:02 +00:00
|
|
|
|
2021-12-19 21:01:24 +00:00
|
|
|
char finalLayoutPath[4096];
|
2021-12-19 08:16:24 +00:00
|
|
|
|
2022-01-20 07:28:55 +00:00
|
|
|
int curIns, curWave, curSample, curOctave, oldRow, oldOrder, oldOrder1, editStep, exportLoops, soloChan, soloTimeout, orderEditMode, orderCursor;
|
2021-12-15 22:32:08 +00:00
|
|
|
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
2021-12-20 03:51:02 +00:00
|
|
|
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
|
2022-01-13 06:03:57 +00:00
|
|
|
bool mixerOpen;
|
2022-01-20 07:11:03 +00:00
|
|
|
SelectionPoint selStart, selEnd, cursor;
|
|
|
|
bool selecting, curNibble, orderNibble, extraChannelButtons, followOrders, followPattern, changeAllOrders;
|
2021-12-14 22:45:37 +00:00
|
|
|
FurnaceGUIWindows curWindow;
|
|
|
|
|
2022-01-20 06:32:16 +00:00
|
|
|
struct ActiveNote {
|
|
|
|
int chan;
|
|
|
|
int note;
|
|
|
|
ActiveNote(int c, int n):
|
|
|
|
chan(c),
|
|
|
|
note(n) {}
|
|
|
|
};
|
|
|
|
std::vector<ActiveNote> activeNotes;
|
2021-12-28 23:23:57 +00:00
|
|
|
|
2022-01-20 05:07:53 +00:00
|
|
|
bool wavePreviewOn;
|
|
|
|
SDL_Scancode wavePreviewKey;
|
|
|
|
int wavePreviewNote;
|
|
|
|
|
2022-01-20 21:51:31 +00:00
|
|
|
bool samplePreviewOn;
|
|
|
|
SDL_Scancode samplePreviewKey;
|
|
|
|
int samplePreviewNote;
|
|
|
|
|
2022-01-17 19:53:46 +00:00
|
|
|
std::map<SDL_Scancode,int> noteKeys;
|
2021-12-14 22:45:37 +00:00
|
|
|
std::map<SDL_Keycode,int> valueKeys;
|
2021-12-11 21:44:02 +00:00
|
|
|
|
2021-12-12 23:19:43 +00:00
|
|
|
int arpMacroScroll;
|
|
|
|
|
2021-12-12 09:21:09 +00:00
|
|
|
ImVec2 macroDragStart;
|
|
|
|
ImVec2 macroDragAreaSize;
|
2022-01-21 07:54:52 +00:00
|
|
|
unsigned char* macroDragCTarget;
|
2021-12-12 09:21:09 +00:00
|
|
|
int* macroDragTarget;
|
|
|
|
int macroDragLen;
|
|
|
|
int macroDragMin, macroDragMax;
|
2022-01-21 06:56:30 +00:00
|
|
|
int macroDragLastX, macroDragLastY;
|
|
|
|
int macroDragBitOff;
|
2022-01-21 22:00:28 +00:00
|
|
|
int macroDragScroll;
|
2022-01-21 06:56:30 +00:00
|
|
|
bool macroDragBitMode;
|
|
|
|
bool macroDragInitialValueSet;
|
|
|
|
bool macroDragInitialValue;
|
2022-01-21 07:54:52 +00:00
|
|
|
bool macroDragChar;
|
2021-12-12 09:21:09 +00:00
|
|
|
bool macroDragActive;
|
|
|
|
|
|
|
|
ImVec2 macroLoopDragStart;
|
|
|
|
ImVec2 macroLoopDragAreaSize;
|
|
|
|
signed char* macroLoopDragTarget;
|
|
|
|
int macroLoopDragLen;
|
|
|
|
bool macroLoopDragActive;
|
|
|
|
|
2021-12-18 22:54:26 +00:00
|
|
|
ImVec2 waveDragStart;
|
|
|
|
ImVec2 waveDragAreaSize;
|
|
|
|
int* waveDragTarget;
|
|
|
|
int waveDragLen;
|
|
|
|
int waveDragMin, waveDragMax;
|
|
|
|
bool waveDragActive;
|
|
|
|
|
2021-12-24 03:14:59 +00:00
|
|
|
float nextScroll, nextAddScroll;
|
|
|
|
|
|
|
|
ImVec2 patWindowPos, patWindowSize;
|
2021-12-13 22:09:46 +00:00
|
|
|
|
2021-12-26 23:05:18 +00:00
|
|
|
int oldOrdersLen;
|
|
|
|
DivOrders oldOrders;
|
2022-01-08 06:57:37 +00:00
|
|
|
DivPattern* oldPat[128];
|
2021-12-24 23:27:55 +00:00
|
|
|
std::deque<UndoStep> undoHist;
|
|
|
|
std::deque<UndoStep> redoHist;
|
|
|
|
|
2021-12-15 22:32:08 +00:00
|
|
|
void updateWindowTitle();
|
2021-12-19 21:01:24 +00:00
|
|
|
void prepareLayout();
|
2021-12-15 22:32:08 +00:00
|
|
|
|
|
|
|
void drawEditControls();
|
2021-12-14 09:45:44 +00:00
|
|
|
void drawSongInfo();
|
|
|
|
void drawOrders();
|
|
|
|
void drawPattern();
|
2021-12-16 08:09:18 +00:00
|
|
|
void drawInsList();
|
2021-12-14 09:45:44 +00:00
|
|
|
void drawInsEdit();
|
2021-12-16 08:09:18 +00:00
|
|
|
void drawWaveList();
|
|
|
|
void drawWaveEdit();
|
|
|
|
void drawSampleList();
|
|
|
|
void drawSampleEdit();
|
2022-01-13 06:03:57 +00:00
|
|
|
void drawMixer();
|
2021-12-19 04:03:50 +00:00
|
|
|
void drawAbout();
|
2021-12-20 03:51:02 +00:00
|
|
|
void drawSettings();
|
|
|
|
|
2022-01-16 22:25:43 +00:00
|
|
|
void syncSettings();
|
2021-12-20 03:51:02 +00:00
|
|
|
void commitSettings();
|
2021-12-24 03:58:43 +00:00
|
|
|
void processDrags(int dragX, int dragY);
|
2021-12-14 09:45:44 +00:00
|
|
|
|
2021-12-14 22:45:37 +00:00
|
|
|
void startSelection(int xCoarse, int xFine, int y);
|
|
|
|
void updateSelection(int xCoarse, int xFine, int y);
|
|
|
|
void finishSelection();
|
|
|
|
|
2021-12-15 05:37:27 +00:00
|
|
|
void moveCursor(int x, int y);
|
2022-01-11 23:54:31 +00:00
|
|
|
void moveCursorTop();
|
|
|
|
void moveCursorBottom();
|
2021-12-14 22:45:37 +00:00
|
|
|
void editAdvance();
|
2021-12-26 23:05:18 +00:00
|
|
|
void prepareUndo(ActionType action);
|
|
|
|
void makeUndo(ActionType action);
|
2021-12-29 05:50:00 +00:00
|
|
|
void doSelectAll();
|
2021-12-15 05:37:27 +00:00
|
|
|
void doDelete();
|
2021-12-19 07:12:19 +00:00
|
|
|
void doPullDelete();
|
|
|
|
void doInsert();
|
2022-01-17 07:06:05 +00:00
|
|
|
void doTranspose(int amount);
|
2021-12-19 07:12:19 +00:00
|
|
|
void doCopy(bool cut);
|
|
|
|
void doPaste();
|
2021-12-26 23:05:18 +00:00
|
|
|
void doUndo();
|
|
|
|
void doRedo();
|
2021-12-14 22:45:37 +00:00
|
|
|
|
2022-01-20 06:32:16 +00:00
|
|
|
void play();
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
void previewNote(int refChan, int note);
|
|
|
|
void stopPreviewNote(SDL_Scancode scancode);
|
|
|
|
|
2021-12-14 22:45:37 +00:00
|
|
|
void keyDown(SDL_Event& ev);
|
|
|
|
void keyUp(SDL_Event& ev);
|
|
|
|
|
2021-12-17 08:33:12 +00:00
|
|
|
void openFileDialog(FurnaceGUIFileDialogs type);
|
2021-12-15 19:15:44 +00:00
|
|
|
int save(String path);
|
2021-12-15 05:37:27 +00:00
|
|
|
int load(String path);
|
2022-01-18 04:34:29 +00:00
|
|
|
void exportAudio(String path, DivAudioExportModes mode);
|
2021-12-15 05:37:27 +00:00
|
|
|
|
2021-12-30 23:52:36 +00:00
|
|
|
void showWarning(String what, FurnaceGUIWarnings type);
|
2021-12-21 04:20:30 +00:00
|
|
|
void showError(String what);
|
|
|
|
|
2021-12-11 07:10:09 +00:00
|
|
|
public:
|
2021-12-13 07:03:36 +00:00
|
|
|
const char* noteName(short note, short octave);
|
2021-12-19 07:12:19 +00:00
|
|
|
bool decodeNote(const char* what, short& note, short& octave);
|
2021-12-11 07:10:09 +00:00
|
|
|
void bindEngine(DivEngine* eng);
|
2021-12-20 03:51:02 +00:00
|
|
|
void updateScroll(int amount);
|
2021-12-24 03:14:59 +00:00
|
|
|
void addScroll(int amount);
|
2021-12-11 08:11:40 +00:00
|
|
|
bool loop();
|
2021-12-19 21:01:24 +00:00
|
|
|
bool finish();
|
2021-12-11 08:11:40 +00:00
|
|
|
bool init();
|
2021-12-11 07:10:09 +00:00
|
|
|
FurnaceGUI();
|
2021-12-11 21:44:02 +00:00
|
|
|
};
|