mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-12-02 22:22:48 +00:00
Added SentChatMessages-History (including navigation)
Added Tab-Completion for Main-Commands
Added Tab-Completion for Sub-Commands
Added Tab-Completion for Player-Names [Now finally fixed and working correctly]
Improved some english translations
Improved a lot of german translations
Fixed a few bugs and bad code regarding "default commands"
Development started on a new chat command handling system (Not in use yet)
Fixed some stuff previously noted/criticized by other developers in a previous the code review
Added new Start-Parameter "--playername PLAYERNAME"
Added new Start-Parameter "--randomplayername"
546 lines
No EOL
21 KiB
C
546 lines
No EOL
21 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "pc/network/network.h"
|
|
#include "pc/lua/smlua_hooks.h"
|
|
#include "pc/chat_commands.h"
|
|
#include "djui.h"
|
|
|
|
struct DjuiChatBox* gDjuiChatBox = NULL;
|
|
bool gDjuiChatBoxFocus = false;
|
|
static bool sDjuiChatBoxClearText = false;
|
|
|
|
#define MAX_HISTORY_SIZE 256
|
|
#define MAX_MSG_LENGTH 201
|
|
|
|
typedef struct {
|
|
s32 initialized;
|
|
s32 size;
|
|
char messages[MAX_HISTORY_SIZE][MAX_MSG_LENGTH];
|
|
s32 currentIndex;
|
|
char currentMessage[MAX_MSG_LENGTH];
|
|
} ArrayList;
|
|
|
|
ArrayList sentHistory;
|
|
|
|
static s32 sCommandsTabCompletionIndex = -1;
|
|
static char sCommandsTabCompletionOriginalText[MAX_MSG_LENGTH];
|
|
static s32 sPlayersTabCompletionIndex = -1;
|
|
static char sPlayersTabCompletionOriginalText[MAX_MSG_LENGTH];
|
|
|
|
void reset_tab_completion_commands(void) {
|
|
sCommandsTabCompletionIndex = -1;
|
|
snprintf(sCommandsTabCompletionOriginalText, MAX_MSG_LENGTH, "%s", "");
|
|
}
|
|
void reset_tab_completion_players(void) {
|
|
sPlayersTabCompletionIndex = -1;
|
|
snprintf(sPlayersTabCompletionOriginalText, MAX_MSG_LENGTH, "%s", "");
|
|
}
|
|
void reset_tab_completion_all(void) {
|
|
reset_tab_completion_commands();
|
|
reset_tab_completion_players();
|
|
}
|
|
|
|
void sent_history_init(ArrayList *arrayList) {
|
|
if (!arrayList->initialized) {
|
|
arrayList->size = 0;
|
|
arrayList->initialized = 1;
|
|
arrayList->currentIndex = -1;
|
|
snprintf(arrayList->currentMessage, MAX_MSG_LENGTH, "%s", "");
|
|
}
|
|
}
|
|
|
|
void sent_history_add_message(ArrayList *arrayList, const char *newMessage) {
|
|
if (arrayList->size == MAX_HISTORY_SIZE) {
|
|
for (s32 i = 1; i < MAX_HISTORY_SIZE; i++) {
|
|
snprintf(arrayList->messages[i-1], MAX_MSG_LENGTH, "%s", arrayList->messages[i]);
|
|
}
|
|
arrayList->size--;
|
|
}
|
|
|
|
snprintf(arrayList->messages[arrayList->size], MAX_MSG_LENGTH, "%s", newMessage);
|
|
arrayList->messages[arrayList->size][MAX_MSG_LENGTH - 1] = '\0';
|
|
arrayList->size++;
|
|
}
|
|
|
|
void sent_history_update_current_message(ArrayList *arrayList, const char *message) {
|
|
if (arrayList->currentIndex == -1) {
|
|
snprintf(arrayList->currentMessage, MAX_MSG_LENGTH, "%s", message);
|
|
}
|
|
}
|
|
|
|
void sent_history_navigate(ArrayList *arrayList, bool navigateUp) {
|
|
if (navigateUp) {
|
|
if (arrayList->currentIndex == -1) {
|
|
arrayList->currentIndex = arrayList->size - 1;
|
|
} else if (arrayList->currentIndex > 1) {
|
|
arrayList->currentIndex = arrayList->currentIndex - 1;
|
|
} else {
|
|
arrayList->currentIndex = 0;
|
|
}
|
|
} else {
|
|
if (arrayList->currentIndex == -1 || arrayList->currentIndex == arrayList->size - 1) {
|
|
arrayList->currentIndex = -1;
|
|
} else if (arrayList->currentIndex > -1) {
|
|
arrayList->currentIndex = arrayList->currentIndex + 1;
|
|
}
|
|
}
|
|
djui_inputbox_set_text(gDjuiChatBox->chatInput, arrayList->currentIndex == -1 ? arrayList->currentMessage : arrayList->messages[arrayList->currentIndex]);
|
|
djui_inputbox_move_cursor_to_end(gDjuiChatBox->chatInput);
|
|
}
|
|
|
|
void sent_history_reset_navigation(ArrayList *arrayList) {
|
|
snprintf(arrayList->currentMessage, MAX_MSG_LENGTH, "%s", "");
|
|
arrayList->currentIndex = -1;
|
|
}
|
|
|
|
bool 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);
|
|
if (sDjuiChatBoxClearText) {
|
|
sDjuiChatBoxClearText = false;
|
|
djui_inputbox_set_text(gDjuiChatBox->chatInput, "");
|
|
djui_inputbox_select_all(gDjuiChatBox->chatInput);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
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) {
|
|
sent_history_add_message(&sentHistory, chatInput->buffer);
|
|
if (chatInput->buffer[0] == '/') {
|
|
if (strcmp(chatInput->buffer, "/help") == 0 || strcmp(chatInput->buffer, "/?") == 0) {
|
|
display_chat_commands();
|
|
} else if (!exec_chat_command(chatInput->buffer)) {
|
|
char extendedUnknownCommandMessage[MAX_MSG_LENGTH];
|
|
snprintf(extendedUnknownCommandMessage, sizeof(extendedUnknownCommandMessage), "%s (/help)", DLANG(CHAT, UNRECOGNIZED));
|
|
djui_chat_message_create(extendedUnknownCommandMessage);
|
|
}
|
|
} else {
|
|
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_interactable_set_input_focus(NULL);
|
|
djui_inputbox_set_text(chatInput, "");
|
|
djui_inputbox_select_all(chatInput);
|
|
if (gDjuiChatBoxFocus) { djui_chat_box_toggle(); }
|
|
}
|
|
|
|
static char* get_main_command_from_input(const char* input) {
|
|
char* spacePos = strrchr(input, ' ');
|
|
if (spacePos == NULL) {
|
|
return NULL;
|
|
}
|
|
size_t len = spacePos - input;
|
|
char* command = (char*) malloc(len + 1);
|
|
snprintf(command, len + 1, "%s", input);
|
|
command[len] = '\0';
|
|
return command;
|
|
}
|
|
|
|
static bool complete_subcommand(const char* mainCommand, const char* subCommandPrefix) {
|
|
char** subcommands = smlua_get_chat_subcommands_list(mainCommand);
|
|
|
|
if (!subcommands || !subcommands[0]) {
|
|
return false;
|
|
}
|
|
|
|
s32 foundSubCommandsCount = 0;
|
|
for (s32 i = 0; subcommands[i] != NULL; i++) {
|
|
if (strncmp(subcommands[i], subCommandPrefix, strlen(subCommandPrefix)) == 0) {
|
|
foundSubCommandsCount++;
|
|
}
|
|
}
|
|
|
|
bool completionSuccess = false;
|
|
if (foundSubCommandsCount > 0) {
|
|
sCommandsTabCompletionIndex = (sCommandsTabCompletionIndex + 1) % foundSubCommandsCount;
|
|
s32 currentIndex = 0;
|
|
|
|
for (s32 i = 0; subcommands[i] != NULL; i++) {
|
|
if (strncmp(subcommands[i], subCommandPrefix, strlen(subCommandPrefix)) == 0) {
|
|
if (currentIndex == sCommandsTabCompletionIndex) {
|
|
char completion[MAX_MSG_LENGTH];
|
|
snprintf(completion, MAX_MSG_LENGTH, "/%s %s", mainCommand, subcommands[i]);
|
|
djui_inputbox_set_text(gDjuiChatBox->chatInput, completion);
|
|
djui_inputbox_move_cursor_to_end(gDjuiChatBox->chatInput);
|
|
completionSuccess = true;
|
|
break;
|
|
}
|
|
currentIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (s32 i = 0; subcommands[i] != NULL; i++) {
|
|
free(subcommands[i]);
|
|
}
|
|
free(subcommands);
|
|
|
|
return completionSuccess;
|
|
}
|
|
|
|
typedef struct {
|
|
char word[MAX_MSG_LENGTH];
|
|
s32 index;
|
|
} CurrentWordInfo;
|
|
|
|
CurrentWordInfo get_current_word_info(char* buffer, s32 position) {
|
|
CurrentWordInfo info;
|
|
memset(info.word, 0, MAX_MSG_LENGTH);
|
|
info.index = -1;
|
|
|
|
s32 currentWordStart = position;
|
|
s32 currentWordEnd = position;
|
|
|
|
while (currentWordStart > 0 && buffer[currentWordStart - 1] != ' ') {
|
|
currentWordStart--;
|
|
}
|
|
|
|
while (buffer[currentWordEnd] != '\0' && buffer[currentWordEnd] != ' ') {
|
|
currentWordEnd++;
|
|
}
|
|
|
|
s32 wordLength = currentWordEnd - currentWordStart;
|
|
if (wordLength > MAX_MSG_LENGTH - 1) {
|
|
wordLength = MAX_MSG_LENGTH - 1;
|
|
}
|
|
|
|
snprintf(info.word, wordLength + 1, "%.*s", wordLength, &buffer[currentWordStart]);
|
|
|
|
s32 wordCount = 0;
|
|
for (s32 i = 0; i <= currentWordStart; i++) {
|
|
if (buffer[i] == ' ' || i == 0) {
|
|
wordCount++;
|
|
}
|
|
}
|
|
info.index = wordCount;
|
|
|
|
return info;
|
|
}
|
|
|
|
void djui_inputbox_replace_current_word(struct DjuiInputbox* inputbox, char* text) {
|
|
if (!inputbox || !text) { return; }
|
|
|
|
s32 currentWordStart = inputbox->selection[0];
|
|
s32 currentWordEnd = inputbox->selection[0];
|
|
|
|
while (currentWordStart > 0 && inputbox->buffer[currentWordStart - 1] != ' ') { currentWordStart--; }
|
|
while (inputbox->buffer[currentWordEnd] != '\0' && inputbox->buffer[currentWordEnd] != ' ') { currentWordEnd++; }
|
|
|
|
char newBuffer[MAX_MSG_LENGTH];
|
|
snprintf(newBuffer, MAX_MSG_LENGTH, "%.*s%s%s", currentWordStart, inputbox->buffer, text, &inputbox->buffer[currentWordEnd]);
|
|
|
|
djui_inputbox_set_text(inputbox, newBuffer);
|
|
djui_inputbox_move_cursor_to_position(inputbox, currentWordStart + strlen(text));
|
|
}
|
|
|
|
static bool complete_player_name(const char* namePrefix) {
|
|
char** playerNames = smlua_get_chat_player_list();
|
|
if (!playerNames || !playerNames[0]) {
|
|
if (playerNames) {
|
|
free(playerNames);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
s32 foundNamesCount = 0;
|
|
for (s32 i = 0; playerNames[i] != NULL; i++) {
|
|
if (strncmp(playerNames[i], namePrefix, strlen(namePrefix)) == 0) {
|
|
foundNamesCount++;
|
|
}
|
|
}
|
|
|
|
bool completionSuccess = false;
|
|
if (foundNamesCount > 0) {
|
|
sPlayersTabCompletionIndex = (sPlayersTabCompletionIndex + 1) % foundNamesCount;
|
|
s32 currentIndex = 0;
|
|
|
|
for (s32 i = 0; playerNames[i] != NULL; i++) {
|
|
if (strncmp(playerNames[i], namePrefix, strlen(namePrefix)) == 0) {
|
|
if (currentIndex == sPlayersTabCompletionIndex) {
|
|
djui_inputbox_replace_current_word(gDjuiChatBox->chatInput, playerNames[i]);
|
|
completionSuccess = true;
|
|
break;
|
|
}
|
|
currentIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (s32 i = 0; playerNames[i] != NULL; i++) {
|
|
free(playerNames[i]);
|
|
}
|
|
free(playerNames);
|
|
|
|
return completionSuccess;
|
|
}
|
|
|
|
static bool handle_tab_completion(void) {
|
|
bool alreadyTabCompleted = false;
|
|
if (gDjuiChatBox->chatInput->buffer[0] == '/') {
|
|
char* spacePosition = strrchr(sCommandsTabCompletionOriginalText, ' ');
|
|
if (spacePosition != NULL) {
|
|
char* mainCommand = get_main_command_from_input(sCommandsTabCompletionOriginalText);
|
|
if (mainCommand) {
|
|
if (!complete_subcommand(mainCommand + 1, spacePosition + 1)) {
|
|
reset_tab_completion_all();
|
|
} else {
|
|
alreadyTabCompleted = true;
|
|
}
|
|
free(mainCommand);
|
|
}
|
|
} else {
|
|
if (sCommandsTabCompletionIndex == -1) {
|
|
snprintf(sCommandsTabCompletionOriginalText, MAX_MSG_LENGTH, "%s", gDjuiChatBox->chatInput->buffer);
|
|
}
|
|
|
|
char* bufferWithoutSlash = sCommandsTabCompletionOriginalText + 1;
|
|
char** commands = smlua_get_chat_maincommands_list();
|
|
s32 foundCommandsCount = 0;
|
|
|
|
for (s32 i = 0; commands[i] != NULL; i++) {
|
|
if (strncmp(commands[i], bufferWithoutSlash, strlen(bufferWithoutSlash)) == 0) {
|
|
foundCommandsCount++;
|
|
}
|
|
}
|
|
|
|
if (foundCommandsCount > 0) {
|
|
sCommandsTabCompletionIndex = (sCommandsTabCompletionIndex + 1) % foundCommandsCount;
|
|
s32 currentIndex = 0;
|
|
|
|
for (s32 i = 0; commands[i] != NULL; i++) {
|
|
if (strncmp(commands[i], bufferWithoutSlash, strlen(bufferWithoutSlash)) == 0) {
|
|
if (currentIndex == sCommandsTabCompletionIndex) {
|
|
char completion[MAX_MSG_LENGTH];
|
|
snprintf(completion, MAX_MSG_LENGTH, "/%s", commands[i]);
|
|
djui_inputbox_set_text(gDjuiChatBox->chatInput, completion);
|
|
djui_inputbox_move_cursor_to_end(gDjuiChatBox->chatInput);
|
|
alreadyTabCompleted = true;
|
|
}
|
|
currentIndex++;
|
|
}
|
|
}
|
|
} else {
|
|
char* spacePositionB = strrchr(sCommandsTabCompletionOriginalText, ' ');
|
|
if (spacePositionB != NULL) {
|
|
char* mainCommandB = get_main_command_from_input(sCommandsTabCompletionOriginalText);
|
|
if (mainCommandB) {
|
|
if (!complete_subcommand(mainCommandB + 1, spacePositionB + 1)) {
|
|
reset_tab_completion_all();
|
|
} else {
|
|
alreadyTabCompleted = true;
|
|
}
|
|
free(mainCommandB);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (s32 i = 0; commands[i] != NULL; i++) {
|
|
free(commands[i]);
|
|
}
|
|
free(commands);
|
|
}
|
|
}
|
|
if (!alreadyTabCompleted) {
|
|
if (gDjuiChatBox->chatInput->selection[0] != gDjuiChatBox->chatInput->selection[1]) {
|
|
alreadyTabCompleted = true;
|
|
}
|
|
}
|
|
if (!alreadyTabCompleted) {
|
|
CurrentWordInfo wordCurrent = get_current_word_info(gDjuiChatBox->chatInput->buffer, gDjuiChatBox->chatInput->selection[0]);
|
|
if (gDjuiChatBox->chatInput->buffer[0] == '/') {
|
|
if (wordCurrent.index == 1 && smlua_maincommand_exists(wordCurrent.word + 1)) {
|
|
alreadyTabCompleted = true;
|
|
} else if (wordCurrent.index == 2) {
|
|
CurrentWordInfo worldMainCommand = get_current_word_info(gDjuiChatBox->chatInput->buffer, 0);
|
|
if (smlua_maincommand_exists(worldMainCommand.word + 1) && smlua_subcommand_exists(worldMainCommand.word + 1, wordCurrent.word)) {
|
|
alreadyTabCompleted = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!alreadyTabCompleted) {
|
|
CurrentWordInfo wordInfo = get_current_word_info(gDjuiChatBox->chatInput->buffer, gDjuiChatBox->chatInput->selection[0]);
|
|
if (wordInfo.index != -1) {
|
|
if (sPlayersTabCompletionIndex == -1) {
|
|
snprintf(sPlayersTabCompletionOriginalText, MAX_MSG_LENGTH, "%s", wordInfo.word);
|
|
}
|
|
if (!complete_player_name(sPlayersTabCompletionOriginalText)) {
|
|
reset_tab_completion_players();
|
|
} else {
|
|
alreadyTabCompleted = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool djui_chat_box_input_on_key_down(struct DjuiBase* base, int scancode) {
|
|
sent_history_init(&sentHistory);
|
|
|
|
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->chatContainer->base.elem.height * 3.0f / 4.0f;
|
|
|
|
char previousText[MAX_MSG_LENGTH];
|
|
snprintf(previousText, MAX_MSG_LENGTH, "%s", gDjuiChatBox->chatInput->buffer);
|
|
|
|
switch (scancode) {
|
|
case SCANCODE_UP:
|
|
sent_history_update_current_message(&sentHistory, gDjuiChatBox->chatInput->buffer);
|
|
sent_history_navigate(&sentHistory, true);
|
|
if (strcmp(previousText, gDjuiChatBox->chatInput->buffer) != 0) {
|
|
reset_tab_completion_all();
|
|
}
|
|
return true;
|
|
case SCANCODE_DOWN:
|
|
sent_history_update_current_message(&sentHistory, gDjuiChatBox->chatInput->buffer);
|
|
sent_history_navigate(&sentHistory, false);
|
|
if (strcmp(previousText, gDjuiChatBox->chatInput->buffer) != 0) {
|
|
reset_tab_completion_all();
|
|
}
|
|
return true;
|
|
case SCANCODE_PAGE_UP:
|
|
gDjuiChatBox->scrolling = true;
|
|
if (canScrollDown) { *yValue = fmin(*yValue + 15, 0); }
|
|
return true;
|
|
case SCANCODE_PAGE_DOWN:
|
|
gDjuiChatBox->scrolling = true;
|
|
if (canScrollUp) { *yValue = fmax(*yValue - 15, yMax); }
|
|
return true;
|
|
case SCANCODE_POS1:
|
|
gDjuiChatBox->scrolling = true;
|
|
if (canScrollDown) { *yValue = fmin(*yValue + pageAmount, 0); }
|
|
return true;
|
|
case SCANCODE_END:
|
|
gDjuiChatBox->scrolling = true;
|
|
if (canScrollUp) { *yValue = fmax(*yValue - pageAmount, yMax); }
|
|
return true;
|
|
case SCANCODE_TAB:
|
|
handle_tab_completion();
|
|
return true;
|
|
case SCANCODE_ENTER:
|
|
reset_tab_completion_all();
|
|
sent_history_reset_navigation(&sentHistory);
|
|
djui_chat_box_input_enter(gDjuiChatBox->chatInput);
|
|
return true;
|
|
case SCANCODE_ESCAPE:
|
|
reset_tab_completion_all();
|
|
sent_history_reset_navigation(&sentHistory);
|
|
djui_chat_box_input_escape(gDjuiChatBox->chatInput);
|
|
return true;
|
|
default:
|
|
bool returnValueOnOtherKeyDown = djui_inputbox_on_key_down(base, scancode);
|
|
if (strcmp(previousText, gDjuiChatBox->chatInput->buffer) != 0) {
|
|
reset_tab_completion_all();
|
|
}
|
|
return returnValueOnOtherKeyDown;
|
|
}
|
|
}
|
|
|
|
static void djui_chat_box_input_on_text_input(struct DjuiBase *base, char* text) {
|
|
size_t expectedIndex = strlen(gDjuiChatBox->chatInput->buffer);
|
|
bool isTextDifferent = (expectedIndex >= MAX_MSG_LENGTH) || (gDjuiChatBox->chatInput->buffer[expectedIndex] != text[0]);
|
|
djui_inputbox_on_text_input(base, text);
|
|
if (isTextDifferent) {
|
|
reset_tab_completion_all();
|
|
}
|
|
}
|
|
|
|
static void djui_chat_box_input_on_text_input(struct DjuiBase *base, char* text) {
|
|
char previousText[MAX_MSG_LENGTH];
|
|
strncpy(previousText, gDjuiChatBox->chatInput->buffer, MAX_MSG_LENGTH - 1);
|
|
djui_inputbox_on_text_input(base, text);
|
|
if (strcmp(previousText, gDjuiChatBox->chatInput->buffer) != 0) {
|
|
reset_tab_completion_all();
|
|
}
|
|
}
|
|
|
|
|
|
void djui_chat_box_toggle(void) {
|
|
if (gDjuiChatBox == NULL) { return; }
|
|
if (!gDjuiChatBoxFocus) { sDjuiChatBoxClearText = true; }
|
|
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 = calloc(1, 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_ABSOLUTE);
|
|
djui_base_set_size(base, 600, 400);
|
|
djui_base_set_alignment(base, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
|
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);
|
|
djui_interactable_hook_text_input(&chatInput->base, djui_chat_box_input_on_text_input);
|
|
chatBox->chatInput = chatInput;
|
|
|
|
gDjuiChatBox = chatBox;
|
|
djui_chat_box_set_focus_style();
|
|
return chatBox;
|
|
} |