mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 13:35:12 +00:00
DJUI: Reimplemented chat
This commit is contained in:
parent
321e101b30
commit
64648a8ce3
24 changed files with 415 additions and 64 deletions
|
@ -3942,6 +3942,8 @@
|
|||
<ClCompile Include="..\src\pc\djui\djui_base.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_bind.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_button.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_chat_box.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_chat_message.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_checkbox.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_inputbox.c" />
|
||||
<ClCompile Include="..\src\pc\djui\djui_panel_cheats.c" />
|
||||
|
@ -4388,6 +4390,8 @@
|
|||
<ClInclude Include="..\src\pc\djui\djui_base.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_bind.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_button.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_chat_box.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_chat_message.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_checkbox.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_inputbox.h" />
|
||||
<ClInclude Include="..\src\pc\djui\djui_panel_cheats.h" />
|
||||
|
|
|
@ -15264,6 +15264,12 @@
|
|||
<ClCompile Include="..\src\pc\djui\djui_panel_cheats.c">
|
||||
<Filter>Source Files\src\pc\djui\panel</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\djui\djui_chat_box.c">
|
||||
<Filter>Source Files\src\pc\djui\component</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\pc\djui\djui_chat_message.c">
|
||||
<Filter>Source Files\src\pc\djui\component\compound</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\actors\common0.h">
|
||||
|
@ -16348,5 +16354,11 @@
|
|||
<ClInclude Include="..\src\pc\djui\djui_panel_cheats.h">
|
||||
<Filter>Source Files\src\pc\djui\panel</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\djui\djui_chat_box.h">
|
||||
<Filter>Source Files\src\pc\djui\component</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\pc\djui\djui_chat_message.h">
|
||||
<Filter>Source Files\src\pc\djui\component\compound</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -22,7 +22,6 @@ void djui_init(void) {
|
|||
djui_panel_main_create(NULL);
|
||||
//djui_panel_debug_create();
|
||||
}
|
||||
|
||||
djui_cursor_create();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "djui_selectionbox.h"
|
||||
#include "djui_bind.h"
|
||||
#include "djui_popup.h"
|
||||
#include "djui_chat_box.h"
|
||||
#include "djui_chat_message.h"
|
||||
|
||||
#include "djui_panel.h"
|
||||
#include "djui_panel_menu.h"
|
||||
|
|
|
@ -180,7 +180,8 @@ static void djui_base_add_child(struct DjuiBase* parent, struct DjuiBase* base)
|
|||
baseChild->next = NULL;
|
||||
|
||||
// add it to the head
|
||||
if (parent->child == NULL) {
|
||||
if (parent->child == NULL || parent->addChildrenToHead) {
|
||||
baseChild->next = parent->child;
|
||||
parent->child = baseChild;
|
||||
return;
|
||||
}
|
||||
|
@ -269,29 +270,29 @@ static void djui_base_render_border(struct DjuiBase* base) {
|
|||
// events //
|
||||
////////////
|
||||
|
||||
void djui_base_render(struct DjuiBase* base) {
|
||||
if (!base->visible) { return; }
|
||||
bool djui_base_render(struct DjuiBase* base) {
|
||||
if (!base->visible) { return false; }
|
||||
|
||||
if (base->on_render_pre != NULL) {
|
||||
bool skipRender = false;
|
||||
base->on_render_pre(base, &skipRender);
|
||||
if (skipRender) { return; }
|
||||
if (skipRender) { return false; }
|
||||
}
|
||||
|
||||
struct DjuiBaseRect* comp = &base->comp;
|
||||
struct DjuiBaseRect* clip = &base->clip;
|
||||
|
||||
djui_base_compute(base);
|
||||
if (comp->width <= 0) { return; }
|
||||
if (comp->height <= 0) { return; }
|
||||
if (clip->width <= 0) { return; }
|
||||
if (clip->height <= 0) { return; }
|
||||
if (comp->width <= 0) { return false; }
|
||||
if (comp->height <= 0) { return false; }
|
||||
if (clip->width <= 0) { return false; }
|
||||
if (clip->height <= 0) { return false; }
|
||||
|
||||
if (base->borderWidth.value > 0 && base->borderColor.a > 0) {
|
||||
djui_base_render_border(base);
|
||||
}
|
||||
|
||||
if (clip->width < 0 || clip->height <= 0) { return; }
|
||||
if (clip->width < 0 || clip->height <= 0) { return false; }
|
||||
|
||||
if (base->render != NULL) {
|
||||
base->render(base);
|
||||
|
@ -301,16 +302,20 @@ void djui_base_render(struct DjuiBase* base) {
|
|||
|
||||
// render all children
|
||||
struct DjuiBaseChild* child = base->child;
|
||||
bool hasChildRendered = false;
|
||||
while (child != NULL) {
|
||||
struct DjuiBaseChild* nextChild = child->next;
|
||||
djui_base_render(child->base);
|
||||
|
||||
bool childRendered = djui_base_render(child->base);
|
||||
if (base->abandonAfterChildRenderFail && !childRendered && hasChildRendered) { break; }
|
||||
hasChildRendered = hasChildRendered || childRendered;
|
||||
if (base->on_child_render != NULL) {
|
||||
base->on_child_render(base, child->base);
|
||||
}
|
||||
|
||||
child = nextChild;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void djui_base_destroy(struct DjuiBase* base) {
|
||||
|
|
|
@ -43,6 +43,8 @@ struct DjuiBase {
|
|||
struct DjuiBaseRect comp;
|
||||
struct DjuiBaseRect clip;
|
||||
struct DjuiInteractable* interactable;
|
||||
bool addChildrenToHead;
|
||||
bool abandonAfterChildRenderFail;
|
||||
s32 tag;
|
||||
void (*get_cursor_hover_location)(struct DjuiBase*, f32* x, f32* y);
|
||||
void (*on_child_render)(struct DjuiBase*, struct DjuiBase*);
|
||||
|
@ -67,6 +69,6 @@ void djui_base_set_alignment(struct DjuiBase* base, enum DjuiHAlign hAlign, enum
|
|||
|
||||
void djui_base_compute(struct DjuiBase* base);
|
||||
|
||||
void djui_base_render(struct DjuiBase* base);
|
||||
bool djui_base_render(struct DjuiBase* base);
|
||||
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*));
|
||||
|
|
135
src/pc/djui/djui_chat_box.c
Normal file
135
src/pc/djui/djui_chat_box.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pc/network/network.h"
|
||||
#include "djui.h"
|
||||
|
||||
struct DjuiChatBox* gDjuiChatBox = NULL;
|
||||
bool gDjuiChatBoxFocus = false;
|
||||
|
||||
void djui_chat_box_render(struct DjuiBase* base) {
|
||||
struct DjuiChatBox* chatBox = (struct DjuiChatBox*)base;
|
||||
struct DjuiBase* ccBase = &chatBox->chatContainer->base;
|
||||
djui_base_set_size(ccBase, 1.0f, chatBox->base.comp.height - 32 - 8);
|
||||
}
|
||||
|
||||
static void djui_chat_box_destroy(struct DjuiBase* base) {
|
||||
struct DjuiChatBox* chatBox = (struct DjuiChatBox*)base;
|
||||
free(chatBox);
|
||||
}
|
||||
|
||||
static void djui_chat_box_set_focus_style(void) {
|
||||
djui_base_set_visible(&gDjuiChatBox->chatInput->base, gDjuiChatBoxFocus);
|
||||
if (gDjuiChatBoxFocus) {
|
||||
djui_interactable_set_input_focus(&gDjuiChatBox->chatInput->base);
|
||||
}
|
||||
|
||||
djui_base_set_color(&gDjuiChatBox->chatFlow->base, 0, 0, 0, gDjuiChatBoxFocus ? 128 : 0);
|
||||
}
|
||||
|
||||
static void djui_chat_box_input_enter(struct DjuiInputbox* chatInput) {
|
||||
djui_interactable_set_input_focus(NULL);
|
||||
|
||||
if (strlen(chatInput->buffer) != 0) {
|
||||
djui_chat_message_create_from(gNetworkPlayerLocal->globalIndex, chatInput->buffer);
|
||||
network_send_chat(chatInput->buffer, gNetworkPlayerLocal->globalIndex);
|
||||
}
|
||||
|
||||
djui_inputbox_set_text(chatInput, "");
|
||||
djui_inputbox_select_all(chatInput);
|
||||
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
||||
}
|
||||
|
||||
static void djui_chat_box_input_escape(struct DjuiInputbox* chatInput) {
|
||||
djui_inputbox_set_text(chatInput, "");
|
||||
djui_inputbox_select_all(chatInput);
|
||||
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
||||
}
|
||||
|
||||
static bool djui_chat_box_input_on_key_down(struct DjuiBase* base, int scancode) {
|
||||
if (gDjuiChatBox == NULL) { return false; }
|
||||
f32 yMax = gDjuiChatBox->chatContainer->base.elem.height - gDjuiChatBox->chatFlow->base.height.value;
|
||||
|
||||
f32* yValue = &gDjuiChatBox->chatFlow->base.y.value;
|
||||
bool canScrollUp = (*yValue > yMax);
|
||||
bool canScrollDown = (*yValue < 0);
|
||||
f32 pageAmount = gDjuiChatBox->chatFlow->base.elem.height / 3.0f;
|
||||
|
||||
switch (scancode) {
|
||||
case SCANCODE_UP:
|
||||
gDjuiChatBox->scrolling = true;
|
||||
if (canScrollUp) { *yValue = fmax(*yValue - 15, yMax); }
|
||||
return true;
|
||||
case SCANCODE_DOWN:
|
||||
gDjuiChatBox->scrolling = true;
|
||||
if (canScrollDown) { *yValue = fmin(*yValue + 15, 0); }
|
||||
return true;
|
||||
case SCANCODE_PAGE_UP:
|
||||
gDjuiChatBox->scrolling = true;
|
||||
if (canScrollUp) { *yValue = fmax(*yValue - pageAmount, yMax); }
|
||||
return true;
|
||||
case SCANCODE_PAGE_DOWN:
|
||||
gDjuiChatBox->scrolling = true;
|
||||
if (canScrollDown) { *yValue = fmin(*yValue + pageAmount, 0); }
|
||||
return true;
|
||||
case SCANCODE_ENTER: djui_chat_box_input_enter(gDjuiChatBox->chatInput); return true;
|
||||
case SCANCODE_ESCAPE: djui_chat_box_input_escape(gDjuiChatBox->chatInput); return true;
|
||||
default: return djui_inputbox_on_key_down(base, scancode);
|
||||
}
|
||||
}
|
||||
|
||||
void djui_chat_box_toggle(void) {
|
||||
if (gDjuiChatBox == NULL) { return; }
|
||||
gDjuiChatBoxFocus = !gDjuiChatBoxFocus;
|
||||
djui_chat_box_set_focus_style();
|
||||
gDjuiChatBox->scrolling = false;
|
||||
gDjuiChatBox->chatFlow->base.y.value = gDjuiChatBox->chatContainer->base.elem.height - gDjuiChatBox->chatFlow->base.height.value;
|
||||
}
|
||||
|
||||
struct DjuiChatBox* djui_chat_box_create(void) {
|
||||
if (gDjuiChatBox != NULL) {
|
||||
djui_base_destroy(&gDjuiChatBox->base);
|
||||
gDjuiChatBox = NULL;
|
||||
}
|
||||
|
||||
struct DjuiChatBox* chatBox = malloc(sizeof(struct DjuiChatBox));
|
||||
struct DjuiBase* base = &chatBox->base;
|
||||
|
||||
djui_base_init(&gDjuiRoot->base, base, djui_chat_box_render, djui_chat_box_destroy);
|
||||
djui_base_set_size_type(base, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE);
|
||||
djui_base_set_size(base, 600, 1.0f);
|
||||
djui_base_set_alignment(base, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
|
||||
djui_base_set_color(base, 0, 0, 0, 0);
|
||||
djui_base_set_padding(base, 0, 8, 8, 8);
|
||||
|
||||
struct DjuiRect* chatContainer = djui_rect_create(base);
|
||||
struct DjuiBase* ccBase = &chatContainer->base;
|
||||
djui_base_set_size_type(ccBase, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(ccBase, 1.0f, 0);
|
||||
djui_base_set_color(ccBase, 0, 0, 0, 0);
|
||||
chatBox->chatContainer = chatContainer;
|
||||
|
||||
struct DjuiFlowLayout* chatFlow = djui_flow_layout_create(ccBase);
|
||||
struct DjuiBase* cfBase = &chatFlow->base;
|
||||
djui_base_set_location(cfBase, 0, 0);
|
||||
djui_base_set_size_type(cfBase, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(cfBase, 1.0f, 2);
|
||||
djui_base_set_color(cfBase, 0, 0, 0, 128);
|
||||
djui_base_set_padding(cfBase, 2, 2, 2, 2);
|
||||
djui_flow_layout_set_margin(chatFlow, 2);
|
||||
djui_flow_layout_set_flow_direction(chatFlow, DJUI_FLOW_DIR_UP);
|
||||
cfBase->addChildrenToHead = true;
|
||||
cfBase->abandonAfterChildRenderFail = true;
|
||||
chatBox->chatFlow = chatFlow;
|
||||
|
||||
struct DjuiInputbox* chatInput = djui_inputbox_create(base, 200);
|
||||
struct DjuiBase* ciBase = &chatInput->base;
|
||||
djui_base_set_size_type(ciBase, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(ciBase, 1.0f, 32);
|
||||
djui_base_set_alignment(ciBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
||||
djui_interactable_hook_key(&chatInput->base, djui_chat_box_input_on_key_down, djui_inputbox_on_key_up);
|
||||
chatBox->chatInput = chatInput;
|
||||
|
||||
gDjuiChatBox = chatBox;
|
||||
djui_chat_box_set_focus_style();
|
||||
return chatBox;
|
||||
}
|
17
src/pc/djui/djui_chat_box.h
Normal file
17
src/pc/djui/djui_chat_box.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include "djui.h"
|
||||
|
||||
#pragma pack(1)
|
||||
struct DjuiChatBox {
|
||||
struct DjuiBase base;
|
||||
struct DjuiRect* chatContainer;
|
||||
struct DjuiFlowLayout* chatFlow;
|
||||
struct DjuiInputbox* chatInput;
|
||||
bool scrolling;
|
||||
};
|
||||
|
||||
extern struct DjuiChatBox* gDjuiChatBox;
|
||||
extern bool gDjuiChatBoxFocus;
|
||||
|
||||
void djui_chat_box_toggle(void);
|
||||
struct DjuiChatBox* djui_chat_box_create(void);
|
91
src/pc/djui/djui_chat_message.c
Normal file
91
src/pc/djui/djui_chat_message.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <stdio.h>
|
||||
#include "pc/network/network.h"
|
||||
#include "audio_defines.h"
|
||||
#include "audio/external.h"
|
||||
#include "game/mario_misc.h"
|
||||
#include "djui.h"
|
||||
|
||||
#define DJUI_CHAT_LIFE_TIME 10.0f
|
||||
|
||||
static void djui_chat_message_render(struct DjuiBase* base) {
|
||||
struct DjuiChatMessage* chatMessage = (struct DjuiChatMessage*)base;
|
||||
struct DjuiBase* ctBase = &chatMessage->message->base;
|
||||
|
||||
f32 seconds = (clock() - chatMessage->createTime) / (f32)CLOCKS_PER_SEC;
|
||||
f32 f = 1.0f;
|
||||
if (seconds >= (DJUI_CHAT_LIFE_TIME - 1)) {
|
||||
f = fmax(1.0f - (seconds - (DJUI_CHAT_LIFE_TIME - 1)), 0.0f);
|
||||
f *= f;
|
||||
f *= f;
|
||||
}
|
||||
|
||||
if (gDjuiChatBoxFocus) {
|
||||
djui_base_set_color(base, 0, 0, 0, 64);
|
||||
djui_base_set_color(ctBase, 255, 255, 255, 255);
|
||||
djui_text_set_drop_shadow(chatMessage->message, 0, 0, 0, 200);
|
||||
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(base, 1.0f, chatMessage->base.height.value);
|
||||
} else {
|
||||
djui_base_set_color(base, 0, 0, 0, 150 * f);
|
||||
djui_base_set_color(ctBase, 255, 255, 255, 255 * f);
|
||||
djui_text_set_drop_shadow(chatMessage->message, 0, 0, 0, 200 * f);
|
||||
djui_base_set_size_type(base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(base, chatMessage->messageWidth, chatMessage->base.height.value);
|
||||
}
|
||||
|
||||
djui_rect_render(base);
|
||||
}
|
||||
|
||||
static void djui_chat_message_destroy(struct DjuiBase* base) {
|
||||
struct DjuiChatMessage* chatMessage = (struct DjuiChatMessage*)base;
|
||||
free(chatMessage);
|
||||
}
|
||||
|
||||
struct DjuiChatMessage* djui_chat_message_create_from(u8 globalIndex, char* message) {
|
||||
u8* rgb = get_player_color(globalIndex, 0);
|
||||
u8 rgb2[3] = { 0 };
|
||||
for (int i = 0; i < 3; i++) { rgb2[i] = fmin((f32)rgb[i] * 1.3f + 32.0f, 255); }
|
||||
char chatMsg[256] = { 0 };
|
||||
snprintf(chatMsg, 256, "\\#%02x%02x%02x\\%s:\\#dcdcdc\\ %s", rgb2[0], rgb2[1], rgb2[2], "Player", message);
|
||||
play_sound((globalIndex == gNetworkPlayerLocal->globalIndex) ? SOUND_MENU_MESSAGE_DISAPPEAR : SOUND_MENU_MESSAGE_APPEAR, gDefaultSoundArgs);
|
||||
return djui_chat_message_create(chatMsg);
|
||||
}
|
||||
|
||||
struct DjuiChatMessage* djui_chat_message_create(char* message) {
|
||||
struct DjuiChatMessage* chatMessage = malloc(sizeof(struct DjuiChatMessage));
|
||||
struct DjuiBase* base = &chatMessage->base;
|
||||
djui_base_init(&gDjuiChatBox->chatFlow->base, base, djui_chat_message_render, djui_chat_message_destroy);
|
||||
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(base, 1.0f, 0);
|
||||
djui_base_set_color(base, 0, 0, 0, 64);
|
||||
djui_base_set_padding(base, 2, 4, 2, 4);
|
||||
djui_base_set_alignment(base, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
||||
|
||||
f32 maxTextWidth = gDjuiChatBox->base.width.value - gDjuiChatBox->base.padding.left.value - gDjuiChatBox->base.padding.right.value - base->padding.left.value - base->padding.right.value;
|
||||
|
||||
struct DjuiText* chatText = djui_text_create(base, message);
|
||||
struct DjuiBase* ctBase = &chatText->base;
|
||||
djui_base_set_size_type(ctBase, DJUI_SVT_ABSOLUTE, DJUI_SVT_RELATIVE);
|
||||
djui_base_set_size(ctBase, maxTextWidth, 1.0f);
|
||||
djui_base_set_color(ctBase, 255, 255, 255, 255);
|
||||
djui_base_set_location(ctBase, 0, 0);
|
||||
djui_text_set_alignment(chatText, DJUI_HALIGN_LEFT, DJUI_VALIGN_TOP);
|
||||
djui_text_set_drop_shadow(chatText, 0, 0, 0, 200);
|
||||
chatMessage->message = chatText;
|
||||
chatMessage->createTime = clock();
|
||||
|
||||
// figure out chat message height
|
||||
chatText->base.comp.width = maxTextWidth;
|
||||
f32 messageHeight = djui_text_count_lines(chatText, 10) * (chatText->font->lineHeight * chatText->font->defaultFontScale) + 8;
|
||||
djui_base_set_size(base, 1.0f, messageHeight);
|
||||
gDjuiChatBox->chatFlow->base.height.value += messageHeight + gDjuiChatBox->chatFlow->margin.value;
|
||||
if (!gDjuiChatBox->scrolling) {
|
||||
gDjuiChatBox->chatFlow->base.y.value = gDjuiChatBox->chatContainer->base.elem.height - gDjuiChatBox->chatFlow->base.height.value;
|
||||
}
|
||||
|
||||
// figure out chat message width
|
||||
f32 messageWidth = djui_text_find_width(chatText, 10);
|
||||
chatMessage->messageWidth = messageWidth + 8;
|
||||
|
||||
return chatMessage;
|
||||
}
|
14
src/pc/djui/djui_chat_message.h
Normal file
14
src/pc/djui/djui_chat_message.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "djui.h"
|
||||
#include <time.h>
|
||||
|
||||
#pragma pack(1)
|
||||
struct DjuiChatMessage {
|
||||
struct DjuiBase base;
|
||||
struct DjuiText* message;
|
||||
f32 messageWidth;
|
||||
clock_t createTime;
|
||||
};
|
||||
|
||||
struct DjuiChatMessage* djui_chat_message_create_from(u8 globalIndex, char* message);
|
||||
struct DjuiChatMessage* djui_chat_message_create(char* message);
|
|
@ -38,10 +38,14 @@ void djui_inputbox_select_all(struct DjuiInputbox* inputbox) {
|
|||
inputbox->selection[0] = strlen(inputbox->buffer);
|
||||
}
|
||||
|
||||
void djui_inputbox_hook_enter_press(struct DjuiInputbox* inputbox, void (*on_enter_press)(void)) {
|
||||
void djui_inputbox_hook_enter_press(struct DjuiInputbox* inputbox, void (*on_enter_press)(struct DjuiInputbox*)) {
|
||||
inputbox->on_enter_press = on_enter_press;
|
||||
}
|
||||
|
||||
void djui_inputbox_hook_escape_press(struct DjuiInputbox* inputbox, void (*on_escape_press)(struct DjuiInputbox*)) {
|
||||
inputbox->on_escape_press = on_escape_press;
|
||||
}
|
||||
|
||||
static void djui_inputbox_set_default_style(struct DjuiBase* base) {
|
||||
struct DjuiInputbox* inputbox = (struct DjuiInputbox*)base;
|
||||
if (inputbox->base.enabled) {
|
||||
|
@ -152,7 +156,7 @@ static void djui_inputbox_delete_selection(struct DjuiInputbox *inputbox) {
|
|||
djui_inputbox_on_change(inputbox);
|
||||
}
|
||||
|
||||
static bool djui_inputbox_on_key_down(struct DjuiBase *base, int scancode) {
|
||||
bool djui_inputbox_on_key_down(struct DjuiBase *base, int scancode) {
|
||||
struct DjuiInputbox *inputbox = (struct DjuiInputbox *) base;
|
||||
u16 *sel = inputbox->selection;
|
||||
char *msg = inputbox->buffer;
|
||||
|
@ -261,13 +265,16 @@ static bool djui_inputbox_on_key_down(struct DjuiBase *base, int scancode) {
|
|||
|
||||
if (scancode == SCANCODE_ESCAPE) {
|
||||
djui_interactable_set_input_focus(NULL);
|
||||
if (inputbox->on_escape_press) {
|
||||
inputbox->on_escape_press(inputbox);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (scancode == SCANCODE_ENTER) {
|
||||
djui_interactable_set_input_focus(NULL);
|
||||
if (inputbox->on_enter_press) {
|
||||
inputbox->on_enter_press();
|
||||
inputbox->on_enter_press(inputbox);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -275,7 +282,7 @@ static bool djui_inputbox_on_key_down(struct DjuiBase *base, int scancode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void djui_inputbox_on_key_up(struct DjuiBase *base, int scancode) {
|
||||
void djui_inputbox_on_key_up(struct DjuiBase *base, int scancode) {
|
||||
switch (scancode) {
|
||||
case SCANCODE_CONTROL_LEFT: sHeldControl &= ~(1 << 0); break;
|
||||
case SCANCODE_CONTROL_RIGHT: sHeldControl &= ~(1 << 1); break;
|
||||
|
|
|
@ -9,12 +9,16 @@ struct DjuiInputbox {
|
|||
u16 selection[2];
|
||||
f32 viewX;
|
||||
struct DjuiColor textColor;
|
||||
void (*on_enter_press)(void);
|
||||
void (*on_enter_press)(struct DjuiInputbox*);
|
||||
void (*on_escape_press)(struct DjuiInputbox*);
|
||||
};
|
||||
|
||||
void djui_inputbox_set_text_color(struct DjuiInputbox* inputbox, u8 r, u8 g, u8 b, u8 a);
|
||||
void djui_inputbox_set_text(struct DjuiInputbox* inputbox, char* text);
|
||||
void djui_inputbox_select_all(struct DjuiInputbox* inputbox);
|
||||
void djui_inputbox_hook_enter_press(struct DjuiInputbox* inputbox, void (*on_enter_press)(void));
|
||||
void djui_inputbox_hook_enter_press(struct DjuiInputbox* inputbox, void (*on_enter_press)(struct DjuiInputbox*));
|
||||
void djui_inputbox_hook_escape_press(struct DjuiInputbox* inputbox, void (*on_escape_press)(struct DjuiInputbox*));
|
||||
bool djui_inputbox_on_key_down(struct DjuiBase* base, int scancode);
|
||||
void djui_inputbox_on_key_up(struct DjuiBase* base, int scancode);
|
||||
|
||||
struct DjuiInputbox* djui_inputbox_create(struct DjuiBase* parent, u16 bufferSize);
|
||||
|
|
|
@ -9,15 +9,6 @@
|
|||
#include "audio_defines.h"
|
||||
#include "audio/external.h"
|
||||
|
||||
#define SCANCODE_UP 328
|
||||
#define SCANCODE_DOWN 336
|
||||
#define SCANCODE_LEFT 331
|
||||
#define SCANCODE_RIGHT 333
|
||||
|
||||
#define SCANCODE_ENTER 28
|
||||
#define SCANCODE_SPACE 57
|
||||
#define SCANCODE_ESCAPE 1
|
||||
|
||||
enum PadHoldDirection { PAD_HOLD_DIR_NONE, PAD_HOLD_DIR_UP, PAD_HOLD_DIR_DOWN, PAD_HOLD_DIR_LEFT, PAD_HOLD_DIR_RIGHT };
|
||||
static enum PadHoldDirection sKeyboardHoldDirection = PAD_HOLD_DIR_NONE;
|
||||
static u16 sKeyboardButtons = 0;
|
||||
|
@ -179,9 +170,11 @@ bool djui_interactable_on_key_down(int scancode) {
|
|||
|
||||
if (keyFocused) {
|
||||
bool consume = sInteractableFocus->interactable->on_key_down(sInteractableFocus, scancode);
|
||||
sKeyboardHoldDirection = PAD_HOLD_DIR_NONE;
|
||||
sKeyboardButtons = 0;
|
||||
return consume;
|
||||
if (consume) {
|
||||
sKeyboardHoldDirection = PAD_HOLD_DIR_NONE;
|
||||
sKeyboardButtons = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (scancode == SCANCODE_ESCAPE) {
|
||||
|
@ -189,6 +182,18 @@ bool djui_interactable_on_key_down(int scancode) {
|
|||
djui_panel_back();
|
||||
}
|
||||
|
||||
if (gDjuiChatBox != NULL && !gDjuiChatBoxFocus) {
|
||||
bool pressChat = false;
|
||||
for (int i = 0; i < MAX_BINDS; i++) {
|
||||
if (scancode == (int)configKeyChat[i]) { pressChat = true; }
|
||||
}
|
||||
|
||||
if (pressChat) {
|
||||
djui_chat_box_toggle();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (scancode) {
|
||||
case SCANCODE_UP: sKeyboardHoldDirection = PAD_HOLD_DIR_UP; return true;
|
||||
case SCANCODE_DOWN: sKeyboardHoldDirection = PAD_HOLD_DIR_DOWN; return true;
|
||||
|
@ -196,6 +201,7 @@ bool djui_interactable_on_key_down(int scancode) {
|
|||
case SCANCODE_RIGHT: sKeyboardHoldDirection = PAD_HOLD_DIR_RIGHT; return true;
|
||||
case SCANCODE_ENTER: sKeyboardButtons |= PAD_BUTTON_A; return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,18 @@
|
|||
|
||||
#define MOUSE_BUTTON_1 ((u16)(1 << 0))
|
||||
|
||||
#define SCANCODE_UP 328
|
||||
#define SCANCODE_DOWN 336
|
||||
#define SCANCODE_LEFT 331
|
||||
#define SCANCODE_RIGHT 333
|
||||
#define SCANCODE_PAGE_DOWN 337
|
||||
#define SCANCODE_PAGE_UP 329
|
||||
|
||||
|
||||
#define SCANCODE_ENTER 28
|
||||
#define SCANCODE_SPACE 57
|
||||
#define SCANCODE_ESCAPE 1
|
||||
|
||||
#pragma pack(1)
|
||||
struct DjuiInteractable {
|
||||
bool enabled;
|
||||
|
|
|
@ -19,6 +19,8 @@ static void djui_panel_pause_quit(struct DjuiBase* caller) {
|
|||
}
|
||||
|
||||
void djui_panel_pause_create(struct DjuiBase* caller) {
|
||||
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
||||
|
||||
f32 bodyHeight = 64 * 3 + 16 * 2;
|
||||
if (Cheats.EnableCheats) { bodyHeight += 64 + 16; }
|
||||
|
||||
|
|
|
@ -169,6 +169,46 @@ static void djui_text_read_line(struct DjuiText* text, u16* index, f32* lineWidt
|
|||
}*/
|
||||
}
|
||||
|
||||
int djui_text_count_lines(struct DjuiText* text, u16 maxLines) {
|
||||
struct DjuiBaseRect* comp = &text->base.comp;
|
||||
u16 startIndex = 0;
|
||||
u16 endIndex = 0;
|
||||
f32 maxLineWidth = comp->width / ((f32)text->fontScale);
|
||||
u16 lineCount = 0;
|
||||
while (text->message[startIndex] != '\0') {
|
||||
bool onLastLine = lineCount + 1 >= maxLines;
|
||||
f32 lineWidth;
|
||||
bool ellipses;
|
||||
djui_text_read_line(text, &endIndex, &lineWidth, maxLineWidth, onLastLine, &ellipses);
|
||||
startIndex = endIndex;
|
||||
lineCount++;
|
||||
if (onLastLine) { break; }
|
||||
}
|
||||
return lineCount;
|
||||
}
|
||||
|
||||
f32 djui_text_find_width(struct DjuiText* text, u16 maxLines) {
|
||||
struct DjuiBaseRect* comp = &text->base.comp;
|
||||
u16 startIndex = 0;
|
||||
u16 endIndex = 0;
|
||||
f32 maxLineWidth = comp->width / ((f32)text->fontScale);
|
||||
u16 lineCount = 0;
|
||||
|
||||
f32 largestWidth = 0;
|
||||
|
||||
while (text->message[startIndex] != '\0') {
|
||||
bool onLastLine = lineCount + 1 >= maxLines;
|
||||
f32 lineWidth;
|
||||
bool ellipses;
|
||||
djui_text_read_line(text, &endIndex, &lineWidth, maxLineWidth, onLastLine, &ellipses);
|
||||
largestWidth = fmax(largestWidth, lineWidth);
|
||||
startIndex = endIndex;
|
||||
lineCount++;
|
||||
if (onLastLine) { break; }
|
||||
}
|
||||
return largestWidth * text->fontScale;
|
||||
}
|
||||
|
||||
static int djui_text_render_line_parse_escape(struct DjuiText* text, u16 startIndex, u16 endIndex) {
|
||||
bool parsingColor = text->message[startIndex + 1] == '#';
|
||||
u16 i = parsingColor ? (startIndex + 1) : startIndex;
|
||||
|
@ -298,20 +338,9 @@ static void djui_text_render(struct DjuiBase* base) {
|
|||
sSavedA = base->color.a;
|
||||
|
||||
// count lines
|
||||
u16 startIndex = 0;
|
||||
u16 endIndex = 0;
|
||||
f32 maxLineWidth = comp->width / ((f32)text->fontScale);
|
||||
u16 lineCount = 0;
|
||||
u16 maxLines = comp->height / ((f32)text->font->lineHeight * text->fontScale);
|
||||
while (text->message[startIndex] != '\0') {
|
||||
bool onLastLine = lineCount + 1 >= maxLines;
|
||||
f32 lineWidth;
|
||||
bool ellipses;
|
||||
djui_text_read_line(text, &endIndex, &lineWidth, maxLineWidth, onLastLine, &ellipses);
|
||||
startIndex = endIndex;
|
||||
lineCount++;
|
||||
if (onLastLine) { break; }
|
||||
}
|
||||
f32 maxLineWidth = comp->width / ((f32)text->fontScale);
|
||||
u16 lineCount = djui_text_count_lines(text, maxLines);
|
||||
|
||||
// do vertical alignment
|
||||
f32 vOffset = 0;
|
||||
|
@ -325,8 +354,8 @@ static void djui_text_render(struct DjuiBase* base) {
|
|||
djui_text_translate(0, vOffset);
|
||||
|
||||
// render lines
|
||||
startIndex = 0;
|
||||
endIndex = 0;
|
||||
u16 startIndex = 0;
|
||||
u16 endIndex = 0;
|
||||
f32 lineWidth;
|
||||
u16 lineIndex = 0;
|
||||
bool ellipses = false;
|
||||
|
|
|
@ -18,4 +18,7 @@ void djui_text_set_font_scale(struct DjuiText* text, f32 fontScale);
|
|||
void djui_text_set_drop_shadow(struct DjuiText* text, f32 r, f32 g, f32 b, f32 a);
|
||||
void djui_text_set_alignment(struct DjuiText* text, enum DjuiHAlign hAlign, enum DjuiVAlign vAlign);
|
||||
|
||||
int djui_text_count_lines(struct DjuiText* text, u16 maxLines);
|
||||
f32 djui_text_find_width(struct DjuiText* text, u16 maxLines);
|
||||
|
||||
struct DjuiText* djui_text_create(struct DjuiBase* parent, const char* message);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#endif
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/cheats.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
// Mario 64 specific externs
|
||||
|
@ -81,6 +82,8 @@ bool network_init(enum NetworkType inNetworkType) {
|
|||
network_player_connected(NPT_LOCAL, 0);
|
||||
extern u8* gOverrideEeprom;
|
||||
gOverrideEeprom = NULL;
|
||||
|
||||
djui_chat_box_create();
|
||||
} else if (gNetworkType == NT_CLIENT) {
|
||||
network_player_connected(NPT_SERVER, 0);
|
||||
}
|
||||
|
@ -267,6 +270,11 @@ void network_register_mod(char* modName) {
|
|||
}
|
||||
|
||||
void network_shutdown(bool sendLeaving) {
|
||||
if (gDjuiChatBox != NULL) {
|
||||
djui_base_destroy(&gDjuiChatBox->base);
|
||||
gDjuiChatBox = NULL;
|
||||
}
|
||||
|
||||
network_forget_all_reliable();
|
||||
if (gNetworkType == NT_NONE) { return; }
|
||||
if (gNetworkSystem == NULL) { LOG_ERROR("no network system attached"); return; }
|
||||
|
@ -277,8 +285,3 @@ void network_shutdown(bool sendLeaving) {
|
|||
|
||||
gNetworkType = NT_NONE;
|
||||
}
|
||||
|
||||
// TODO: replace
|
||||
void chat_add_message(char* message) {
|
||||
LOG_INFO("chat: %s", message);
|
||||
}
|
||||
|
|
|
@ -102,6 +102,4 @@ void network_update(void);
|
|||
void network_register_mod(char* modName);
|
||||
void network_shutdown(bool sendLeaving);
|
||||
|
||||
// TODO: replace
|
||||
void chat_add_message(char* message);
|
||||
#endif
|
||||
|
|
|
@ -183,8 +183,10 @@ u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex) {
|
|||
} else {
|
||||
// display popup
|
||||
u8* rgb = get_player_color(np->globalIndex, 0);
|
||||
u8 rgb2[3] = { 0 };
|
||||
for (int i = 0; i < 3; i++) { rgb2[i] = fmin((f32)rgb[i] * 1.3f + 32.0f, 255); }
|
||||
char popupMsg[128] = { 0 };
|
||||
snprintf(popupMsg, 128, "\\#%02x%02x%02x\\Player\\#dcdcdc\\ connected.", rgb[0], rgb[1], rgb[2]);
|
||||
snprintf(popupMsg, 128, "\\#%02x%02x%02x\\%s\\#dcdcdc\\ connected.", rgb2[0], rgb2[1], rgb2[2], "Player");
|
||||
djui_popup_create(popupMsg, 1);
|
||||
}
|
||||
LOG_INFO("player connected, local %d, global %d", i, np->globalIndex);
|
||||
|
@ -229,8 +231,10 @@ u8 network_player_disconnected(u8 globalIndex) {
|
|||
|
||||
// display popup
|
||||
u8* rgb = get_player_color(np->globalIndex, 0);
|
||||
u8 rgb2[3] = { 0 };
|
||||
for (int i = 0; i < 3; i++) { rgb2[i] = fmin((f32)rgb[i] * 1.3f + 32.0f, 255); }
|
||||
char popupMsg[128] = { 0 };
|
||||
snprintf(popupMsg, 128, "\\#%02x%02x%02x\\Player\\#dcdcdc\\ disconnected.", rgb[0], rgb[1], rgb[2]);
|
||||
snprintf(popupMsg, 128, "\\#%02x%02x%02x\\%s\\#dcdcdc\\ disconnected.", rgb2[0], rgb2[1], rgb2[2], "Player");
|
||||
djui_popup_create(popupMsg, 1);
|
||||
|
||||
packet_ordered_clear(globalIndex);
|
||||
|
|
|
@ -169,7 +169,7 @@ void network_send_custom(u8 customId, bool reliable, bool levelAreaMustMatch, vo
|
|||
void network_receive_custom(struct Packet* p);
|
||||
|
||||
// packet_chat.c
|
||||
void network_send_chat(char* message, u8 rgb[3]);
|
||||
void network_send_chat(char* message, u8 globalIndex);
|
||||
void network_receive_chat(struct Packet* p);
|
||||
|
||||
// packet_kick.c
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include "../network.h"
|
||||
#include "../reservation_area.h"
|
||||
#include "pc/djui/djui.h"
|
||||
#include "pc/debuglog.h"
|
||||
|
||||
#ifdef DEVELOPMENT
|
||||
|
@ -28,11 +29,11 @@ static void print_network_player_table(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
void network_send_chat(char* message, u8 rgb[3]) {
|
||||
void network_send_chat(char* message, u8 globalIndex) {
|
||||
u16 messageLength = strlen(message);
|
||||
struct Packet p;
|
||||
packet_init(&p, PACKET_CHAT, true, false);
|
||||
packet_write(&p, rgb, 3 * sizeof(u8));
|
||||
packet_write(&p, &globalIndex, sizeof(u8));
|
||||
packet_write(&p, &messageLength, sizeof(u16));
|
||||
packet_write(&p, message, messageLength * sizeof(u8));
|
||||
network_send(&p);
|
||||
|
@ -45,16 +46,16 @@ void network_send_chat(char* message, u8 rgb[3]) {
|
|||
|
||||
void network_receive_chat(struct Packet* p) {
|
||||
u16 remoteMessageLength = 0;
|
||||
char remoteMessage[255] = { 0 };
|
||||
u8 rgb[3] = { 255, 255, 255};
|
||||
char remoteMessage[256] = { 0 };
|
||||
u8 globalIndex;
|
||||
|
||||
packet_read(p, rgb, 3 * sizeof(u8));
|
||||
packet_read(p, &globalIndex, sizeof(u8));
|
||||
packet_read(p, &remoteMessageLength, sizeof(u16));
|
||||
if (remoteMessageLength > 255) { remoteMessageLength = 254; }
|
||||
if (remoteMessageLength > 256) { remoteMessageLength = 255; }
|
||||
packet_read(p, &remoteMessage, remoteMessageLength * sizeof(u8));
|
||||
|
||||
// add the message
|
||||
chat_add_message(remoteMessage);
|
||||
djui_chat_message_create_from(globalIndex, remoteMessage);
|
||||
LOG_INFO("rx chat: %s", remoteMessage);
|
||||
/*
|
||||
#ifdef DEVELOPMENT
|
||||
|
|
|
@ -178,6 +178,7 @@ void network_receive_join(struct Packet* p) {
|
|||
|
||||
network_player_connected(NPT_SERVER, 0);
|
||||
network_player_connected(NPT_LOCAL, myGlobalIndex);
|
||||
djui_chat_box_create();
|
||||
|
||||
save_file_load_all(TRUE);
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ void network_receive_player(struct Packet* p) {
|
|||
|
||||
// inform of player death
|
||||
if (oldData.action != ACT_BUBBLED && data.action == ACT_BUBBLED) {
|
||||
chat_add_message("player died");
|
||||
//chat_add_message("player died");
|
||||
}
|
||||
|
||||
// action changed, reset timer
|
||||
|
|
Loading…
Reference in a new issue