mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-07-07 15:06:47 +00:00
[proximity chat] muting and per-player volume
This commit is contained in:
parent
3242b0bf0b
commit
6b0e1b01c9
21 changed files with 247 additions and 31 deletions
|
|
@ -67,6 +67,14 @@ ALIGNED8 const Texture texture_microphone_muted[] = {
|
|||
#include "textures/segment2/custom_microphone_muted.rgba16.inc.c"
|
||||
};
|
||||
|
||||
ALIGNED8 const Texture texture_microphone_red[] = {
|
||||
#include "textures/segment2/custom_microphone_red.rgba16.inc.c"
|
||||
};
|
||||
|
||||
ALIGNED8 const Texture texture_microphone_red_muted[] = {
|
||||
#include "textures/segment2/custom_microphone_red_muted.rgba16.inc.c"
|
||||
};
|
||||
|
||||
ALIGNED8 const Texture texture_microphone_warning[] = {
|
||||
#include "textures/segment2/custom_microphone_warning.rgba16.inc.c"
|
||||
};
|
||||
|
|
@ -1562,6 +1562,8 @@ extern ALIGNED8 const Texture texture_ping_four[];
|
|||
extern ALIGNED8 const Texture texture_ping_full[];
|
||||
extern ALIGNED8 const Texture texture_microphone[];
|
||||
extern ALIGNED8 const Texture texture_microphone_muted[];
|
||||
extern ALIGNED8 const Texture texture_microphone_red[];
|
||||
extern ALIGNED8 const Texture texture_microphone_red_muted[];
|
||||
extern ALIGNED8 const Texture texture_microphone_warning[];
|
||||
extern ALIGNED8 const Texture pss_seg7_texture_07000000[];
|
||||
extern ALIGNED8 const Texture pss_seg7_texture_07000800[];
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,8 @@ static const struct BuiltinTexInfo sDynosBuiltinTexs[] = {
|
|||
// Proximity Chat Microphone Icons
|
||||
define_builtin_tex(texture_microphone, "textures/segment2/custom_microphone.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
|
||||
define_builtin_tex(texture_microphone_muted, "textures/segment2/custom_microphone_muted.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
|
||||
define_builtin_tex(texture_microphone_red, "textures/segment2/custom_microphone_red.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
|
||||
define_builtin_tex(texture_microphone_red_muted, "textures/segment2/custom_microphone_red_muted.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
|
||||
define_builtin_tex(texture_microphone_warning, "textures/segment2/custom_microphone_warning.rgba16.png", 16, 16, G_IM_FMT_RGBA, G_IM_SIZ_16b),
|
||||
|
||||
// Goddard
|
||||
|
|
|
|||
|
|
@ -373,6 +373,7 @@ PLAYER = "Hráč"
|
|||
DYNOS_PACKS = "DynOS packy"
|
||||
OPTIONS = "Nastavení"
|
||||
CHEATS = "Cheaty"
|
||||
PROXIMITY_CHAT = "Proximity chat"
|
||||
SERVER_SETTINGS = "Nastavení serveru"
|
||||
RESUME = "Pokračovat"
|
||||
STOP_HOSTING = "Vypnout server"
|
||||
|
|
|
|||
|
|
@ -373,6 +373,7 @@ PLAYER = "Player"
|
|||
DYNOS_PACKS = "DynOS Packs"
|
||||
OPTIONS = "Options"
|
||||
CHEATS = "Cheats"
|
||||
PROXIMITY_CHAT = "Proximity Chat"
|
||||
SERVER_SETTINGS = "Server Settings"
|
||||
RESUME = "Resume"
|
||||
STOP_HOSTING = "Stop Hosting"
|
||||
|
|
|
|||
|
|
@ -599,12 +599,13 @@ void render_hud_proxchat(void) {
|
|||
|
||||
const Texture* tex = NULL;
|
||||
if (proxchat_error[0] != PROXCHAT_ERR_NONE) tex = texture_microphone_warning;
|
||||
else if (*proxchat_player_muted(0) & PROXCHAT_MUTE_GLOBAL) tex = texture_microphone_red_muted;
|
||||
else if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) {
|
||||
if (proxchat_muted) tex = texture_microphone_muted;
|
||||
if (*proxchat_player_muted(0) != PROXCHAT_UNMUTED) tex = texture_microphone_muted;
|
||||
else tex = texture_microphone;
|
||||
}
|
||||
else if (configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) {
|
||||
if (proxchat_muted) tex = texture_microphone_muted;
|
||||
if (*proxchat_player_muted(0) != PROXCHAT_UNMUTED) tex = texture_microphone_muted;
|
||||
else if (proxchat_player_is_talking(0)) tex = texture_microphone;
|
||||
else tex = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static void djui_button_destroy(struct DjuiBase* base) {
|
|||
free(button);
|
||||
}
|
||||
|
||||
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
|
||||
static struct DjuiButton* djui_button_create_base(struct DjuiBase* parent, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
|
||||
struct DjuiButton* button = calloc(1, sizeof(struct DjuiButton));
|
||||
struct DjuiBase* base = &button->base;
|
||||
|
||||
|
|
@ -62,7 +62,18 @@ struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* messa
|
|||
djui_base_set_size(&rect->base, 1.0f, 1.0f);
|
||||
button->rect = rect;
|
||||
|
||||
struct DjuiText* text = djui_text_create(&rect->base, message);
|
||||
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(base, 1.0f, configDjuiThemeCenter ? 50 : 64);
|
||||
djui_interactable_hook_click(base, on_click);
|
||||
button->style = style;
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*)) {
|
||||
struct DjuiButton* button = djui_button_create_base(parent, style, on_click);
|
||||
|
||||
struct DjuiText* text = djui_text_create(&button->rect->base, message);
|
||||
struct DjuiColor color = gDjuiThemes[configDjuiTheme]->interactables.textColor;
|
||||
|
||||
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_RELATIVE);
|
||||
|
|
@ -72,11 +83,19 @@ struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* messa
|
|||
djui_text_set_drop_shadow(text, 64, 64, 64, 100);
|
||||
button->text = text;
|
||||
|
||||
djui_base_set_size_type(base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(base, 1.0f, configDjuiThemeCenter ? 50 : 64);
|
||||
djui_interactable_hook_click(base, on_click);
|
||||
button->style = style;
|
||||
djui_button_update_style(base);
|
||||
djui_button_update_style(&button->base);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
struct DjuiButton* djui_image_button_create(struct DjuiBase* parent, const Texture* tex, u16 width, u16 height, u8 fmt, u8 siz, enum DjuiButtonStyle style, void(*on_click)(struct DjuiBase*)) {
|
||||
struct DjuiButton* button = djui_button_create_base(parent, style, on_click);
|
||||
|
||||
struct DjuiImage* icon = djui_image_create(&button->rect->base, tex, width, height, fmt, siz);
|
||||
djui_base_set_alignment(&icon->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_CENTER);
|
||||
button->icon = icon;
|
||||
|
||||
djui_button_update_style(&button->base);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
struct DjuiButton {
|
||||
struct DjuiBase base;
|
||||
struct DjuiRect* rect;
|
||||
struct DjuiText* text;
|
||||
union {
|
||||
struct DjuiText* text;
|
||||
struct DjuiImage* icon;
|
||||
};
|
||||
u8 style;
|
||||
};
|
||||
|
||||
|
|
@ -16,5 +19,6 @@ enum DjuiButtonStyle {
|
|||
void djui_button_set_style(struct DjuiButton* button, enum DjuiButtonStyle style);
|
||||
|
||||
struct DjuiButton* djui_button_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));
|
||||
struct DjuiButton* djui_image_button_create(struct DjuiBase* parent, const Texture* tex, u16 width, u16 height, u8 fmt, u8 siz, enum DjuiButtonStyle style, void(*on_click)(struct DjuiBase*));
|
||||
struct DjuiButton* djui_button_left_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));
|
||||
struct DjuiButton* djui_button_right_create(struct DjuiBase* parent, const char* message, enum DjuiButtonStyle style, void (*on_click)(struct DjuiBase*));
|
||||
|
|
|
|||
|
|
@ -226,9 +226,14 @@ bool djui_interactable_on_key_down(int scancode) {
|
|||
if (scancode == (int)configKeyPushToTalk[i]) pressPushToTalk = true;
|
||||
}
|
||||
|
||||
u32* mute_state = proxchat_player_muted(0);
|
||||
if (pressChat) djui_chat_box_toggle();
|
||||
if (pressMute && configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) proxchat_muted ^= 1; // flip
|
||||
if (pressPushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) proxchat_muted = false;
|
||||
if (pressMute && configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD) {
|
||||
if (*mute_state & PROXCHAT_MUTE_LOCAL) *mute_state &= ~PROXCHAT_MUTE_LOCAL;
|
||||
else *mute_state |= PROXCHAT_MUTE_LOCAL;
|
||||
}
|
||||
if (pressPushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
|
||||
*mute_state &= ~PROXCHAT_MUTE_LOCAL;
|
||||
|
||||
return pressChat || pressMute || pressPushToTalk;
|
||||
}
|
||||
|
|
@ -291,7 +296,8 @@ void djui_interactable_on_key_up(int scancode) {
|
|||
}
|
||||
|
||||
if (toggleConsole) djui_console_toggle();
|
||||
if (disablePushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) proxchat_muted = true;
|
||||
if (disablePushToTalk && configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
|
||||
*proxchat_player_muted(0) |= PROXCHAT_MUTE_LOCAL;
|
||||
}
|
||||
|
||||
if (gDjuiPlayerList != NULL || gDjuiModList != NULL) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "djui_panel_menu.h"
|
||||
#include "djui_panel_confirm.h"
|
||||
#include "djui_panel_mod_menu.h"
|
||||
#include "djui_panel_proximity_chat.h"
|
||||
#include "pc/pc_main.h"
|
||||
#include "pc/network/network.h"
|
||||
#include "pc/lua/smlua_hooks.h"
|
||||
|
|
@ -75,6 +76,9 @@ void djui_panel_pause_create(struct DjuiBase* caller) {
|
|||
djui_button_create(body, DLANG(PAUSE, SERVER_SETTINGS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_client_server_settings_create);
|
||||
}
|
||||
|
||||
if (gServerSettings.proximityChat)
|
||||
djui_button_create(body, DLANG(PAUSE, PROXIMITY_CHAT), DJUI_BUTTON_STYLE_NORMAL, djui_panel_proximity_chat_ingame_create);
|
||||
|
||||
struct Mod* addedMods[MAX_HOOKED_MOD_MENU_ELEMENTS] = { 0 };
|
||||
int modCount = 0;
|
||||
for (int i = 0; i < gHookedModMenuElementsCount; i++) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "pc/configfile.h"
|
||||
#include "pc/proximity_chat.h"
|
||||
#include "pc/lua/utils/smlua_audio_utils.h"
|
||||
#include "pc/network/network.h"
|
||||
#include "pc/utils/misc.h"
|
||||
|
||||
static struct DjuiBase* activation_threshold_slider;
|
||||
static float threshold;
|
||||
|
|
@ -14,7 +16,10 @@ static void djui_panel_sound_value_change(UNUSED struct DjuiBase* caller) {
|
|||
|
||||
static void djui_panel_mode_value_change(UNUSED struct DjuiBase* caller) {
|
||||
djui_base_set_enabled(activation_threshold_slider, configProxchatActivationMode == PROXCHAT_ACTMODE_THRESHOLD);
|
||||
proxchat_muted = configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK;
|
||||
|
||||
u32* mute_state = proxchat_player_muted(0);
|
||||
if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK) *mute_state |= PROXCHAT_MUTE_LOCAL;
|
||||
else *mute_state &= ~PROXCHAT_MUTE_LOCAL;
|
||||
}
|
||||
|
||||
static void djui_panel_threshold_value_change(UNUSED struct DjuiBase* caller) {
|
||||
|
|
@ -52,3 +57,119 @@ void djui_panel_proximity_chat_create(struct DjuiBase* caller) {
|
|||
|
||||
djui_panel_add(caller, panel, NULL);
|
||||
}
|
||||
|
||||
static struct DjuiImage* djui_texture_create(struct DjuiBase* base, struct TextureInfo* info) {
|
||||
return djui_image_create(base, info->texture, info->width, info->height, info->format, info->size);
|
||||
}
|
||||
|
||||
static struct DjuiPaginated* sPlayerPaginated;
|
||||
static struct DjuiFlowLayout* sPlayerLayout;
|
||||
static struct DjuiInputbox* sSearchInputbox = NULL;
|
||||
|
||||
static struct MicButton {
|
||||
bool global;
|
||||
s32 player_id;
|
||||
struct DjuiBase* base;
|
||||
struct DjuiButton* button;
|
||||
} sMicButtons[32];
|
||||
|
||||
static void toggle_mute(struct DjuiBase* caller) {
|
||||
struct MicButton* mic = NULL;
|
||||
for (int i = 0; i < 32 && !mic; i++) {
|
||||
if (sMicButtons[i].base == caller) mic = &sMicButtons[i];
|
||||
}
|
||||
if (!mic) return;
|
||||
|
||||
u32* mute_state = proxchat_player_muted(mic->player_id);
|
||||
if (mic->global) {
|
||||
if (*mute_state & PROXCHAT_MUTE_GLOBAL) *mute_state &= ~PROXCHAT_MUTE_GLOBAL;
|
||||
else *mute_state |= PROXCHAT_MUTE_GLOBAL;
|
||||
dynos_texture_get(*mute_state & PROXCHAT_MUTE_GLOBAL ? "texture_microphone_red_muted" : "texture_microphone_red", &mic->button->icon->textureInfo);
|
||||
network_send_proxchat_muted(gNetworkPlayers[mic->player_id].globalIndex, *mute_state & PROXCHAT_MUTE_GLOBAL);
|
||||
}
|
||||
else {
|
||||
if (*mute_state & PROXCHAT_MUTE_LOCAL) *mute_state &= ~PROXCHAT_MUTE_LOCAL;
|
||||
else *mute_state |= PROXCHAT_MUTE_LOCAL;
|
||||
dynos_texture_get(*mute_state & PROXCHAT_MUTE_LOCAL ? "texture_microphone_muted" : "texture_microphone", &mic->button->icon->textureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
#define TEXTURE_INFO(tex) (tex).texture, (tex).width, (tex).height, (tex).format, (tex).size
|
||||
|
||||
static void djui_panel_proximity_chat_add_players(struct DjuiBase* body) {
|
||||
s32 button_counter = 0;
|
||||
|
||||
for (int i = 1; i < MAX_PLAYERS; i++) {
|
||||
if (!gNetworkPlayers[i].connected) continue;
|
||||
if (sSearchInputbox != NULL &&
|
||||
sSearchInputbox->buffer != NULL &&
|
||||
!strstr_lowercased(djui_text_get_uncolored_string(NULL, strlen(gNetworkPlayers[i].name) + 1, gNetworkPlayers[i].name), sSearchInputbox->buffer)
|
||||
) continue;
|
||||
|
||||
struct DjuiFlowLayout* layout = djui_flow_layout_create(body);
|
||||
djui_flow_layout_set_flow_direction(layout, DJUI_FLOW_DIR_RIGHT);
|
||||
djui_base_set_size_type(&layout->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&layout->base, 1, 32);
|
||||
djui_base_set_color(&layout->base, 0, 0, 0, 0);
|
||||
|
||||
struct DjuiImage* icon = djui_texture_create(&layout->base, &gMarioStates[i].character->hudHeadTexture);
|
||||
|
||||
struct DjuiFlowLayout* inner_layout = djui_flow_layout_create(&layout->base);
|
||||
djui_flow_layout_set_flow_direction(inner_layout, DJUI_FLOW_DIR_LEFT);
|
||||
djui_base_set_size_type(&inner_layout->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&inner_layout->base, 1, 32);
|
||||
djui_base_set_color(&inner_layout->base, 0, 0, 0, 0);
|
||||
|
||||
struct TextureInfo lmute_tex, gmute_tex;
|
||||
dynos_texture_get(*proxchat_player_muted(i) & PROXCHAT_MUTE_LOCAL ? "texture_microphone_muted" : "texture_microphone", &lmute_tex);
|
||||
dynos_texture_get(*proxchat_player_muted(i) & PROXCHAT_MUTE_GLOBAL ? "texture_microphone_red_muted" : "texture_microphone_red", &gmute_tex);
|
||||
|
||||
struct DjuiButton* gmute = djui_image_button_create(&inner_layout->base, TEXTURE_INFO(gmute_tex), DJUI_BUTTON_STYLE_NORMAL, toggle_mute);
|
||||
struct DjuiButton* lmute = djui_image_button_create(&inner_layout->base, TEXTURE_INFO(lmute_tex), DJUI_BUTTON_STYLE_NORMAL, toggle_mute);
|
||||
struct DjuiSlider* vol = djui_slider_create(&inner_layout->base, gNetworkPlayers[i].name, proxchat_player_volume(i), 0, 100, NULL);
|
||||
|
||||
sMicButtons[button_counter++] = (struct MicButton){ .base = &lmute->base, .button = lmute, .player_id = i, .global = false };
|
||||
sMicButtons[button_counter++] = (struct MicButton){ .base = &gmute->base, .button = gmute, .player_id = i, .global = true };
|
||||
|
||||
djui_base_set_alignment(&vol->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
|
||||
djui_base_set_alignment(&lmute->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
|
||||
djui_base_set_alignment(&gmute->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_CENTER);
|
||||
|
||||
djui_base_set_size(&icon->base, 32, 32);
|
||||
djui_base_set_size(&lmute->text->base, 32, 32);
|
||||
djui_base_set_size(&gmute->text->base, 32, 32);
|
||||
|
||||
djui_base_set_size_type(&lmute->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size_type(&gmute->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_size(&lmute->base, 32, 32);
|
||||
djui_base_set_size(&gmute->base, 32, 32);
|
||||
|
||||
djui_base_set_enabled(&gmute->base, gNetworkPlayers[0].moderator || gNetworkPlayers[0].globalIndex == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void djui_panel_rebuild_players_list(UNUSED struct DjuiBase* caller) {
|
||||
djui_base_destroy_children(&sPlayerLayout->base);
|
||||
sPlayerLayout = sPlayerPaginated->layout;
|
||||
djui_panel_proximity_chat_add_players(&sPlayerLayout->base);
|
||||
djui_paginated_calculate_height(sPlayerPaginated);
|
||||
}
|
||||
|
||||
void djui_panel_proximity_chat_ingame_create(struct DjuiBase* caller) {
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(PROXCHAT, PROXIMITY_CHAT), false);
|
||||
struct DjuiBase* body = djui_three_panel_get_body(panel);
|
||||
{
|
||||
struct DjuiSearchbox* searchbox = djui_searchbox_create(body, djui_panel_rebuild_players_list);
|
||||
sSearchInputbox = searchbox->inputbox;
|
||||
|
||||
sPlayerPaginated = djui_paginated_create(body, 8);
|
||||
sPlayerPaginated->showMaxCount = true;
|
||||
sPlayerLayout = sPlayerPaginated->layout;
|
||||
djui_panel_proximity_chat_add_players(&sPlayerLayout->base);
|
||||
djui_paginated_calculate_height(sPlayerPaginated);
|
||||
|
||||
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_proxchat_back);
|
||||
}
|
||||
|
||||
djui_panel_add(caller, panel, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
#include "djui.h"
|
||||
|
||||
void djui_panel_proximity_chat_create(struct DjuiBase* caller);
|
||||
void djui_panel_proximity_chat_ingame_create(struct DjuiBase* caller);
|
||||
|
|
@ -70,9 +70,9 @@ static void djui_slider_on_cursor_down(struct DjuiBase* base) {
|
|||
f32 x = slider->rect->base.elem.x;
|
||||
f32 w = slider->rect->base.elem.width;
|
||||
f32 cursorX = gCursorX;
|
||||
cursorX = fmax(cursorX, x);
|
||||
cursorX = fmin(cursorX, x + w);
|
||||
*value = ((cursorX - x) / w) * (max - min) + min;
|
||||
if (cursorX < x) *value = min;
|
||||
else if (cursorX > x + w) *value = max;
|
||||
else *value = ((cursorX - x) / w) * (max - min) + min;
|
||||
if (base != NULL && base->interactable != NULL && base->interactable->on_value_change != NULL) {
|
||||
base->interactable->on_value_change(base);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,9 +173,12 @@ void nametags_render(void) {
|
|||
|
||||
|
||||
// render mic icon
|
||||
if (proxchat_player_is_talking(playerIndex)) {
|
||||
const char* mic = NULL;
|
||||
if (*proxchat_player_muted(playerIndex) & PROXCHAT_MUTE_GLOBAL) mic = "texture_microphone_red_muted";
|
||||
else if (proxchat_player_is_talking(playerIndex)) mic = "texture_microphone";
|
||||
if (mic) {
|
||||
struct TextureInfo texture;
|
||||
dynos_texture_get("texture_microphone", &texture);
|
||||
dynos_texture_get(mic, &texture);
|
||||
djui_hud_render_texture_interpolated(&texture,
|
||||
e->prevPos[0] - prevHalfWidth - 36 * e->prevScale, prevNametagPosY, e->prevScale * 2, e->prevScale * 2,
|
||||
nametag->pos[0] - currHalfWidth - 36 * nametag->scale, currNametagPosY, nametag->scale * 2, nametag->scale * 2
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ void packet_process(struct Packet* p) {
|
|||
case PACKET_NETWORK_PLAYERS: network_receive_network_players(p); break;
|
||||
case PACKET_DEATH: network_receive_death(p); break;
|
||||
case PACKET_PROXCHAT_FRAME: network_receive_proxchat_frame(p); break;
|
||||
case PACKET_PROXCHAT_GLOBAL_MUTE: network_receive_proxchat_muted(p); break;
|
||||
|
||||
case PACKET_PING: network_receive_ping(p); break;
|
||||
case PACKET_PONG: network_receive_pong(p); break;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ enum PacketType {
|
|||
PACKET_NETWORK_PLAYERS,
|
||||
PACKET_DEATH,
|
||||
PACKET_PROXCHAT_FRAME,
|
||||
PACKET_PROXCHAT_GLOBAL_MUTE,
|
||||
|
||||
PACKET_PING,
|
||||
PACKET_PONG,
|
||||
|
|
@ -282,6 +283,8 @@ void network_receive_death(struct Packet* p);
|
|||
// packet_proxchat.c
|
||||
void network_send_proxchat_frame(void);
|
||||
void network_receive_proxchat_frame(struct Packet* p);
|
||||
void network_send_proxchat_muted(s32 globalIndex, bool mute);
|
||||
void network_receive_proxchat_muted(struct Packet* p);
|
||||
|
||||
// packet_ping.c
|
||||
void network_send_ping(struct NetworkPlayer* toNp);
|
||||
|
|
|
|||
|
|
@ -23,5 +23,31 @@ void network_receive_proxchat_frame(struct Packet* p) {
|
|||
u8 frame_data[frame_size];
|
||||
packet_read(p, frame_data, frame_size);
|
||||
|
||||
proxchat_decode_audio(p->localIndex, frame_data, frame_size);
|
||||
proxchat_decode_audio(
|
||||
network_player_from_global_index(p->orderedFromGlobalId)->localIndex,
|
||||
frame_data, frame_size
|
||||
);
|
||||
}
|
||||
|
||||
void network_send_proxchat_muted(s32 globalIndex, bool muted) {
|
||||
struct Packet p = {};
|
||||
|
||||
packet_init(&p, PACKET_PROXCHAT_GLOBAL_MUTE, false, PLMT_NONE);
|
||||
packet_write(&p, &globalIndex, sizeof(s32));
|
||||
packet_write(&p, &muted, sizeof(bool));
|
||||
|
||||
network_send(&p);
|
||||
}
|
||||
|
||||
void network_receive_proxchat_muted(struct Packet* p) {
|
||||
s32 globalIndex;
|
||||
bool muted;
|
||||
|
||||
packet_read(p, &globalIndex, sizeof(s32));
|
||||
packet_read(p, &muted, sizeof(bool));
|
||||
|
||||
if (!network_player_from_global_index(p->orderedFromGlobalId)->moderator) return;
|
||||
|
||||
if (muted) *proxchat_player_muted(network_player_from_global_index(globalIndex)->localIndex) |= PROXCHAT_MUTE_GLOBAL;
|
||||
else *proxchat_player_muted(network_player_from_global_index(globalIndex)->localIndex) &= ~PROXCHAT_MUTE_GLOBAL;
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ typedef struct {
|
|||
} Buffer;
|
||||
|
||||
static struct {
|
||||
bool muted;
|
||||
u32 muted_state;
|
||||
u32 volume;
|
||||
Buffer audio;
|
||||
union {
|
||||
|
|
@ -40,7 +40,6 @@ static struct {
|
|||
|
||||
static bool inited = false;
|
||||
|
||||
bool proxchat_muted = false;
|
||||
bool proxchat_loopback = false;
|
||||
float proxchat_mic_level = 0;
|
||||
|
||||
|
|
@ -168,7 +167,8 @@ static void proxchat_callback(const u8* input, u32 bytes) {
|
|||
|
||||
if (!inited || gNetworkType == NT_NONE ||
|
||||
configProxchatActivationMode == PROXCHAT_ACTMODE_DISABLED ||
|
||||
!gServerSettings.proximityChat || proxchat_muted || is_below_threshold()
|
||||
!gServerSettings.proximityChat || client->muted_state != PROXCHAT_UNMUTED ||
|
||||
is_below_threshold()
|
||||
) {
|
||||
// drain the pcm buffer
|
||||
buffer_drain(&client->audio);
|
||||
|
|
@ -202,10 +202,11 @@ void proxchat_init() {
|
|||
|
||||
players[i].audio.capacity = FRAME_SIZE * MAX_FRAMES * sizeof(s16);
|
||||
players[i].audio.dynamic = false;
|
||||
players[i].volume = 1;
|
||||
players[i].volume = 100;
|
||||
}
|
||||
|
||||
proxchat_muted = configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK;
|
||||
if (configProxchatActivationMode == PROXCHAT_ACTMODE_PUSH_TO_TALK)
|
||||
client->muted_state |= PROXCHAT_MUTE_LOCAL;
|
||||
|
||||
inited = true;
|
||||
}
|
||||
|
|
@ -225,6 +226,10 @@ bool proxchat_inited() {
|
|||
return inited;
|
||||
}
|
||||
|
||||
u32* proxchat_player_muted(s32 id) {
|
||||
return &players[id].muted_state;
|
||||
}
|
||||
|
||||
u32* proxchat_player_volume(s32 id) {
|
||||
return &players[id].volume;
|
||||
}
|
||||
|
|
@ -276,6 +281,12 @@ void proxchat_mix(s16* out_pcm, u32 num_out_samples) {
|
|||
|
||||
if (proxchat_num_frames_in_buffer(&players[i].audio) < MIN_FRAMES_REQUIRED) continue;
|
||||
|
||||
s16 player_pcm[num_samples];
|
||||
u32 n = buffer_read(&players[i].audio, sizeof(player_pcm), player_pcm) / sizeof(s16);
|
||||
memset(player_pcm + n, 0, sizeof(player_pcm) - n * sizeof(s16));
|
||||
|
||||
if (players[i].muted_state != PROXCHAT_UNMUTED) continue;
|
||||
|
||||
float volume;
|
||||
float dist = vec3f_dist(gMarioStates[i].pos, gMarioState->pos);
|
||||
if (dist < FULL_VOL_RADIUS) volume = 1;
|
||||
|
|
@ -298,10 +309,6 @@ void proxchat_mix(s16* out_pcm, u32 num_out_samples) {
|
|||
float pan_mono = 0.5f + pan * 0.5f * (configProxchatStereoSpread / 100.f);
|
||||
float vol_right = pan_mono;
|
||||
float vol_left = 1 - pan_mono;
|
||||
|
||||
s16 player_pcm[num_samples];
|
||||
u32 n = buffer_read(&players[i].audio, sizeof(player_pcm), player_pcm) / sizeof(s16);
|
||||
memset(player_pcm + n, 0, sizeof(player_pcm) - n * sizeof(s16));
|
||||
|
||||
for (s32 s = 0; s < num_samples * 2; s++) {
|
||||
float pan_factor = s % 2 == 0 ? vol_left : vol_right;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "types.h"
|
||||
|
||||
extern bool proxchat_muted;
|
||||
extern bool proxchat_loopback;
|
||||
extern float proxchat_mic_level;
|
||||
|
||||
|
|
@ -21,13 +20,20 @@ enum ProxchatActivationMode {
|
|||
PROXCHAT_ACTMODE_THRESHOLD
|
||||
};
|
||||
|
||||
enum ProxchatMuteState {
|
||||
PROXCHAT_UNMUTED = 0,
|
||||
|
||||
PROXCHAT_MUTE_LOCAL = (1 << 0),
|
||||
PROXCHAT_MUTE_GLOBAL = (1 << 1),
|
||||
};
|
||||
|
||||
void proxchat_init();
|
||||
bool proxchat_inited();
|
||||
void proxchat_shutdown();
|
||||
|
||||
const Texture* proxchat_get_microphone_texture();
|
||||
|
||||
bool* proxchat_player_muted(s32 id);
|
||||
u32* proxchat_player_muted(s32 id);
|
||||
u32* proxchat_player_volume(s32 id);
|
||||
bool proxchat_player_is_talking(s32 id);
|
||||
|
||||
|
|
|
|||
BIN
textures/segment2/custom_microphone_red.rgba16.png
Normal file
BIN
textures/segment2/custom_microphone_red.rgba16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 470 B |
BIN
textures/segment2/custom_microphone_red_muted.rgba16.png
Normal file
BIN
textures/segment2/custom_microphone_red_muted.rgba16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 631 B |
Loading…
Add table
Reference in a new issue