sm64coopdx/src/pc/djui/djui_hud_utils.c
Agent X 594ff262bc a bunch of fixes (#216)
Nice job targeting the main branch Isaac

Co-Authored-By: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com>
2024-07-17 08:37:42 -04:00

619 lines
21 KiB
C

#include <stdio.h>
#include <PR/ultratypes.h>
#include <PR/gbi.h>
#include <string.h>
#include "pc/controller/controller_mouse.h"
#include "pc/gfx/gfx_pc.h"
#include "pc/gfx/gfx_window_manager_api.h"
#include "pc/pc_main.h"
#include "pc/utils/misc.h"
#include "djui_gfx.h"
#include "gfx_dimensions.h"
#include "config.h"
#include "djui.h"
#include "djui_unicode.h"
#include "djui_hud_utils.h"
#include "djui_panel_pause.h"
#include "game/camera.h"
#include "game/hud.h"
#include "game/rendering_graph_node.h"
#include "game/first_person_cam.h"
#include "pc/lua/smlua.h"
#include "engine/math_util.h"
static enum HudUtilsResolution sResolution = RESOLUTION_DJUI;
static enum HudUtilsFilter sFilter = FILTER_NEAREST;
static enum DjuiFontType sFont = FONT_NORMAL;
static struct HudUtilsRotation sRotation = { 0, 0, 0 };
static struct DjuiColor sColor = { 255, 255, 255, 255 };
static struct DjuiColor sRefColor = { 255, 255, 255, 255 };
static bool sLegacy = false;
f32 gDjuiHudUtilsZ = 0;
u8 gDjuiHudLockMouse = false;
extern ALIGNED8 const u8 texture_hud_char_camera[];
extern ALIGNED8 const u8 texture_hud_char_lakitu[];
extern ALIGNED8 const u8 texture_hud_char_no_camera[];
extern ALIGNED8 const u8 texture_hud_char_arrow_up[];
extern ALIGNED8 const u8 texture_hud_char_arrow_down[];
extern ALIGNED8 const u8 texture_hud_char_coin[];
extern ALIGNED8 const u8 texture_hud_char_star[];
extern ALIGNED8 const u8 texture_hud_char_mario_head[];
extern ALIGNED8 const u8 texture_hud_char_luigi_head[];
extern ALIGNED8 const u8 texture_hud_char_toad_head[];
extern ALIGNED8 const u8 texture_hud_char_waluigi_head[];
extern ALIGNED8 const u8 texture_hud_char_wario_head[];
extern ALIGNED8 const u8 texture_hud_char_apostrophe[];
extern ALIGNED8 const u8 texture_hud_char_double_quote[];
struct GlobalTextures gGlobalTextures = {
.camera = { .texture = (u8*)texture_hud_char_camera, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_camera" },
.lakitu = { .texture = (u8*)texture_hud_char_lakitu, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_lakitu" },
.no_camera = { .texture = (u8*)texture_hud_char_no_camera, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_no_camera" },
.arrow_up = { .texture = (u8*)texture_hud_char_arrow_up, .bitSize = 8, .width = 8, .height = 8, "texture_hud_char_arrow_up" },
.arrow_down = { .texture = (u8*)texture_hud_char_arrow_down, .bitSize = 8, .width = 8, .height = 8, "texture_hud_char_arrow_down" },
.coin = { .texture = (u8*)texture_hud_char_coin, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_coin" },
.star = { .texture = (u8*)texture_hud_char_star, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_star" },
.apostrophe = { .texture = (u8*)texture_hud_char_apostrophe, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_apostrophe" },
.double_quote = { .texture = (u8*)texture_hud_char_double_quote, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_double_quote" },
.mario_head = { .texture = (u8*)texture_hud_char_mario_head, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_mario_head" },
.luigi_head = { .texture = (u8*)texture_hud_char_luigi_head, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_luigi_head" },
.toad_head = { .texture = (u8*)texture_hud_char_toad_head, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_toad_head" },
.waluigi_head = { .texture = (u8*)texture_hud_char_waluigi_head, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_waluigi_head" },
.wario_head = { .texture = (u8*)texture_hud_char_wario_head, .bitSize = 8, .width = 16, .height = 16, "texture_hud_char_wario_head" }
};
static void djui_hud_position_translate(f32* x, f32* y) {
if (sResolution == RESOLUTION_DJUI) {
djui_gfx_position_translate(x, y);
} else {
*x = GFX_DIMENSIONS_FROM_LEFT_EDGE(0) + *x;
*y = SCREEN_HEIGHT - *y;
}
}
static void djui_hud_size_translate(f32* size) {
if (sResolution == RESOLUTION_DJUI) {
djui_gfx_size_translate(size);
}
}
////////////
// interp //
////////////
#define MAX_INTERP_HUD 512
struct InterpHud {
Gfx* headPos;
f32 z;
f32 prevX;
f32 prevY;
f32 x;
f32 y;
f32 prevScaleW;
f32 prevScaleH;
f32 scaleW;
f32 scaleH;
f32 width;
f32 height;
enum HudUtilsResolution resolution;
};
static struct InterpHud sInterpHuds[MAX_INTERP_HUD] = { 0 };
static u16 sInterpHudCount = 0;
static u8 sColorAltered = FALSE;
void patch_djui_hud_before(void) {
sInterpHudCount = 0;
}
void patch_djui_hud(f32 delta) {
f32 savedZ = gDjuiHudUtilsZ;
Gfx* savedHeadPos = gDisplayListHead;
enum HudUtilsResolution savedResolution = sResolution;
for (u16 i = 0; i < sInterpHudCount; i++) {
struct InterpHud* interp = &sInterpHuds[i];
f32 x = delta_interpolate_f32(interp->prevX, interp->x, delta);
f32 y = delta_interpolate_f32(interp->prevY, interp->y, delta);
f32 scaleW = delta_interpolate_f32(interp->prevScaleW, interp->scaleW, delta);
f32 scaleH = delta_interpolate_f32(interp->prevScaleH, interp->scaleH, delta);
sResolution = interp->resolution;
gDjuiHudUtilsZ = interp->z;
gDisplayListHead = interp->headPos;
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// translate scale
f32 translatedW = scaleW;
f32 translatedH = scaleH;
djui_hud_size_translate(&translatedW);
djui_hud_size_translate(&translatedH);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, interp->width * translatedW, interp->height * translatedH, 1.0f);
}
sResolution = savedResolution;
gDisplayListHead = savedHeadPos;
gDjuiHudUtilsZ = savedZ;
}
////////////
// others //
////////////
u8 djui_hud_get_resolution(void) {
return sResolution;
}
void djui_hud_set_resolution(enum HudUtilsResolution resolutionType) {
if (resolutionType >= RESOLUTION_COUNT) { return; }
sResolution = resolutionType;
}
u8 djui_hud_get_filter(void) {
return sFilter;
}
void djui_hud_set_filter(enum HudUtilsFilter filterType) {
if (filterType >= FILTER_COUNT) { return; }
sFilter = filterType;
}
u8 djui_hud_get_font(void) {
return sFont;
}
void djui_hud_set_font(s8 fontType) {
if (fontType >= FONT_COUNT || fontType < -1) { return; }
sLegacy = fontType == -1;
if (sLegacy) { fontType = 0; }
sFont = fontType;
}
struct DjuiColor* djui_hud_get_color(void) {
sRefColor.r = sColor.r;
sRefColor.g = sColor.g;
sRefColor.b = sColor.b;
sRefColor.a = sColor.a;
return &sRefColor;
}
void djui_hud_set_color(u8 r, u8 g, u8 b, u8 a) {
sColor.r = r;
sColor.g = g;
sColor.b = b;
sColor.a = a;
sColorAltered = TRUE;
gDPSetEnvColor(gDisplayListHead++, r, g, b, a);
}
void djui_hud_reset_color(void) {
if (sColorAltered) {
sColor.r = 255;
sColor.g = 255;
sColor.b = 255;
sColor.a = 255;
sColorAltered = FALSE;
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255);
}
}
struct HudUtilsRotation* djui_hud_get_rotation(void) {
return &sRotation;
}
void djui_hud_set_rotation(s16 rotation, f32 pivotX, f32 pivotY) {
sRotation.rotation = (rotation * 180.f) / 0x8000;
sRotation.pivotX = pivotX;
sRotation.pivotY = pivotY;
}
u32 djui_hud_get_screen_width(void) {
u32 windowWidth, windowHeight;
wm_api->get_dimensions(&windowWidth, &windowHeight);
if (sResolution == RESOLUTION_N64) {
return (GFX_DIMENSIONS_ASPECT_RATIO) * SCREEN_HEIGHT;
} else {
return (windowWidth / djui_gfx_get_scale());
}
}
u32 djui_hud_get_screen_height(void) {
u32 windowWidth, windowHeight;
wm_api->get_dimensions(&windowWidth, &windowHeight);
return (sResolution == RESOLUTION_N64)
? SCREEN_HEIGHT
: (windowHeight / djui_gfx_get_scale());
}
f32 djui_hud_get_mouse_x(void) {
controller_mouse_read_window();
return mouse_window_x / djui_gfx_get_scale();
}
f32 djui_hud_get_mouse_y(void) {
controller_mouse_read_window();
return mouse_window_y / djui_gfx_get_scale();
}
f32 djui_hud_get_raw_mouse_x(void) {
return mouse_x;
}
f32 djui_hud_get_raw_mouse_y(void) {
return mouse_y;
}
void djui_hud_set_mouse_locked(bool locked) {
gDjuiHudLockMouse = locked;
}
f32 djui_hud_measure_text(const char* message) {
if (message == NULL) { return 0; }
const struct DjuiFont* font = gDjuiFonts[sFont];
f32 width = 0;
const char* c = message;
while(*c != '\0') {
width += font->char_width((char*)c) * (sLegacy ? 0.5f : 1.0f);
c = djui_unicode_next_char((char*)c);
}
return width * font->defaultFontScale;
}
void djui_hud_print_text(const char* message, f32 x, f32 y, f32 scale) {
if (message == NULL) { return; }
gDjuiHudUtilsZ += 0.01f;
if (sLegacy) { scale *= 0.5f; }
const struct DjuiFont* font = gDjuiFonts[sFont];
f32 fontScale = font->defaultFontScale * scale;
// setup display list
if (font->textBeginDisplayList != NULL) {
gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList);
}
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// compute font size
f32 translatedFontSize = fontScale;
djui_hud_size_translate(&translatedFontSize);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f);
// render the line
f32 addX = 0;
char* c = (char*)message;
while (*c != '\0') {
f32 charWidth = font->char_width(c);
if (*c == '\n' && *c == ' ') {
addX += charWidth;
c++;
continue;
}
// render
font->render_char(c);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth + addX, 0, 0);
addX = 0;
c = djui_unicode_next_char(c);
}
// pop
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
void djui_hud_print_text_interpolated(const char* message, f32 prevX, f32 prevY, f32 prevScale, f32 x, f32 y, f32 scale) {
if (message == NULL) { return; }
f32 savedZ = gDjuiHudUtilsZ;
gDjuiHudUtilsZ += 0.01f;
if (sLegacy) {
prevScale *= 0.5f;
scale *= 0.5f;
}
const struct DjuiFont* font = gDjuiFonts[sFont];
f32 fontScale = font->defaultFontScale * scale;
// setup display list
if (font->textBeginDisplayList != NULL) {
gSPDisplayList(gDisplayListHead++, font->textBeginDisplayList);
}
Gfx* savedHeadPos = gDisplayListHead;
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// compute font size
f32 translatedFontSize = fontScale;
djui_hud_size_translate(&translatedFontSize);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedFontSize, translatedFontSize, 1.0f);
// render the line
f32 addX = 0;
char* c = (char*)message;
while (*c != '\0') {
f32 charWidth = font->char_width(c);
if (*c == '\n' && *c == ' ') {
addX += charWidth;
c++;
continue;
}
// render
font->render_char(c);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, charWidth + addX, 0, 0);
addX = 0;
c = djui_unicode_next_char(c);
}
// pop
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
interp->headPos = savedHeadPos;
interp->prevX = prevX;
interp->prevY = prevY;
interp->prevScaleW = prevScale;
interp->prevScaleH = prevScale;
interp->x = x;
interp->y = y;
interp->scaleW = scale;
interp->scaleH = scale;
interp->width = font->defaultFontScale;
interp->height = font->defaultFontScale;
interp->z = savedZ;
interp->resolution = sResolution;
}
static inline bool is_power_of_two(u32 n) {
return (n > 0) && ((n & (n - 1)) == 0);
}
void djui_hud_render_texture_raw(const u8* texture, u32 bitSize, u32 width, u32 height, f32 x, f32 y, f32 scaleW, f32 scaleH) {
if (!is_power_of_two(width) || !is_power_of_two(height)) {
LOG_LUA_LINE("Tried to render DJUI HUD texture with NPOT width or height");
return;
}
gDjuiHudUtilsZ += 0.01f;
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// rotate
f32 translatedW = scaleW;
f32 translatedH = scaleH;
djui_hud_size_translate(&translatedW);
djui_hud_size_translate(&translatedH);
if (sRotation.rotation != 0) {
f32 pivotTranslationX = width * translatedW * sRotation.pivotX;
f32 pivotTranslationY = height * translatedH * sRotation.pivotY;
create_dl_translation_matrix(DJUI_MTX_NOPUSH, +pivotTranslationX, -pivotTranslationY, 0);
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sRotation.rotation, 0, 0, 1);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
}
// translate scale
create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f);
// render
djui_gfx_render_texture(texture, width, height, bitSize, sFilter);
// pop
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
void djui_hud_render_texture_tile_raw(const u8* texture, u32 bitSize, u32 width, u32 height, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
gDjuiHudUtilsZ += 0.01f;
scaleW *= (f32) tileW / (f32) width;
scaleH *= (f32) tileH / (f32) height;
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// rotate
f32 translatedW = scaleW;
f32 translatedH = scaleH;
djui_hud_size_translate(&translatedW);
djui_hud_size_translate(&translatedH);
if (sRotation.rotation != 0) {
f32 aspect = tileH ? ((f32) tileW / (f32) tileH) : 1.f;
f32 pivotTranslationX = width * translatedW * aspect * sRotation.pivotX;
f32 pivotTranslationY = height * translatedH * sRotation.pivotY;
create_dl_translation_matrix(DJUI_MTX_NOPUSH, +pivotTranslationX, -pivotTranslationY, 0);
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sRotation.rotation, 0, 0, 1);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
}
// translate scale
create_dl_scale_matrix(DJUI_MTX_NOPUSH, width * translatedW, height * translatedH, 1.0f);
// render
djui_gfx_render_texture_tile(texture, width, height, bitSize, tileX, tileY, tileW, tileH, sFilter);
// pop
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH) {
djui_hud_render_texture_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, x, y, scaleW, scaleH);
}
void djui_hud_render_texture_tile(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH);
}
void djui_hud_render_texture_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH) {
Gfx* savedHeadPos = gDisplayListHead;
f32 savedZ = gDjuiHudUtilsZ;
djui_hud_render_texture_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, prevX, prevY, prevScaleW, prevScaleH);
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
interp->headPos = savedHeadPos;
interp->prevX = prevX;
interp->prevY = prevY;
interp->prevScaleW = prevScaleW;
interp->prevScaleH = prevScaleH;
interp->x = x;
interp->y = y;
interp->scaleW = scaleW;
interp->scaleH = scaleH;
interp->width = texInfo->width;
interp->height = texInfo->height;
interp->z = savedZ;
interp->resolution = sResolution;
}
void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {
Gfx* savedHeadPos = gDisplayListHead;
f32 savedZ = gDjuiHudUtilsZ;
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, prevX, prevY, prevScaleW, prevScaleH, tileX, tileY, tileW, tileH);
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
interp->headPos = savedHeadPos;
interp->prevX = prevX;
interp->prevY = prevY;
interp->prevScaleW = prevScaleW;
interp->prevScaleH = prevScaleH;
interp->x = x;
interp->y = y;
interp->scaleW = scaleW;
interp->scaleH = scaleH;
interp->width = texInfo->width;
interp->height = texInfo->height;
interp->z = savedZ;
interp->resolution = sResolution;
}
void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
gDjuiHudUtilsZ += 0.01f;
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// rotate
f32 translatedW = width;
f32 translatedH = height;
djui_hud_size_translate(&translatedW);
djui_hud_size_translate(&translatedH);
if (sRotation.rotation != 0) {
f32 pivotTranslationX = translatedW * sRotation.pivotX;
f32 pivotTranslationY = translatedH * sRotation.pivotY;
create_dl_translation_matrix(DJUI_MTX_NOPUSH, +pivotTranslationX, -pivotTranslationY, 0);
create_dl_rotation_matrix(DJUI_MTX_NOPUSH, sRotation.rotation, 0, 0, 1);
create_dl_translation_matrix(DJUI_MTX_NOPUSH, -pivotTranslationX, +pivotTranslationY, 0);
}
// translate scale
create_dl_scale_matrix(DJUI_MTX_NOPUSH, translatedW, translatedH, 1.0f);
// render
gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect);
// pop
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
void djui_hud_render_rect_interpolated(f32 prevX, f32 prevY, f32 prevWidth, f32 prevHeight, f32 x, f32 y, f32 width, f32 height) {
Gfx* savedHeadPos = gDisplayListHead;
f32 savedZ = gDjuiHudUtilsZ;
djui_hud_render_rect(prevX, prevY, prevWidth, prevHeight);
if (sInterpHudCount >= MAX_INTERP_HUD) { return; }
struct InterpHud* interp = &sInterpHuds[sInterpHudCount++];
interp->headPos = savedHeadPos;
interp->prevX = prevX;
interp->prevY = prevY;
interp->prevScaleW = prevWidth;
interp->prevScaleH = prevHeight;
interp->x = x;
interp->y = y;
interp->scaleW = width;
interp->scaleH = height;
interp->width = 1;
interp->height = 1;
interp->z = savedZ;
interp->resolution = sResolution;
}
static void hud_rotate_and_translate_vec3f(Vec3f vec, Mat4* mtx, Vec3f out) {
out[0] = (*mtx)[0][0] * vec[0] + (*mtx)[1][0] * vec[1] + (*mtx)[2][0] * vec[2];
out[1] = (*mtx)[0][1] * vec[0] + (*mtx)[1][1] * vec[1] + (*mtx)[2][1] * vec[2];
out[2] = (*mtx)[0][2] * vec[0] + (*mtx)[1][2] * vec[1] + (*mtx)[2][2] * vec[2];
out[0] += (*mtx)[3][0];
out[1] += (*mtx)[3][1];
out[2] += (*mtx)[3][2];
}
bool djui_hud_world_pos_to_screen_pos(Vec3f pos, Vec3f out) {
if (!gCamera) { return false; }
hud_rotate_and_translate_vec3f(pos, &gCamera->mtx, out);
if (out[2] >= 0.0f) {
return false;
}
out[0] *= 256.0f / -out[2];
out[1] *= 256.0f / out[2];
// fov of 45.0 is the default fov
f32 fov = get_first_person_enabled() ? gFirstPersonCamera.fov : not_zero(45.0f, gOverrideFOV);
f32 fovDefault = tanf(fov * ((f32)M_PI / 360.0f));
f32 fovCurrent = tanf((fov + gFOVState.fovOffset) * ((f32)M_PI / 360.0f));
f32 fovDifference = (fovDefault / fovCurrent) * 1.13f;
out[0] *= fovDifference;
out[1] *= fovDifference;
out[0] += djui_hud_get_screen_width() / 2.0f;
out[1] += djui_hud_get_screen_height() / 2.0f;
return true;
}
bool djui_hud_is_pause_menu_created(void) {
return gDjuiPanelPauseCreated;
}
void djui_open_pause_menu(void) {
if (!gDjuiPanelPauseCreated) {
djui_panel_pause_create(NULL);
}
}