diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj
index f42b2aeae..b61021a56 100644
--- a/build-windows-visual-studio/sm64ex.vcxproj
+++ b/build-windows-visual-studio/sm64ex.vcxproj
@@ -3948,6 +3948,8 @@
+
+
@@ -4017,6 +4019,7 @@
+
@@ -4370,6 +4373,8 @@
+
+
@@ -4388,6 +4393,7 @@
+
diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters
index 24040d78d..09a11b39b 100644
--- a/build-windows-visual-studio/sm64ex.vcxproj.filters
+++ b/build-windows-visual-studio/sm64ex.vcxproj.filters
@@ -15189,6 +15189,15 @@
Source Files\src\pc\djui\component\compound
+
+ Source Files\src\pc\djui\panel
+
+
+ Source Files\src\pc\djui\panel
+
+
+ Source Files\src\pc\utils
+
@@ -16198,5 +16207,14 @@
Source Files\src\pc\djui\component\compound
+
+ Source Files\src\pc\djui\panel
+
+
+ Source Files\src\pc\djui\panel
+
+
+ Source Files\src\pc\utils
+
\ No newline at end of file
diff --git a/src/pc/djui/djui.h b/src/pc/djui/djui.h
index e39003987..1e9e3a2d0 100644
--- a/src/pc/djui/djui.h
+++ b/src/pc/djui/djui.h
@@ -21,6 +21,7 @@
#include "djui_flow_layout.h"
#include "djui_panel_main.h"
+#include "djui_panel_quit.h"
extern struct DjuiRoot* gDjuiRoot;
diff --git a/src/pc/djui/djui_base.c b/src/pc/djui/djui_base.c
index 5ecfc5348..03db100d9 100644
--- a/src/pc/djui/djui_base.c
+++ b/src/pc/djui/djui_base.c
@@ -9,6 +9,10 @@ void djui_base_set_visible(struct DjuiBase* base, bool visible) {
base->visible = visible;
}
+void djui_base_set_enabled(struct DjuiBase* base, bool enabled) {
+ base->enabled = enabled;
+}
+
void djui_base_set_location(struct DjuiBase* base, f32 x, f32 y) {
base->x.value = x;
base->y.value = y;
@@ -150,7 +154,8 @@ void djui_base_compute(struct DjuiBase* base) {
comp->width = width;
comp->height = height;
- //djui_base_add_padding(base);
+ base->elem = base->comp;
+
djui_base_clip(base);
}
@@ -256,7 +261,9 @@ void djui_base_render(struct DjuiBase* base) {
if (!base->visible) { return; }
if (base->on_render_pre != NULL) {
- base->on_render_pre(base);
+ bool skipRender = false;
+ base->on_render_pre(base, &skipRender);
+ if (skipRender) { return; }
}
struct DjuiBaseRect* comp = &base->comp;
@@ -283,13 +290,14 @@ void djui_base_render(struct DjuiBase* base) {
// render all children
struct DjuiBaseChild* child = base->child;
while (child != NULL) {
+ struct DjuiBaseChild* nextChild = child->next;
djui_base_render(child->base);
if (base->on_child_render != NULL) {
base->on_child_render(base, child->base);
}
- child = child->next;
+ child = nextChild;
}
}
@@ -298,13 +306,16 @@ void djui_base_destroy(struct DjuiBase* base) {
if (base->parent != NULL) {
struct DjuiBaseChild* child = base->parent->child;
struct DjuiBaseChild* lastChild = NULL;
+ struct DjuiBaseChild* nextChild = NULL;
while (child != NULL) {
+ nextChild = child->next;
+
if (child->base == base) {
// adjust linked list
if (lastChild == NULL) {
- base->parent->child = child->next;
+ base->parent->child = nextChild;
} else {
- lastChild->next = child->next;
+ lastChild->next = nextChild;
}
// deallocate child node
free(child);
@@ -314,18 +325,18 @@ void djui_base_destroy(struct DjuiBase* base) {
// iterate
lastChild = child;
- child = child->next;
+ child = nextChild;
}
}
// destroy all children and our linked list
struct DjuiBaseChild* child = base->child;
while (child != NULL) {
- struct DjuiBaseChild* nextChild = child;
+ struct DjuiBaseChild* nextChild = child->next;
child->base->parent = NULL;
djui_base_destroy(child->base);
free(child);
- child = nextChild->next;
+ child = nextChild;
}
// deallocate interactable
@@ -341,7 +352,8 @@ void djui_base_destroy(struct DjuiBase* base) {
void djui_base_init(struct DjuiBase* parent, struct DjuiBase* base, void(*render)(struct DjuiBase*), void (*destroy)(struct DjuiBase*)) {
memset(base, 0, sizeof(struct DjuiBase));
base->parent = parent;
- base->visible = true;
+ djui_base_set_visible(base, true);
+ djui_base_set_enabled(base, true);
djui_base_set_size(base, 64, 64);
djui_base_set_color(base, 255, 255, 255, 255);
base->render = render;
diff --git a/src/pc/djui/djui_base.h b/src/pc/djui/djui_base.h
index d2fc592dc..9aff2db7b 100644
--- a/src/pc/djui/djui_base.h
+++ b/src/pc/djui/djui_base.h
@@ -28,6 +28,7 @@ struct DjuiBase {
struct DjuiBase* parent;
struct DjuiBaseChild* child;
bool visible;
+ bool enabled;
struct DjuiScreenValue x;
struct DjuiScreenValue y;
struct DjuiScreenValue width;
@@ -38,16 +39,18 @@ struct DjuiBase {
struct DjuiBasePadding padding;
enum DjuiHAlign hAlign;
enum DjuiVAlign vAlign;
+ struct DjuiBaseRect elem;
struct DjuiBaseRect comp;
struct DjuiBaseRect clip;
struct DjuiInteractable* interactable;
void (*on_child_render)(struct DjuiBase*, struct DjuiBase*);
- void (*on_render_pre)(struct DjuiBase*);
+ void (*on_render_pre)(struct DjuiBase*, bool*);
void (*render)(struct DjuiBase*);
void (*destroy)(struct DjuiBase*);
};
void djui_base_set_visible(struct DjuiBase* base, bool visible);
+void djui_base_set_enabled(struct DjuiBase* base, bool enabled);
void djui_base_set_location(struct DjuiBase* base, f32 x, f32 y);
void djui_base_set_location_type(struct DjuiBase* base, enum DjuiScreenValueType xType, enum DjuiScreenValueType yType);
void djui_base_set_size(struct DjuiBase* base, f32 width, f32 height);
diff --git a/src/pc/djui/djui_flow_layout.c b/src/pc/djui/djui_flow_layout.c
index da886ec8c..f99d4cdb0 100644
--- a/src/pc/djui/djui_flow_layout.c
+++ b/src/pc/djui/djui_flow_layout.c
@@ -25,18 +25,18 @@ static void djui_flow_layout_on_child_render(struct DjuiBase* base, struct DjuiB
struct DjuiFlowLayout* layout = (struct DjuiFlowLayout*)base;
switch (layout->flowDirection) {
case DJUI_FLOW_DIR_DOWN:
- base->comp.y += (child->comp.height + layout->margin.value);
- base->comp.height -= (child->comp.height + layout->margin.value);
+ base->comp.y += (child->elem.height + layout->margin.value);
+ base->comp.height -= (child->elem.height + layout->margin.value);
break;
case DJUI_FLOW_DIR_UP:
- base->comp.height -= (child->comp.height + layout->margin.value);
+ base->comp.height -= (child->elem.height + layout->margin.value);
break;
case DJUI_FLOW_DIR_RIGHT:
- base->comp.x += (child->comp.width + layout->margin.value);
- base->comp.width -= (child->comp.width + layout->margin.value);
+ base->comp.x += (child->elem.width + layout->margin.value);
+ base->comp.width -= (child->elem.width + layout->margin.value);
break;
case DJUI_FLOW_DIR_LEFT:
- base->comp.width -= (child->comp.width + layout->margin.value);
+ base->comp.width -= (child->elem.width + layout->margin.value);
break;
}
}
diff --git a/src/pc/djui/djui_interactable.c b/src/pc/djui/djui_interactable.c
index 54a28b30d..64b8a38d3 100644
--- a/src/pc/djui/djui_interactable.c
+++ b/src/pc/djui/djui_interactable.c
@@ -7,6 +7,22 @@
struct DjuiBase* sHovered = NULL;
struct DjuiBase* sMouseDown = NULL;
+static bool djui_interactable_mouse_inside(struct DjuiBase* base) {
+ struct DjuiBaseRect* clip = &base->elem;
+ if (mouse_window_x < clip->x) { return false; }
+ if (mouse_window_x > clip->x + clip->width) { return false; }
+ if (mouse_window_y < clip->y) { return false; }
+ if (mouse_window_y > clip->y + clip->height) { return false; }
+ return true;
+}
+
+static void djui_interactable_on_click(struct DjuiBase* base) {
+ if (base == NULL) { return; }
+ if (base->interactable == NULL) { return; }
+ if (base->interactable->on_click == NULL) { return; }
+ base->interactable->on_click(base);
+}
+
static void djui_interactable_on_hover_begin(struct DjuiBase* base) {
if (base == NULL) { return; }
if (base->interactable == NULL) { return; }
@@ -39,18 +55,26 @@ static void djui_interactable_on_mouse_down_end(struct DjuiBase* base) {
if (base->interactable == NULL) { return; }
if (base->interactable->on_mouse_down_end == NULL) { return; }
base->interactable->on_mouse_down_end(base);
+
+ if (djui_interactable_mouse_inside(base)) {
+ djui_interactable_on_click(base);
+ }
}
static void djui_interactable_mouse_update_active(struct DjuiBase* base) {
if (!base->visible) { return; }
+ if (!base->enabled) { return; }
- struct DjuiBaseRect* clip = &base->clip;
- if (mouse_window_x < clip->x) { return; }
- if (mouse_window_x > clip->x + clip->width) { return; }
- if (mouse_window_y < clip->y) { return; }
- if (mouse_window_y > clip->y + clip->height) { return; }
+ static struct DjuiBase* insideParent = NULL;
- if (base->interactable != NULL) { sHovered = base; }
+ if (!djui_interactable_mouse_inside(base)) { return; }
+
+ if (base->interactable != NULL) {
+ sHovered = base;
+ insideParent = base;
+ } else if (insideParent == NULL) {
+ sHovered = NULL;
+ }
// check all children
struct DjuiBaseChild* child = base->child;
@@ -58,6 +82,10 @@ static void djui_interactable_mouse_update_active(struct DjuiBase* base) {
djui_interactable_mouse_update_active(child->base);
child = child->next;
}
+
+ if (insideParent == base) {
+ insideParent = NULL;
+ }
}
void djui_interactable_update(void) {
@@ -98,6 +126,7 @@ void djui_interactable_create(struct DjuiBase* base,
interactable->on_hover_end = on_hover_end;
interactable->on_mouse_down_begin = on_mouse_down_begin;
interactable->on_mouse_down_end = on_mouse_down_end;
+ interactable->on_click = NULL;
base->interactable = interactable;
}
\ No newline at end of file
diff --git a/src/pc/djui/djui_interactable.h b/src/pc/djui/djui_interactable.h
index 0b2b805e1..fcbf79f6d 100644
--- a/src/pc/djui/djui_interactable.h
+++ b/src/pc/djui/djui_interactable.h
@@ -4,10 +4,12 @@
#pragma pack(1)
struct DjuiInteractable {
+ bool enabled;
void (*on_hover_begin)(struct DjuiBase*);
void (*on_hover_end)(struct DjuiBase*);
void (*on_mouse_down_begin)(struct DjuiBase*);
void (*on_mouse_down_end)(struct DjuiBase*);
+ void (*on_click)(struct DjuiBase*);
};
void djui_interactable_update(void);
diff --git a/src/pc/djui/djui_panel_main.c b/src/pc/djui/djui_panel_main.c
index b423e932d..c491e850c 100644
--- a/src/pc/djui/djui_panel_main.c
+++ b/src/pc/djui/djui_panel_main.c
@@ -4,28 +4,29 @@ ALIGNED8 static u8 texture_title[] = {
#include "textures/segment2/custom_title.rgba32.inc.c"
};
+struct DjuiRect* gPanelMainMenu = NULL;
struct DjuiRect* sTitleContainer = NULL;
struct DjuiFlowLayout* sButtonContainer = NULL;
struct DjuiText* sVersionText = NULL;
-static void djui_panel_main_render_pre(struct DjuiBase* base) {
- sTitleContainer->base.height.value = sButtonContainer->base.clip.y - sTitleContainer->base.clip.y;
+static void djui_panel_main_render_pre(struct DjuiBase* base, bool* skipRender) {
+ sTitleContainer->base.height.value = sButtonContainer->base.clip.y - gPanelMainMenu->base.comp.y;
sVersionText->base.height.value = sTitleContainer->base.height.value;
}
void djui_panel_main_create(void) {
- struct DjuiRect* menuContainer = djui_rect_create(&gDjuiRoot->base);
- djui_base_set_size_type(&menuContainer->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE);
- djui_base_set_size(&menuContainer->base, 512.0f + (16 * 2.0f), 1.0f);
- djui_base_set_color(&menuContainer->base, 0, 0, 0, 230);
- djui_base_set_border_color(&menuContainer->base, 0, 0, 0, 200);
- djui_base_set_border_width(&menuContainer->base, 8);
- djui_base_set_padding(&menuContainer->base, 16, 16, 16, 16);
+ gPanelMainMenu = djui_rect_create(&gDjuiRoot->base);
+ djui_base_set_size_type(&gPanelMainMenu->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE);
+ djui_base_set_size(&gPanelMainMenu->base, 512.0f + (16 * 2.0f), 1.0f);
+ djui_base_set_color(&gPanelMainMenu->base, 0, 0, 0, 230);
+ djui_base_set_border_color(&gPanelMainMenu->base, 0, 0, 0, 200);
+ djui_base_set_border_width(&gPanelMainMenu->base, 8);
+ djui_base_set_padding(&gPanelMainMenu->base, 16, 16, 16, 16);
{
- sButtonContainer = djui_flow_layout_create(&menuContainer->base);
+ sButtonContainer = djui_flow_layout_create(&gPanelMainMenu->base);
djui_base_set_alignment(&sButtonContainer->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
djui_base_set_size_type(&sButtonContainer->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
- djui_base_set_size(&sButtonContainer->base, 1.0f, 292);
+ djui_base_set_size(&sButtonContainer->base, 1.0f, 64 * 4 + 16 * 3);
djui_base_set_color(&sButtonContainer->base, 0, 0, 0, 0);
djui_flow_layout_set_margin(sButtonContainer, 16);
djui_flow_layout_set_flow_direction(sButtonContainer, DJUI_FLOW_DIR_DOWN);
@@ -45,9 +46,11 @@ void djui_panel_main_create(void) {
struct DjuiButton* button4 = djui_button_create(&sButtonContainer->base, "Quit");
djui_base_set_size_type(&button4->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button4->base, 1.0f, 64);
+ button4->base.interactable->on_click = djui_panel_quit_open;
}
- sTitleContainer = djui_rect_create(&menuContainer->base);
+ sTitleContainer = djui_rect_create(&gPanelMainMenu->base);
+ djui_base_set_alignment(&sTitleContainer->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
djui_base_set_size_type(&sTitleContainer->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&sTitleContainer->base, 1.0f, 1.0f);
djui_base_set_color(&sTitleContainer->base, 0, 0, 0, 0);
@@ -59,12 +62,11 @@ void djui_panel_main_create(void) {
djui_base_set_alignment(&title->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
}
- sVersionText = djui_text_create(&menuContainer->base, "version - unst 5");
- djui_base_set_alignment(&sVersionText->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
+ sVersionText = djui_text_create(&gPanelMainMenu->base, "version - unst 5");
+ djui_base_set_alignment(&sVersionText->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
djui_base_set_size_type(&sVersionText->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&sVersionText->base, 1.0f, 1.0f);
djui_base_set_color(&sVersionText->base, 50, 50, 50, 255);
djui_text_set_alignment(sVersionText, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
}
-
}
diff --git a/src/pc/djui/djui_panel_main.h b/src/pc/djui/djui_panel_main.h
index 495ad48b9..1b30887a3 100644
--- a/src/pc/djui/djui_panel_main.h
+++ b/src/pc/djui/djui_panel_main.h
@@ -1,4 +1,6 @@
#pragma once
#include "djui.h"
+extern struct DjuiRect* gPanelMainMenu;
+
void djui_panel_main_create(void);
diff --git a/src/pc/djui/djui_panel_quit.c b/src/pc/djui/djui_panel_quit.c
new file mode 100644
index 000000000..de0362bd7
--- /dev/null
+++ b/src/pc/djui/djui_panel_quit.c
@@ -0,0 +1,89 @@
+#include "djui.h"
+#include "src/pc/utils/misc.h"
+
+struct DjuiRect* sPanelQuit = NULL;
+bool sOpening = false;
+bool sClosing = false;
+
+static void djui_panel_quit_render_pre(struct DjuiBase* base, bool* skipRender) {
+ float yMove = gPanelMainMenu->base.elem.height;
+ static float movement = 0;
+ if (sOpening) {
+ movement += yMove / 10.0f;
+ if (movement >= yMove) {
+ movement = yMove;
+ sOpening = false;
+ djui_base_set_enabled(&sPanelQuit->base, true);
+ }
+ } else if (sClosing) {
+ movement -= yMove / 10.0f;
+ if (movement <= 0) {
+ movement = 0;
+ sClosing = false;
+ djui_base_destroy(&sPanelQuit->base);
+ sPanelQuit = NULL;
+ *skipRender = true;
+ djui_base_set_enabled(&gPanelMainMenu->base, true);
+ gPanelMainMenu->base.y.value = 0;
+ return;
+ }
+ } else {
+ movement = yMove;
+ }
+ gPanelMainMenu->base.y.value = -yMove * smoothstep(0, yMove, movement);
+ sPanelQuit->base.y.value = gPanelMainMenu->base.elem.y + gPanelMainMenu->base.elem.height;
+}
+
+static void djui_panel_quit_yes(struct DjuiBase* base) {
+ exit(0);
+}
+
+static void djui_panel_quit_no(struct DjuiBase* base) {
+ sClosing = true;
+ djui_base_set_enabled(&sPanelQuit->base, false);
+}
+
+static void djui_panel_quit_create(void) {
+ sOpening = true;
+ sClosing = false;
+ sPanelQuit = djui_rect_create(&gDjuiRoot->base);
+ djui_base_set_size_type(&sPanelQuit->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE);
+ djui_base_set_size(&sPanelQuit->base, 512.0f + (16 * 2.0f), 1.0f);
+ djui_base_set_color(&sPanelQuit->base, 0, 0, 0, 230);
+ djui_base_set_border_color(&sPanelQuit->base, 0, 0, 0, 200);
+ djui_base_set_border_width(&sPanelQuit->base, 8);
+ djui_base_set_padding(&sPanelQuit->base, 16, 16, 16, 16);
+ djui_base_set_enabled(&sPanelQuit->base, false);
+ sPanelQuit->base.on_render_pre = djui_panel_quit_render_pre;
+ {
+ struct DjuiFlowLayout* quitContainer = djui_flow_layout_create(&sPanelQuit->base);
+ djui_base_set_alignment(&quitContainer->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
+ djui_base_set_size_type(&quitContainer->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
+ djui_base_set_size(&quitContainer->base, 1.0f, 64 * 3 + 16 * 2);
+ djui_base_set_color(&quitContainer->base, 0, 0, 0, 0);
+ djui_flow_layout_set_margin(quitContainer, 16);
+ djui_flow_layout_set_flow_direction(quitContainer, DJUI_FLOW_DIR_DOWN);
+ {
+ struct DjuiText* text = djui_text_create(&quitContainer->base, "Are you sure you want to quit?");
+ djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
+ djui_base_set_size(&text->base, 1.0f, 64);
+ djui_base_set_color(&text->base, 200, 200, 200, 255);
+ djui_text_set_alignment(text, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
+
+ struct DjuiButton* button1 = djui_button_create(&quitContainer->base, "Yes");
+ djui_base_set_size_type(&button1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
+ djui_base_set_size(&button1->base, 1.0f, 64);
+ button1->base.interactable->on_click = djui_panel_quit_yes;
+
+ struct DjuiButton* button2 = djui_button_create(&quitContainer->base, "No");
+ djui_base_set_size_type(&button2->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
+ djui_base_set_size(&button2->base, 1.0f, 64);
+ button2->base.interactable->on_click = djui_panel_quit_no;
+ }
+ }
+}
+
+void djui_panel_quit_open(struct DjuiBase* caller) {
+ djui_base_set_enabled(&gPanelMainMenu->base, false);
+ djui_panel_quit_create();
+}
\ No newline at end of file
diff --git a/src/pc/djui/djui_panel_quit.h b/src/pc/djui/djui_panel_quit.h
new file mode 100644
index 000000000..0b47f9a62
--- /dev/null
+++ b/src/pc/djui/djui_panel_quit.h
@@ -0,0 +1,4 @@
+#pragma once
+#include "djui.h"
+
+void djui_panel_quit_open(struct DjuiBase* caller);
diff --git a/src/pc/utils/misc.c b/src/pc/utils/misc.c
new file mode 100644
index 000000000..8314a4ad6
--- /dev/null
+++ b/src/pc/utils/misc.c
@@ -0,0 +1,8 @@
+#include "misc.h"
+
+float smoothstep(float edge0, float edge1, float x) {
+ float t = (x - edge0) / (edge1 - edge0);
+ if (t < 0) { t = 0; }
+ if (t > 1) { t = 1; }
+ return t * t * (3.0 - 2.0 * t);
+}
\ No newline at end of file
diff --git a/src/pc/utils/misc.h b/src/pc/utils/misc.h
new file mode 100644
index 000000000..d69b77d1d
--- /dev/null
+++ b/src/pc/utils/misc.h
@@ -0,0 +1,6 @@
+#ifndef UTILS_MISC_H
+#define UTILS_MISC_H
+
+float smoothstep(float edge0, float edge1, float x);
+
+#endif
\ No newline at end of file