102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
ui.c
Go to the documentation of this file.
1#include <dttr_imgui.h>
2#include <dttr_loader_ui.h>
3#include <dttr_sdl.h>
4
5#include <stdbool.h>
6#include <stdio.h>
7
8#define DTTR_LOADER_UI_WINDOW_W 560
9#define DTTR_LOADER_UI_WINDOW_H 190
10#define DTTR_LOADER_UI_BUTTON_W 160.0f
11#define DTTR_LOADER_UI_BUTTON_H 28.0f
12#define DTTR_LOADER_UI_BUTTON_SPACING 8.0f
13#define DTTR_LOADER_UI_TEXT_PADDING_X 18.0f
14#define DTTR_LOADER_UI_TEXT_PADDING_Y 16.0f
15
16#ifndef DTTR_VERSION
17#define DTTR_VERSION "unknown"
18#endif
19
20static const char *const WINDOW_TITLE = "DttR: Specify Game Files";
21static const char *const HEADER_TITLE = "102 Patches: Detours to the Rescue!";
22static const char *const GAME_SOURCE_MESSAGE
23 = "Select either a directory containing the 102 Dalmatians: Puppies to the Rescue "
24 "files, the original game disc, or an ISO image.";
25static const char *const ERROR_TITLE = "DttR: Error";
26
28 const SDL_MessageBoxButtonData buttons[] = {
29 {0, DTTR_LOADER_UI_CHOICE_BROWSE_FOLDER, "Open Directory"},
30 {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
32 "Open ISO"},
33 };
34
35 const SDL_MessageBoxData msgbox = {
36 .flags = SDL_MESSAGEBOX_INFORMATION,
37 .window = NULL,
38 .title = WINDOW_TITLE,
39 .message = GAME_SOURCE_MESSAGE,
40 .numbuttons = 2,
41 .buttons = buttons,
42 };
43
44 int choice_id = DTTR_LOADER_UI_CHOICE_EXIT;
45 if (!DTTR_SDL_ShowMessageBox(&msgbox, &choice_id)) {
47 }
48
49 return DTTR_LoaderUI_ChoiceFromID(choice_id);
50}
51
55
56static float button_row_width(const DTTR_ImGuiDialogContext *ctx, size_t button_count) {
57 if (button_count == 0) {
58 return 0.0f;
59 }
60
61 const float button_width = DTTR_ImGuiDialog_ScaledFloat(ctx, DTTR_LOADER_UI_BUTTON_W);
62 return (button_width * (float)button_count)
63 + (button_spacing(ctx) * (float)(button_count - 1));
64}
65
72
75 const char *id,
76 const char *label,
78 DTTR_LoaderUIChoice *result,
79 bool *running
80) {
81 if (!DTTR_ImGuiDialog_Button(ctx, id, label, button_size(ctx))) {
82 return false;
83 }
84
85 *result = choice;
86 *running = false;
87 return true;
88}
89
90static bool draw_disc_button(
92 size_t disc_index,
93 const DTTR_LoaderUIDiscCandidate *disc_candidates,
94 DTTR_LoaderUIChoice *result,
95 bool *running
96) {
97 igPushID_Int((int)disc_index);
98 const bool selected = draw_source_button(
99 ctx,
100 "##disc",
101 disc_candidates[disc_index].label,
103 result,
104 running
105 );
106 igPopID();
107 return selected;
108}
109
111 igSameLine(0.0f, button_spacing(ctx));
112}
113
114static size_t clamp_disc_candidate_count(size_t disc_candidate_count) {
115 if (disc_candidate_count > DTTR_LOADER_UI_MAX_DISC_CANDIDATES) {
117 }
118
119 return disc_candidate_count;
120}
121
124 DTTR_LoaderUIChoice *result,
125 bool *running
126) {
128 ctx,
129 "##open_directory",
130 "Open Directory",
132 result,
133 running
134 )) {
135 return;
136 }
137
140 ctx,
141 "##open_iso",
142 "Open ISO",
144 result,
145 running
146 );
147}
148
151 const DTTR_LoaderUIDiscCandidate *disc_candidates,
152 size_t disc_candidate_count,
153 DTTR_LoaderUIChoice *result,
154 bool *running
155) {
156 size_t disc_index = 0;
157 const size_t first_row_buttons = disc_candidate_count > 0 ? 3 : 2;
159
160 if (disc_candidate_count > 0) {
161 draw_disc_button(ctx, disc_index++, disc_candidates, result, running);
163 }
164
165 draw_browse_buttons(ctx, result, running);
166
167 while (disc_index < disc_candidate_count && *running) {
168 const size_t remaining = disc_candidate_count - disc_index;
169 const size_t row_count = remaining < 3 ? remaining : 3;
171
172 for (size_t col = 0; col < row_count && *running; col++, disc_index++) {
173 if (col > 0) {
175 }
176
177 draw_disc_button(ctx, disc_index, disc_candidates, result, running);
178 }
179 }
180}
181
183 const DTTR_LoaderUIDiscCandidate *disc_candidates,
184 size_t disc_candidate_count
185) {
187
189 &ctx,
193 )) {
195 }
196
197 disc_candidate_count = disc_candidates
198 ? clamp_disc_candidate_count(disc_candidate_count)
199 : 0;
200
202 bool running = true;
203 while (running) {
207
208 if (DTTR_ImGuiDialog_BeginRoot(&ctx, WINDOW_TITLE, ImGuiWindowFlags_None)) {
210 igSeparator();
212 &ctx,
216 );
218 &ctx,
219 disc_candidates,
220 disc_candidate_count,
221 &result,
222 &running
223 );
225 }
226
228
230 }
231
233 return result;
234}
235
236void DTTR_LoaderUI_ShowError(const char *title, const char *message) {
237 const char *window_title = title ? title : ERROR_TITLE;
238 const char *safe_message = message ? message : "";
239
240 if (DTTR_ImGui_ErrorShow(window_title, safe_message)) {
241 return;
242 }
243
244 DTTR_SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, window_title, safe_message, NULL);
245}
DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 void void void void DWORD f DTTR_Graphics_COM_Direct3DDevice7 DWORD idx float
void void * ctx
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
void DTTR_ImGuiDialog_End(DTTR_ImGuiDialogContext *ctx)
void DTTR_ImGuiDialog_DrawHeader(const DTTR_ImGuiDialogContext *ctx, const char *title, const char *version)
bool DTTR_ImGui_ErrorShow(const char *title, const char *message)
void DTTR_ImGuiDialog_CenterNextItem(float item_width)
void DTTR_ImGuiDialog_Render(DTTR_ImGuiDialogContext *ctx)
bool DTTR_ImGuiDialog_RefreshScale(DTTR_ImGuiDialogContext *ctx)
bool DTTR_ImGuiDialog_BeginRoot(DTTR_ImGuiDialogContext *ctx, const char *title, ImGuiWindowFlags flags)
float DTTR_ImGuiDialog_ScaledFloat(const DTTR_ImGuiDialogContext *ctx, float value)
void DTTR_ImGuiDialog_DrawPaddedText(const DTTR_ImGuiDialogContext *ctx, const char *message, float padding_x, float padding_y)
void DTTR_ImGuiDialog_ProcessEvents(const DTTR_ImGuiDialogContext *ctx, bool *running)
bool DTTR_ImGuiDialog_Button(const DTTR_ImGuiDialogContext *ctx, const char *id, const char *label, ImVec2_c size)
void DTTR_ImGuiDialog_EndRoot()
void DTTR_ImGuiDialog_NewFrame(const DTTR_ImGuiDialogContext *ctx)
void DTTR_ImGuiDialog_FitWindowToContent(DTTR_ImGuiDialogContext *ctx, int width, float padding_y)
bool DTTR_ImGuiDialog_Begin(DTTR_ImGuiDialogContext *ctx, const char *title, int width, int height)
@ DTTR_LOADER_UI_MAX_DISC_CANDIDATES
DTTR_LoaderUIChoice DTTR_LoaderUI_ChoiceFromID(int choice_id)
Definition ui_logic.c:21
DTTR_LoaderUIChoice
@ DTTR_LOADER_UI_CHOICE_BROWSE_ISO
@ DTTR_LOADER_UI_CHOICE_BROWSE_FOLDER
@ DTTR_LOADER_UI_CHOICE_EXIT
DTTR_LoaderUIChoice DTTR_LoaderUI_DiscChoiceForIndex(size_t index)
Definition ui_logic.c:34
bool DTTR_SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
Definition sdl.c:135
bool DTTR_SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char *title, const char *message, SDL_Window *window)
Definition sdl.c:121
static sds window_title
Definition graphics.c:34
#define DTTR_VERSION
static const char *const HEADER_TITLE
static const char *const ERROR_TITLE
static float button_spacing(const DTTR_ImGuiDialogContext *ctx)
Definition ui.c:52
DTTR_LoaderUIChoice DTTR_LoaderUI_ChooseGameSource(const DTTR_LoaderUIDiscCandidate *disc_candidates, size_t disc_candidate_count)
Definition ui.c:182
static bool draw_disc_button(const DTTR_ImGuiDialogContext *ctx, size_t disc_index, const DTTR_LoaderUIDiscCandidate *disc_candidates, DTTR_LoaderUIChoice *result, bool *running)
Definition ui.c:90
static void draw_browse_buttons(const DTTR_ImGuiDialogContext *ctx, DTTR_LoaderUIChoice *result, bool *running)
Definition ui.c:122
#define DTTR_LOADER_UI_BUTTON_W
Definition ui.c:10
static void draw_source_buttons(const DTTR_ImGuiDialogContext *ctx, const DTTR_LoaderUIDiscCandidate *disc_candidates, size_t disc_candidate_count, DTTR_LoaderUIChoice *result, bool *running)
Definition ui.c:149
static float button_row_width(const DTTR_ImGuiDialogContext *ctx, size_t button_count)
Definition ui.c:56
static size_t clamp_disc_candidate_count(size_t disc_candidate_count)
Definition ui.c:114
#define DTTR_LOADER_UI_WINDOW_W
Definition ui.c:8
#define DTTR_LOADER_UI_BUTTON_H
Definition ui.c:11
#define DTTR_LOADER_UI_TEXT_PADDING_Y
Definition ui.c:14
static const char *const GAME_SOURCE_MESSAGE
Definition ui.c:23
#define DTTR_LOADER_UI_BUTTON_SPACING
Definition ui.c:12
#define DTTR_LOADER_UI_TEXT_PADDING_X
Definition ui.c:13
static void same_button_row(const DTTR_ImGuiDialogContext *ctx)
Definition ui.c:110
static ImVec2_c button_size(const DTTR_ImGuiDialogContext *ctx)
Definition ui.c:66
static bool draw_source_button(const DTTR_ImGuiDialogContext *ctx, const char *id, const char *label, DTTR_LoaderUIChoice choice, DTTR_LoaderUIChoice *result, bool *running)
Definition ui.c:73
static const char *const WINDOW_TITLE
Definition ui.c:20
void DTTR_LoaderUI_ShowError(const char *title, const char *message)
Definition ui.c:236
static DTTR_LoaderUIChoice native_choose_game_source()
Definition ui.c:27
#define DTTR_LOADER_UI_WINDOW_H
Definition ui.c:9