From 7aec232450c22dd5d50f427fc48f77424074879c Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 21 Jun 2021 02:35:42 -0700 Subject: [PATCH] Added quit menu create enabled switch to disable interactables fixed djui_base_destroy() added on_click() event --- build-windows-visual-studio/sm64ex.vcxproj | 6 ++ .../sm64ex.vcxproj.filters | 18 ++++ src/pc/djui/djui.h | 1 + src/pc/djui/djui_base.c | 30 +++++-- src/pc/djui/djui_base.h | 5 +- src/pc/djui/djui_flow_layout.c | 12 +-- src/pc/djui/djui_interactable.c | 41 +++++++-- src/pc/djui/djui_interactable.h | 2 + src/pc/djui/djui_panel_main.c | 32 +++---- src/pc/djui/djui_panel_main.h | 2 + src/pc/djui/djui_panel_quit.c | 89 +++++++++++++++++++ src/pc/djui/djui_panel_quit.h | 4 + src/pc/utils/misc.c | 8 ++ src/pc/utils/misc.h | 6 ++ 14 files changed, 219 insertions(+), 37 deletions(-) create mode 100644 src/pc/djui/djui_panel_quit.c create mode 100644 src/pc/djui/djui_panel_quit.h create mode 100644 src/pc/utils/misc.c create mode 100644 src/pc/utils/misc.h diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index f42b2aea..b61021a5 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 24040d78..09a11b39 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 e3900398..1e9e3a2d 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 5ecfc534..03db100d 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 d2fc592d..9aff2db7 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 da886ec8..f99d4cdb 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 54a28b30..64b8a38d 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 0b2b805e..fcbf79f6 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 b423e932..c491e850 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 495ad48b..1b30887a 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 00000000..de0362bd --- /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 00000000..0b47f9a6 --- /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 00000000..8314a4ad --- /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 00000000..d69b77d1 --- /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