You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
394 lines
19 KiB
394 lines
19 KiB
2 years ago
|
//Standard lib
|
||
|
#include <stdlib.h> // atoi for commandline argument char to int
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
//Third party
|
||
|
#include "raylib.h"
|
||
|
#define RAYGUI_IMPLEMENTATION
|
||
|
#include "raygui.h" // Required for GUI controls
|
||
|
|
||
|
#define GUI_FILE_DIALOG_IMPLEMENTATION
|
||
|
#include "gui_file_dialog.h"
|
||
|
|
||
|
|
||
|
//Our own files
|
||
|
#include "constants.h"
|
||
|
#include "programstate.h"
|
||
|
#include "gui.h"
|
||
|
#include "jackclient.h"
|
||
|
#include "camera.h"
|
||
|
#include "draw.h"
|
||
|
|
||
|
extern ProgramState programState;
|
||
|
extern Effect effects[NR_OF_EFFECTS];
|
||
|
|
||
|
static int screenWidth;
|
||
|
static int screenHeight;
|
||
|
static int center;
|
||
|
static int bottom;
|
||
|
static int remember; // Helper var: Did a value change so we need to instruct a gui reposition/draw?
|
||
|
static float alpha; //Helper var for colors.
|
||
|
static Vector2 panelScroll = { 0, 0 }; //This is the current state of scrolling. It must be declared outside the loop of course
|
||
|
|
||
|
static int currentColorIndex=0;
|
||
|
static int currentPaletteIndex=0; //see programstate.c setColorPalette()
|
||
|
|
||
|
static int columnX; //in pixel
|
||
|
static const int checkboxWidth = 24;
|
||
|
|
||
|
static bool colorChoiceEditMode = false;
|
||
|
static bool colorPaletteEditMode = false;
|
||
|
static bool pitchMarkerEditMode = false;
|
||
|
static bool pitchMaxEditMode = false;
|
||
|
static bool pitchMinEditMode= false;
|
||
|
|
||
|
static int configTab = layerIndex_notes; //index from enum in constants.h
|
||
|
|
||
|
static char fileNameToLoad[512] = { 0 };
|
||
|
static GuiFileDialogState fileDialogState;
|
||
|
|
||
|
//"Port 00;Port 01;Port 02;Port 03;Port 04;Port 05;Port 06;Port 07;Port 08;Port 09;Port 10;Port 11;Port 12;Port 13;Port 14;Port 15;Background;Panels;Marker"
|
||
|
static char colorsPortsString[VIS_PORTS*9 + 25];
|
||
|
|
||
|
void init_gui() {
|
||
|
for (int i=0; i<VIS_PORTS; i++) {
|
||
|
//Only works if VIS_PORTS is below 100 ports.
|
||
|
snprintf(colorsPortsString+strlen(colorsPortsString), sizeof(colorsPortsString), "Port %2d;", i); //9 because the substring is 9 chars.
|
||
|
}
|
||
|
snprintf(colorsPortsString+strlen(colorsPortsString), sizeof(colorsPortsString), "Background;Panels;Marker"); //Attach to the end
|
||
|
|
||
|
fileDialogState = InitGuiFileDialog(420, 310, GetWorkingDirectory(), false);
|
||
|
}
|
||
|
|
||
|
bool guiIsKeyPressed(int keyConstant) {
|
||
|
//Wrap Raylib function to only accept input when we want it.
|
||
|
if (programState.lockInput) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
return IsKeyPressed(keyConstant);
|
||
|
}
|
||
|
}
|
||
|
bool guiIsKeyDown(int keyConstant) {
|
||
|
//Wrap Raylib function to only accept input when we want it.
|
||
|
if (programState.lockInput) {
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
return IsKeyDown(keyConstant);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void mainLoop_gui() {
|
||
|
//bool pressed = IsMouseButtonPressed(0) || IsMouseButtonPressed(1); //0 left, 1 right //Registers no matter where you clicked
|
||
|
//if (pressed) { printf("click\n"); };
|
||
|
|
||
|
GuiUnlock();
|
||
|
programState.lockInput = false;
|
||
|
|
||
|
if (fileDialogState.SelectFilePressed)
|
||
|
{
|
||
|
// Load image file (if supported extension)
|
||
|
|
||
|
if (IsFileExtension(fileDialogState.fileNameText, ".png"))
|
||
|
{
|
||
|
strcpy(fileNameToLoad, TextFormat("%s/%s", fileDialogState.dirPathText, fileDialogState.fileNameText));
|
||
|
loadBackgroundImage(fileNameToLoad, true); //also saves the path in programstate
|
||
|
}
|
||
|
|
||
|
fileDialogState.SelectFilePressed = false;
|
||
|
}
|
||
|
|
||
|
GuiFileDialog(&fileDialogState); //does nothing if not activated. This needs to be processed before the GUI locks.
|
||
|
|
||
|
if (fileDialogState.fileDialogActive) {
|
||
|
GuiLock();
|
||
|
programState.lockInput = true;
|
||
|
}
|
||
|
|
||
|
//Shortcuts and toggles
|
||
|
bool controlDown=false;
|
||
|
if ( guiIsKeyDown(KEY_LEFT_CONTROL) || guiIsKeyDown(KEY_RIGHT_CONTROL) ) {
|
||
|
controlDown = true;
|
||
|
}
|
||
|
|
||
|
if (controlDown && guiIsKeyPressed(KEY_S)) {
|
||
|
saveStateToFile();
|
||
|
}
|
||
|
|
||
|
if (guiIsKeyPressed(KEY_SPACE)){ toggleTransport(); }
|
||
|
if (guiIsKeyPressed(KEY_G) || guiIsKeyPressed(KEY_ESCAPE)) { programState.guiVisible = !programState.guiVisible; }
|
||
|
if (guiIsKeyPressed(KEY_B)){ programState.showPortBackground = !programState.showPortBackground; }
|
||
|
if (guiIsKeyPressed(KEY_P)){ programState.showPitchMarker = !programState.showPitchMarker; }
|
||
|
if (guiIsKeyPressed(KEY_N)){ programState.showConnectedPortnames = !programState.showConnectedPortnames; }
|
||
|
if (guiIsKeyPressed(KEY_C)){ programState.alwaysShowClock = !programState.alwaysShowClock; }
|
||
|
|
||
|
//Camera Controls
|
||
|
cameraMaybeZoom();
|
||
|
if (guiIsKeyPressed(KEY_R)){ cameraReset(); }
|
||
|
|
||
|
if (guiIsKeyDown(KEY_A)) { cameraLeft(); }
|
||
|
else if (guiIsKeyDown(KEY_D)) { cameraRight(); }
|
||
|
|
||
|
if (guiIsKeyDown(KEY_W)) { cameraUp(); }
|
||
|
else if (!controlDown && guiIsKeyDown(KEY_S)) { cameraDown(); }
|
||
|
|
||
|
if (guiIsKeyDown(KEY_Q)) { cameraRotateLeft(); }
|
||
|
else if (guiIsKeyDown(KEY_E)) { cameraRotateRight(); }
|
||
|
else if (guiIsKeyPressed(KEY_X)) { cameraRotate180(); }
|
||
|
|
||
|
|
||
|
//Undocumented because it is based on the current window size.
|
||
|
if (guiIsKeyPressed(KEY_F)){ ToggleFullscreen(); }
|
||
|
|
||
|
if (guiIsKeyPressed(KEY_M)){
|
||
|
programState.drawMode++;
|
||
|
if (programState.drawMode > 4) { programState.drawMode = 0;} //wrap around
|
||
|
programState.guiRedrawNeeded = true;
|
||
|
}
|
||
|
|
||
|
//Draw GUI Elements
|
||
|
//All position numbers are trial and error
|
||
|
//RayGUI draws and delievers the result in one ste. e.g. button clicked.
|
||
|
//The state of e.g. ComboBox index is given each time in the caller function.
|
||
|
//newState = GuiElement(RectPositionDimension, options, oldState);
|
||
|
|
||
|
if (programState.alwaysShowClock || programState.guiVisible) {
|
||
|
//DrawFPS(0,0); //Fugly!
|
||
|
screenWidth = GetScreenWidth(); //Changes on resize
|
||
|
screenHeight = GetScreenHeight(); //Changes on resize
|
||
|
center = screenWidth/2;
|
||
|
bottom = screenHeight - 2*SPACING;
|
||
|
//DrawText(programState.clockString, center, bottom-2*SPACING, 20, RAYWHITE); //text, x, y, int fontsize, color
|
||
|
DrawTextEx(GuiGetFont(), programState.clockString, (Vector2){center, bottom-2*SPACING}, 31, 1, RAYWHITE);
|
||
|
}
|
||
|
|
||
|
if (programState.guiVisible) {
|
||
|
|
||
|
//Clock is drawn outside of guiVisible with an individual check
|
||
|
|
||
|
//Transport Control Buttons
|
||
|
if (GuiButton((Rectangle){center-100-5, bottom, 100, HEIGHT}, "Rewind")) {
|
||
|
//No shortcut
|
||
|
seekToStart();
|
||
|
}
|
||
|
if (GuiButton((Rectangle){center, bottom, 205, HEIGHT}, "[Space] Play / Pause")) {
|
||
|
toggleTransport();
|
||
|
}
|
||
|
|
||
|
//Save
|
||
|
if (programState.filePath && programState.filePath[0] != '\0') {
|
||
|
if (GuiButton((Rectangle){ screenWidth-120, bottom-1*SPACING, 105, HEIGHT }, "[Ctrl+S] Save")) {
|
||
|
saveStateToFile();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Quit
|
||
|
programState.instructedToQuit = GuiButton((Rectangle){ screenWidth-120, bottom, 105, HEIGHT }, "Quit");
|
||
|
|
||
|
int row=1;
|
||
|
columnX = 10; //in pixel
|
||
|
|
||
|
//Configs for all layers
|
||
|
|
||
|
//Layer Config "Tabs" Panel
|
||
|
DrawRectangle(columnX, row*SPACING-5, 160+230, HEIGHT+10, (Color){ 35, 40, 47, 255 });
|
||
|
GuiLabel((Rectangle){ columnX+checkboxWidth, row*SPACING, 105, HEIGHT }, "Show Config for"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
configTab = GuiComboBox((Rectangle){ 160, row*SPACING, 200, HEIGHT }, "Music Layer;Effects;Sprites;General", configTab);
|
||
|
row++;
|
||
|
|
||
|
//Tab for each Layer. Begin at row=2
|
||
|
if (configTab == layerIndex_notes) {
|
||
|
|
||
|
remember = programState.showDrawMode;
|
||
|
programState.showDrawMode = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "Enable Note Layer", programState.showDrawMode);
|
||
|
if (remember != programState.showDrawMode) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
remember = programState.drawMode;
|
||
|
GuiLabel((Rectangle){ columnX+checkboxWidth, row*SPACING, 105, HEIGHT }, "[M] Note Layer Mode"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
programState.drawMode = GuiComboBox((Rectangle){ 200, row*SPACING, 130, HEIGHT }, "Horizontal;Vertical;Grid;Meterbridge;Port Shapes;", programState.drawMode); //These need to be manually synced to draw.c drawFunctions[]
|
||
|
if (remember != programState.drawMode) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
//Show Port Background Checkbox
|
||
|
programState.showPortBackground = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "[B] Port Background", programState.showPortBackground);
|
||
|
|
||
|
row++;
|
||
|
|
||
|
//Show Unconnected Port Background Checkbox
|
||
|
programState.showPortBackgroundForUnconnected = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "Draw unconnected Port Background", programState.showPortBackgroundForUnconnected);
|
||
|
|
||
|
row++;
|
||
|
|
||
|
//Pitch Marker
|
||
|
programState.showPitchMarker = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "[P] Pitch Marker", programState.showPitchMarker);
|
||
|
remember = programState.pitchMarkerValue;
|
||
|
if (GuiSpinner((Rectangle){ 200, row*SPACING, 80, HEIGHT }, "", &programState.pitchMarkerValue, 0, 127, pitchMarkerEditMode)) pitchMarkerEditMode = !pitchMarkerEditMode; // bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||
|
//Bug in raygui. If edit mode for spinner is true the max check is not done.
|
||
|
if (programState.pitchMarkerValue > 127) {programState.pitchMarkerValue=127;}
|
||
|
if (programState.pitchMarkerValue < 0) {programState.pitchMarkerValue=0;}
|
||
|
if (remember != programState.pitchMarkerValue) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
// FadeOut Mode
|
||
|
GuiLabel((Rectangle){ columnX+checkboxWidth, row*SPACING, 105, HEIGHT }, "Fade Out Mode"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
programState.fadeOutMode = GuiComboBox((Rectangle){ 200, row*SPACING, 150, HEIGHT }, "Fixed;Tempo (bpm);Off", programState.fadeOutMode); //This needs to be manually synced to programState options
|
||
|
|
||
|
if (programState.fadeOutMode == 0) {
|
||
|
GuiSpinner((Rectangle){ 75+220+120, row*SPACING, 80, HEIGHT }, "Factor", &programState.fadeOutFactor, 1, 9, false); // bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||
|
//Bug in raygui. If edit mode for spinner is true the max check is not done.
|
||
|
if (programState.fadeOutFactor > 9) {programState.fadeOutFactor=9;}
|
||
|
if (programState.fadeOutFactor < 1) {programState.fadeOutFactor=1;}
|
||
|
}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
// Show Port Names
|
||
|
programState.showConnectedPortnames = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "[N] Show Connected Port Names", programState.showConnectedPortnames);
|
||
|
row++;
|
||
|
programState.includeClientInPortNameDisplay = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "Include Client in Port Names", programState.includeClientInPortNameDisplay);
|
||
|
|
||
|
row++;
|
||
|
|
||
|
|
||
|
|
||
|
//Pitch Range Min
|
||
|
GuiLabel((Rectangle){ columnX+checkboxWidth, row*SPACING, 105, HEIGHT }, "Pitch Range Minimum"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
remember = programState.pitchMin;
|
||
|
if (GuiSpinner((Rectangle){ 200, row*SPACING, 80, HEIGHT }, "", &programState.pitchMin, 0, 127, pitchMinEditMode)) pitchMinEditMode = !pitchMinEditMode; // bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||
|
//Bug in raygui. If edit mode for spinner is true the max check is not done.
|
||
|
if (programState.pitchMin > 127) {programState.pitchMin=127;}
|
||
|
if (programState.pitchMin < 0) {programState.pitchMin=0;}
|
||
|
if (remember != programState.pitchMin) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
//Pitch Range Max
|
||
|
GuiLabel((Rectangle){ columnX+checkboxWidth, row*SPACING, 105, HEIGHT }, "Pitch Range Maximum"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
remember = programState.pitchMax;
|
||
|
if (GuiSpinner((Rectangle){ 200, row*SPACING, 80, HEIGHT }, "", &programState.pitchMax, 0, 127, pitchMaxEditMode)) pitchMaxEditMode = !pitchMaxEditMode; // bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||
|
//Bug in raygui. If edit mode for spinner is true the max check is not done.
|
||
|
if (programState.pitchMax > 127) {programState.pitchMax=127;}
|
||
|
if (programState.pitchMax < 0) {programState.pitchMax=0;}
|
||
|
if (remember != programState.pitchMax) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
|
||
|
//Second Column
|
||
|
////////////////
|
||
|
columnX=400;
|
||
|
|
||
|
|
||
|
//NOTE: GuiDropdownBox must draw after any other control that can be covered on unfolding
|
||
|
//Therefore no automatic rows
|
||
|
GuiLabel((Rectangle){ columnX, 2*SPACING, 105, HEIGHT }, "Color for");
|
||
|
GuiLabel((Rectangle){ columnX, 5*SPACING, 105, HEIGHT }, "Set Palette");
|
||
|
remember = currentPaletteIndex;
|
||
|
if (GuiDropdownBox((Rectangle){ columnX, 5*SPACING, 130, HEIGHT }, "Default;Random;Grayscale", ¤tPaletteIndex, colorPaletteEditMode)) { colorPaletteEditMode = !colorPaletteEditMode; }
|
||
|
if (remember != currentPaletteIndex) { setColorPalette(currentPaletteIndex);}
|
||
|
//Draw last in this column
|
||
|
if (GuiDropdownBox((Rectangle){ columnX, 3*SPACING, 130, HEIGHT }, colorsPortsString, ¤tColorIndex, colorChoiceEditMode)) colorChoiceEditMode = !colorChoiceEditMode;
|
||
|
|
||
|
//Third Column
|
||
|
////////////////
|
||
|
row = 2;
|
||
|
columnX=550;
|
||
|
|
||
|
row++; alpha = GuiColorBarAlpha((Rectangle){ columnX, row*SPACING, 200, HEIGHT }, (float)programState.colors[currentColorIndex].a/255.0f);
|
||
|
programState.colors[currentColorIndex] = Fade(programState.colors[currentColorIndex], alpha);
|
||
|
row++; programState.colors[currentColorIndex] = GuiColorPicker((Rectangle){ columnX, row*SPACING, 196, 192 }, programState.colors[currentColorIndex]);
|
||
|
char colorString[24];
|
||
|
sprintf(colorString, "R%i G%i B%i A%i", programState.colors[currentColorIndex].r, programState.colors[currentColorIndex].g, programState.colors[currentColorIndex].b, programState.colors[currentColorIndex].a);
|
||
|
GuiLabel((Rectangle){ columnX, row*SPACING+190, 105, HEIGHT }, colorString);
|
||
|
|
||
|
|
||
|
//Fourth Column
|
||
|
////////////////
|
||
|
|
||
|
row = 2;
|
||
|
columnX=850;
|
||
|
|
||
|
//Show keys for camera control
|
||
|
GuiLabel((Rectangle){ columnX, row*SPACING, 105, HEIGHT }, "Camera Controls");
|
||
|
row++; GuiLabel((Rectangle){ columnX, row*SPACING, 105, HEIGHT }, "[W][A][S][D] Pan");
|
||
|
row++; GuiLabel((Rectangle){ columnX, row*SPACING, 105, HEIGHT }, "[Q][E][X] Rotate");
|
||
|
row++; GuiLabel((Rectangle){ columnX, row*SPACING, 105, HEIGHT }, "[R] Reset");
|
||
|
|
||
|
row++;
|
||
|
|
||
|
//Help Label 40 per with 80 characters in the top right corner.
|
||
|
GuiLabel((Rectangle){ screenWidth-450, 1*SPACING, 105, HEIGHT }, "Mode Help"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
Rectangle panelRec = { screenWidth-450, 2*SPACING, 410, 300 }; //What the user sees
|
||
|
Rectangle panelContentRec = {0, 0, 400, 500 }; //content, bigger than panelRec
|
||
|
Rectangle helpText = GuiScrollPanel(panelRec, panelContentRec, &panelScroll); //Rectangle GuiScrollPanel(Rectangle bounds, Rectangle content, Vector2 *scroll);
|
||
|
BeginScissorMode(helpText.x, helpText.y, helpText.width, helpText.height); // Begin scissor mode (define screen area for following drawing)
|
||
|
//GuiLabelColor((Rectangle){ panelRec.x + panelScroll.x, panelRec.y + panelScroll.y, panelContentRec.width, panelContentRec.height }, "Hallo Leute hier ist\nEin schöner Text für euch. Cool!\nUnd noch ne Zeile.", BLACK); // void GuiLabelColor(Rectangle bounds, const char *text, Color color);
|
||
|
GuiLabelColor((Rectangle){ panelRec.x + panelScroll.x, -4.5*SPACING + panelScroll.y, panelContentRec.width, panelContentRec.height }, programState.modeDescription, RAYWHITE); // void GuiLabelColor(Rectangle bounds, const char *text, Color color);
|
||
|
EndScissorMode();
|
||
|
|
||
|
}
|
||
|
|
||
|
//Effect Layer
|
||
|
else if (configTab == layerIndex_effects) {
|
||
|
|
||
|
//Show BG Layer Switch
|
||
|
remember = programState.showEffectLayer;
|
||
|
programState.showEffectLayer = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "Enable Effects", programState.showEffectLayer);
|
||
|
if (remember != programState.showEffectLayer) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
|
||
|
for (int i=0; i<NR_OF_EFFECTS; i++) {
|
||
|
//Enabled
|
||
|
remember =effects[i].enabled;
|
||
|
effects[i].enabled = GuiCheckBox((Rectangle){ columnX+10, row*SPACING, 20, HEIGHT }, effects[i].name, effects[i].enabled);
|
||
|
if (remember != effects[i].enabled) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
//Foreground
|
||
|
effects[i].foreground = GuiCheckBox((Rectangle){ columnX+150, row*SPACING, 20, HEIGHT }, "in foreground", effects[i].foreground);
|
||
|
|
||
|
//Opacity
|
||
|
effects[i].opacity = GuiColorBarAlpha((Rectangle){ columnX+300, row*SPACING, 100, HEIGHT }, effects[i].opacity);
|
||
|
|
||
|
//Speed
|
||
|
effects[i].speed = GuiSlider((Rectangle){ columnX+460, row*SPACING, 100, HEIGHT }, "Speed", TextFormat("x%i", effects[i].speed), effects[i].speed, -4, 4);
|
||
|
|
||
|
//Size
|
||
|
effects[i].size = GuiSlider((Rectangle){ columnX+660, row*SPACING, 100, HEIGHT }, "Size", TextFormat("%i", effects[i].size), effects[i].size, 1, 8);
|
||
|
|
||
|
row++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//General Config
|
||
|
else if (configTab == layerIndex_count) {
|
||
|
// Show Clock even when GUI is not visible
|
||
|
programState.alwaysShowClock = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "[C] Clock always visible", programState.alwaysShowClock);
|
||
|
|
||
|
row++;
|
||
|
|
||
|
remember = programState.showBackgroundImageLayer;
|
||
|
programState.showBackgroundImageLayer = GuiCheckBox((Rectangle){ columnX, row*SPACING, 20, HEIGHT }, "Enable Background Image", programState.showBackgroundImageLayer);
|
||
|
if (remember != programState.showBackgroundImageLayer) { programState.guiRedrawNeeded = true;}
|
||
|
|
||
|
row++;
|
||
|
|
||
|
if (GuiButton((Rectangle){ columnX, row*SPACING, 205, HEIGHT}, "Open Image")) {
|
||
|
fileDialogState.fileDialogActive = true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|