mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 02:25:32 -04:00
Merge pull request #601 from UnknownShadow200/ScreenRewrite
Merge screen rewrite stuff
This commit is contained in:
commit
d1fb95092e
@ -7,4 +7,10 @@
|
||||
* catbox.moe texture packs/terrain.png links insta-crash the game
|
||||
* Sometimes you randomly crash reading leveldatachunk packet on OSX
|
||||
* Models with size of over 2 are not supported at all
|
||||
* Direct3D9 backend uses an ill-formed vertex format that works by accident
|
||||
* Direct3D9 backend uses an ill-formed vertex format that works by accident
|
||||
* Alt text doesn't update its Y position if you click on chat
|
||||
* Menu inputs (save, edit hotkey, water level, etc) are reset on window resize
|
||||
* Chat input caret is reset on window resize
|
||||
* Position in chat (if you scrolled up into history) is reset on window resize
|
||||
* Two blank lines get shown in chat when you type /client cuboid
|
||||
* Alt text is closed on window resize
|
@ -97,8 +97,7 @@ static void PerspectiveCamera_UpdateMouseRotation(double delta) {
|
||||
}
|
||||
|
||||
static void PerspectiveCamera_UpdateMouse(double delta) {
|
||||
struct Screen* s = Gui_GetActiveScreen();
|
||||
if (!s->handlesAllInput && Window_Focused) Window_UpdateRawMouse();
|
||||
if (!Gui_GetInputGrab() && Window_Focused) Window_UpdateRawMouse();
|
||||
|
||||
PerspectiveCamera_UpdateMouseRotation(delta);
|
||||
cam_deltaX = 0; cam_deltaY = 0;
|
||||
@ -273,7 +272,7 @@ void Camera_Register(struct Camera* cam) {
|
||||
|
||||
static bool cam_focussed;
|
||||
void Camera_CheckFocus(void) {
|
||||
bool focus = !Gui_GetActiveScreen()->handlesAllInput;
|
||||
bool focus = Gui_GetInputGrab() == NULL;
|
||||
if (focus == cam_focussed) return;
|
||||
cam_focussed = focus;
|
||||
|
||||
|
@ -591,6 +591,10 @@ int Drawer2D_TextWidth(struct DrawTextArgs* args) {
|
||||
return width;
|
||||
}
|
||||
|
||||
int Drawer2D_TextHeight(struct DrawTextArgs* args) {
|
||||
return Drawer2D_FontHeight(&args->font, args->useShadow);
|
||||
}
|
||||
|
||||
int Drawer2D_FontHeight(const FontDesc* font, bool useShadow) {
|
||||
int height, point;
|
||||
if (Drawer2D_BitmappedText) {
|
||||
@ -609,7 +613,7 @@ int Drawer2D_FontHeight(const FontDesc* font, bool useShadow) {
|
||||
Size2D Drawer2D_MeasureText(struct DrawTextArgs* args) {
|
||||
Size2D size;
|
||||
size.Width = Drawer2D_TextWidth(args);
|
||||
size.Height = Drawer2D_FontHeight(&args->font, args->useShadow);
|
||||
size.Height = Drawer2D_TextHeight(args);
|
||||
|
||||
if (!size.Width) size.Height = 0;
|
||||
return size;
|
||||
|
@ -63,8 +63,11 @@ void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, Bitmap
|
||||
CC_API void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y);
|
||||
/* Returns how wide the given text would be when drawn. */
|
||||
int Drawer2D_TextWidth(struct DrawTextArgs* args);
|
||||
/* Returns how tall the given text would be when drawn. */
|
||||
/* NOTE: Height returned only depends on the font. (see Drawer2D_FontHeight). */
|
||||
int Drawer2D_TextHeight(struct DrawTextArgs* args);
|
||||
/* Returns size the given text would be when drawn. */
|
||||
/* NOTE: Height returned only depends on the font. (see Drawer2D_FontHeight).*/
|
||||
/* NOTE: Height returned only depends on the font. (see Drawer2D_FontHeight). */
|
||||
CC_API Size2D Drawer2D_MeasureText(struct DrawTextArgs* args);
|
||||
/* Similar to Drawer2D_DrawText, but trims the text with trailing ".." if wider than maxWidth. */
|
||||
void Drawer2D_DrawClippedText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y, int maxWidth);
|
||||
|
@ -781,7 +781,7 @@ static void LocalPlayer_HandleInput(float* xMoving, float* zMoving) {
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
struct HacksComp* hacks = &p->Hacks;
|
||||
|
||||
if (Gui_GetActiveScreen()->handlesAllInput) {
|
||||
if (Gui_GetInputGrab()) {
|
||||
p->Physics.Jumping = false; hacks->Speeding = false;
|
||||
hacks->FlyingUp = false; hacks->FlyingDown = false;
|
||||
} else {
|
||||
|
15
src/Game.c
15
src/Game.c
@ -177,9 +177,8 @@ void Game_UpdateProjection(void) {
|
||||
|
||||
void Game_Disconnect(const String* title, const String* reason) {
|
||||
Event_RaiseVoid(&NetEvents.Disconnected);
|
||||
Gui_FreeActive();
|
||||
DisconnectScreen_Show(title, reason);
|
||||
Game_Reset();
|
||||
DisconnectScreen_Show(title, reason);
|
||||
}
|
||||
|
||||
void Game_Reset(void) {
|
||||
@ -619,7 +618,6 @@ void Game_TakeScreenshot(void) {
|
||||
|
||||
static void Game_RenderFrame(double delta) {
|
||||
struct ScheduledTask entTask;
|
||||
bool allowZoom, visible;
|
||||
float t;
|
||||
|
||||
/* TODO: Should other tasks get called back too? */
|
||||
@ -637,13 +635,9 @@ static void Game_RenderFrame(double delta) {
|
||||
Game_Vertices = 0;
|
||||
|
||||
Camera.Active->UpdateMouse(delta);
|
||||
if (!Window_Focused && !Gui_GetActiveScreen()->handlesAllInput) {
|
||||
Gui_FreeActive();
|
||||
Gui_SetActive(PauseScreen_MakeInstance());
|
||||
}
|
||||
if (!Window_Focused && !Gui_GetInputGrab()) PauseScreen_Show();
|
||||
|
||||
allowZoom = !Gui_Active && !Gui_HUD->handlesAllInput;
|
||||
if (allowZoom && KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL)) {
|
||||
if (KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL) && !Gui_GetInputGrab()) {
|
||||
InputHandler_SetFOV(Game_ZoomFov);
|
||||
}
|
||||
|
||||
@ -656,8 +650,7 @@ static void Game_RenderFrame(double delta) {
|
||||
Camera.CurrentPos = Camera.Active->GetPosition(t);
|
||||
Game_UpdateViewMatrix();
|
||||
|
||||
visible = !Gui_Active || !Gui_Active->blocksWorld;
|
||||
if (visible && World.Blocks) {
|
||||
if (!Gui_GetBlocksWorld() && World.Blocks) {
|
||||
Game_Render3D(delta, t);
|
||||
} else {
|
||||
PickedPos_SetAsInvalid(&Game_SelectedPos);
|
||||
|
249
src/Gui.c
249
src/Gui.c
@ -19,30 +19,9 @@ bool Gui_ClickableChat, Gui_TabAutocomplete, Gui_ShowFPS;
|
||||
GfxResourceID Gui_GuiTex, Gui_GuiClassicTex, Gui_IconsTex;
|
||||
struct Screen* Gui_Status;
|
||||
struct Screen* Gui_HUD;
|
||||
struct Screen* Gui_Active;
|
||||
struct Screen* Gui_Overlays[GUI_MAX_OVERLAYS];
|
||||
int Gui_OverlaysCount;
|
||||
|
||||
void Gui_DefaultRecreate(void* elem) {
|
||||
struct GuiElem* e = (struct GuiElem*)elem;
|
||||
Elem_Free(e); Elem_Init(e);
|
||||
}
|
||||
|
||||
void Screen_CommonInit(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
Event_RegisterVoid(&GfxEvents.ContextLost, s, s->VTABLE->ContextLost);
|
||||
Event_RegisterVoid(&GfxEvents.ContextRecreated, s, s->VTABLE->ContextRecreated);
|
||||
|
||||
if (Gfx.LostContext) return;
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
}
|
||||
|
||||
void Screen_CommonFree(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
Event_UnregisterVoid(&GfxEvents.ContextLost, s, s->VTABLE->ContextLost);
|
||||
Event_UnregisterVoid(&GfxEvents.ContextRecreated, s, s->VTABLE->ContextRecreated);
|
||||
s->VTABLE->ContextLost(s);
|
||||
}
|
||||
struct Screen* Gui_Screens[GUI_MAX_SCREENS];
|
||||
int Gui_ScreensCount;
|
||||
static uint8_t priorities[GUI_MAX_SCREENS];
|
||||
|
||||
void Widget_SetLocation(void* widget, uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset) {
|
||||
struct Widget* w = (struct Widget*)widget;
|
||||
@ -91,9 +70,29 @@ bool Gui_Contains(int recX, int recY, int width, int height, int x, int y) {
|
||||
return x >= recX && y >= recY && x < (recX + width) && y < (recY + height);
|
||||
}
|
||||
|
||||
CC_NOINLINE static void Gui_RecreateScreen(struct Screen* screen) {
|
||||
if (Gfx.LostContext || !screen) return;
|
||||
Elem_Recreate(screen);
|
||||
void Gui_ShowDefault(void) {
|
||||
StatusScreen_Show();
|
||||
HUDScreen_Show();
|
||||
}
|
||||
|
||||
static void Gui_ContextLost(void* obj) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
s->VTABLE->ContextLost(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void Gui_ContextRecreated(void* obj) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void Gui_LoadOptions(void) {
|
||||
@ -108,11 +107,7 @@ static void Gui_LoadOptions(void) {
|
||||
Gui_ShowFPS = Options_GetBool(OPT_SHOW_FPS, true);
|
||||
}
|
||||
|
||||
static void Gui_FontChanged(void* obj) {
|
||||
Gui_RecreateScreen(Gui_Active);
|
||||
Gui_RecreateScreen(Gui_Status);
|
||||
Gui_RecreateScreen(Gui_HUD);
|
||||
}
|
||||
static void Gui_FontChanged(void* obj) { Gui_RefreshAll(); }
|
||||
|
||||
static void Gui_FileChanged(void* obj, struct Stream* stream, const String* name) {
|
||||
if (String_CaselessEqualsConst(name, "gui.png")) {
|
||||
@ -127,29 +122,23 @@ static void Gui_FileChanged(void* obj, struct Stream* stream, const String* name
|
||||
static void Gui_Init(void) {
|
||||
Event_RegisterVoid(&ChatEvents.FontChanged, NULL, Gui_FontChanged);
|
||||
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, Gui_FileChanged);
|
||||
Event_RegisterVoid(&GfxEvents.ContextLost, NULL, Gui_ContextLost);
|
||||
Event_RegisterVoid(&GfxEvents.ContextRecreated, NULL, Gui_ContextRecreated);
|
||||
Gui_LoadOptions();
|
||||
|
||||
StatusScreen_Show();
|
||||
HUDScreen_Show();
|
||||
Elem_Init(Gui_Status);
|
||||
Elem_Init(Gui_HUD);
|
||||
Gui_ShowDefault();
|
||||
}
|
||||
|
||||
static void Gui_Reset(void) {
|
||||
int i;
|
||||
for (i = 0; i < Gui_OverlaysCount; i++) {
|
||||
Elem_TryFree(Gui_Overlays[i]);
|
||||
}
|
||||
Gui_OverlaysCount = 0;
|
||||
/* TODO:Should we reset all screens here.. ? */
|
||||
}
|
||||
|
||||
static void Gui_Free(void) {
|
||||
Event_UnregisterVoid(&ChatEvents.FontChanged, NULL, Gui_FontChanged);
|
||||
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, Gui_FileChanged);
|
||||
Event_UnregisterVoid(&GfxEvents.ContextLost, NULL, Gui_ContextLost);
|
||||
Event_UnregisterVoid(&GfxEvents.ContextRecreated, NULL, Gui_ContextRecreated);
|
||||
|
||||
if (Gui_Active) Elem_TryFree(Gui_Active);
|
||||
Elem_TryFree(Gui_Status);
|
||||
Elem_TryFree(Gui_HUD);
|
||||
while (Gui_ScreensCount) Gui_Remove(Gui_Screens[0]);
|
||||
|
||||
Gfx_DeleteTexture(&Gui_GuiTex);
|
||||
Gfx_DeleteTexture(&Gui_GuiClassicTex);
|
||||
@ -165,95 +154,135 @@ struct IGameComponent Gui_Component = {
|
||||
NULL, /* OnNewMapLoaded */
|
||||
};
|
||||
|
||||
struct Screen* Gui_GetActiveScreen(void) {
|
||||
return Gui_OverlaysCount ? Gui_Overlays[0] : Gui_GetUnderlyingScreen();
|
||||
void Gui_RefreshAll(void) {
|
||||
Gui_ContextLost(NULL);
|
||||
Gui_ContextRecreated(NULL);
|
||||
}
|
||||
|
||||
struct Screen* Gui_GetUnderlyingScreen(void) {
|
||||
return Gui_Active ? Gui_Active : Gui_HUD;
|
||||
void Gui_RefreshHud(void) { Gui_Refresh(Gui_HUD); }
|
||||
void Gui_Refresh(struct Screen* s) {
|
||||
s->VTABLE->ContextLost(s);
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
}
|
||||
|
||||
void Gui_FreeActive(void) {
|
||||
if (Gui_Active) { Elem_TryFree(Gui_Active); }
|
||||
}
|
||||
void Gui_Close(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
if (s) { Elem_TryFree(s); }
|
||||
if (s == Gui_Active) Gui_SetActive(NULL);
|
||||
}
|
||||
|
||||
void Gui_CloseActive(void) { Gui_Close(Gui_Active); }
|
||||
|
||||
void Gui_SetActive(struct Screen* screen) {
|
||||
InputHandler_ScreenChanged(Gui_Active, screen);
|
||||
Gui_Active = screen;
|
||||
|
||||
if (screen) {
|
||||
Elem_Init(screen);
|
||||
/* for selecting active button etc */
|
||||
Elem_HandlesMouseMove(screen, Mouse_X, Mouse_Y);
|
||||
}
|
||||
Camera_CheckFocus();
|
||||
}
|
||||
void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); }
|
||||
|
||||
void Gui_ShowOverlay(struct Screen* screen) {
|
||||
if (Gui_OverlaysCount == GUI_MAX_OVERLAYS) {
|
||||
Logger_Abort("Gui_ShowOverlay - hit max count");
|
||||
}
|
||||
|
||||
Gui_Overlays[Gui_OverlaysCount] = screen;
|
||||
Gui_OverlaysCount++;
|
||||
|
||||
Elem_Init(screen);
|
||||
Camera_CheckFocus();
|
||||
}
|
||||
|
||||
int Gui_IndexOverlay(const void* screen) {
|
||||
int Gui_Index(struct Screen* s) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_OverlaysCount; i++) {
|
||||
if (Gui_Overlays[i] == screen) return i;
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
if (Gui_Screens[i] == s) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Gui_RemoveOverlay(const void* screen) {
|
||||
int i = Gui_IndexOverlay(screen);
|
||||
if (i == -1) return;
|
||||
static void Gui_AddCore(struct Screen* s, int priority) {
|
||||
int i, j;
|
||||
if (Gui_ScreensCount >= GUI_MAX_SCREENS) Logger_Abort("Hit max screens");
|
||||
|
||||
for (; i < Gui_OverlaysCount - 1; i++) {
|
||||
Gui_Overlays[i] = Gui_Overlays[i + 1];
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
if (priority <= priorities[i]) continue;
|
||||
|
||||
/* Shift lower priority screens right */
|
||||
for (j = Gui_ScreensCount; j > i; j--) {
|
||||
Gui_Screens[j] = Gui_Screens[j - 1];
|
||||
priorities[j] = priorities[j - 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Gui_OverlaysCount--;
|
||||
Gui_Overlays[Gui_OverlaysCount] = NULL;
|
||||
Gui_Screens[i] = s;
|
||||
priorities[i] = priority;
|
||||
Gui_ScreensCount++;
|
||||
|
||||
s->VTABLE->Init(s);
|
||||
s->VTABLE->ContextRecreated(s);
|
||||
/* for selecting active button etc */
|
||||
s->VTABLE->HandlesMouseMove(s, Mouse_X, Mouse_Y);
|
||||
}
|
||||
|
||||
static void Gui_RemoveCore(struct Screen* s) {
|
||||
int i = Gui_Index(s);
|
||||
if (i == -1) return;
|
||||
|
||||
for (; i < Gui_ScreensCount - 1; i++) {
|
||||
Gui_Screens[i] = Gui_Screens[i + 1];
|
||||
priorities[i] = priorities[i + 1];
|
||||
}
|
||||
Gui_ScreensCount--;
|
||||
|
||||
s->VTABLE->ContextLost(s);
|
||||
s->VTABLE->Free(s);
|
||||
}
|
||||
|
||||
CC_NOINLINE static void Gui_OnScreensChanged(void) {
|
||||
Camera_CheckFocus();
|
||||
InputHandler_OnScreensChanged();
|
||||
}
|
||||
|
||||
void Gui_Add(struct Screen* s, int priority) {
|
||||
Gui_AddCore(s, priority);
|
||||
Gui_OnScreensChanged();
|
||||
}
|
||||
|
||||
void Gui_Remove(struct Screen* s) {
|
||||
Gui_RemoveCore(s);
|
||||
Gui_OnScreensChanged();
|
||||
}
|
||||
|
||||
void Gui_Replace(struct Screen* s, int priority) {
|
||||
int i;
|
||||
Gui_RemoveCore(s);
|
||||
/* Backwards loop since removing changes count and gui_screens */
|
||||
for (i = Gui_ScreensCount - 1; i >= 0; i--) {
|
||||
if (priorities[i] == priority) Gui_RemoveCore(Gui_Screens[i]);
|
||||
}
|
||||
|
||||
Gui_AddCore(s, priority);
|
||||
Gui_OnScreensChanged();
|
||||
}
|
||||
|
||||
struct Screen* Gui_GetInputGrab(void) {
|
||||
int i;
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
if (Gui_Screens[i]->grabsInput) return Gui_Screens[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Screen* Gui_GetBlocksWorld(void) {
|
||||
int i;
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
if (Gui_Screens[i]->blocksWorld) return Gui_Screens[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Screen* Gui_GetClosable(void) {
|
||||
int i;
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
if (Gui_Screens[i]->closable) return Gui_Screens[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Gui_RenderGui(double delta) {
|
||||
bool showHUD, hudBefore;
|
||||
struct Screen* s;
|
||||
int i;
|
||||
Gfx_Mode2D(Game.Width, Game.Height);
|
||||
|
||||
showHUD = !Gui_Active || !Gui_Active->hidesHUD;
|
||||
hudBefore = !Gui_Active || !Gui_Active->renderHUDOver;
|
||||
if (showHUD) { Elem_Render(Gui_Status, delta); }
|
||||
|
||||
if (showHUD && hudBefore) { Elem_Render(Gui_HUD, delta); }
|
||||
if (Gui_Active) { Elem_Render(Gui_Active, delta); }
|
||||
if (showHUD && !hudBefore) { Elem_Render(Gui_HUD, delta); }
|
||||
|
||||
if (Gui_OverlaysCount) { Elem_Render(Gui_Overlays[0], delta); }
|
||||
/* Draw back to front so highest priority screen is on top */
|
||||
for (i = Gui_ScreensCount - 1; i >= 0; i--) {
|
||||
s = Gui_Screens[i];
|
||||
s->VTABLE->Render(s, delta);
|
||||
}
|
||||
Gfx_Mode3D();
|
||||
}
|
||||
|
||||
void Gui_OnResize(void) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
if (Gui_Active) { Screen_OnResize(Gui_Active); }
|
||||
Screen_OnResize(Gui_HUD);
|
||||
|
||||
for (i = 0; i < Gui_OverlaysCount; i++) {
|
||||
Screen_OnResize(Gui_Overlays[i]);
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
s->VTABLE->OnResize(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
145
src/Gui.h
145
src/Gui.h
@ -16,7 +16,7 @@ enum GuiAnchor {
|
||||
};
|
||||
|
||||
struct IGameComponent;
|
||||
struct GuiElem;
|
||||
struct Widget;
|
||||
extern struct IGameComponent Gui_Component;
|
||||
|
||||
/* Whether vanilla Minecraft Classic gui texture is used. */
|
||||
@ -34,50 +34,44 @@ extern bool Gui_TabAutocomplete;
|
||||
/* Whether FPS counter (and other info) is shown in top left. */
|
||||
extern bool Gui_ShowFPS;
|
||||
|
||||
#define GuiElemVTABLE_Layout() \
|
||||
void (*Init)(void* elem); \
|
||||
void (*Render)(void* elem, double delta); \
|
||||
void (*Free)(void* elem); \
|
||||
void (*Recreate)(void* elem); \
|
||||
bool (*HandlesKeyDown)(void* elem, Key key, bool wasDown); \
|
||||
bool (*HandlesKeyUp)(void* elem, Key key); \
|
||||
bool (*HandlesKeyPress)(void* elem, char keyChar); \
|
||||
bool (*HandlesMouseDown)(void* elem, int x, int y, MouseButton btn); \
|
||||
bool (*HandlesMouseUp)(void* elem, int x, int y, MouseButton btn); \
|
||||
bool (*HandlesMouseMove)(void* elem, int x, int y); \
|
||||
bool (*HandlesMouseScroll)(void* elem, float delta);
|
||||
|
||||
struct GuiElemVTABLE { GuiElemVTABLE_Layout() };
|
||||
struct GuiElem { struct GuiElemVTABLE* VTABLE; };
|
||||
void Gui_DefaultRecreate(void* elem);
|
||||
|
||||
|
||||
struct ScreenVTABLE {
|
||||
GuiElemVTABLE_Layout()
|
||||
void (*Init)(void* elem);
|
||||
void (*Render)(void* elem, double delta);
|
||||
void (*Free)(void* elem);
|
||||
bool (*HandlesKeyDown)(void* elem, Key key);
|
||||
bool (*HandlesKeyUp)(void* elem, Key key);
|
||||
bool (*HandlesKeyPress)(void* elem, char keyChar);
|
||||
bool (*HandlesMouseDown)(void* elem, int x, int y, MouseButton btn);
|
||||
bool (*HandlesMouseUp)(void* elem, int x, int y, MouseButton btn);
|
||||
bool (*HandlesMouseMove)(void* elem, int x, int y);
|
||||
bool (*HandlesMouseScroll)(void* elem, float delta);
|
||||
void (*OnResize)(void* elem);
|
||||
Event_Void_Callback ContextLost;
|
||||
Event_Void_Callback ContextRecreated;
|
||||
};
|
||||
#define Screen_Layout struct ScreenVTABLE* VTABLE; \
|
||||
bool handlesAllInput; /* Whether this screen handles all input. Prevents user interacting with the world. */ \
|
||||
bool blocksWorld; /* Whether this screen completely and opaquely covers the game world behind it. */ \
|
||||
bool hidesHUD; /* Whether this screen hides the normal in-game HUD. */ \
|
||||
bool renderHUDOver; /* Whether the normal in-game HUD should be drawn over the top of this screen. */ \
|
||||
bool closable; /* Whether this screen is automatically closed when pressing Escape */
|
||||
#define Screen_Layout const struct ScreenVTABLE* VTABLE; \
|
||||
bool grabsInput; /* Whether this screen grabs input. Causes the cursor to become visible. */ \
|
||||
bool blocksWorld; /* Whether this screen completely and opaquely covers the game world behind it. */ \
|
||||
bool closable; /* Whether this screen is automatically closed when pressing Escape */ \
|
||||
struct Widget** widgets; int numWidgets;
|
||||
|
||||
/* Represents a container of widgets and other 2D elements. May cover entire window. */
|
||||
struct Screen { Screen_Layout };
|
||||
void Screen_CommonInit(void* screen);
|
||||
void Screen_CommonFree(void* screen);
|
||||
|
||||
|
||||
typedef void (*Widget_LeftClick)(void* screen, void* widget);
|
||||
struct Widget;
|
||||
struct WidgetVTABLE {
|
||||
GuiElemVTABLE_Layout()
|
||||
void (*Init)(void* elem);
|
||||
void (*Render)(void* elem, double delta);
|
||||
void (*Free)(void* elem);
|
||||
bool (*HandlesKeyDown)(void* elem, Key key);
|
||||
bool (*HandlesKeyUp)(void* elem, Key key);
|
||||
bool (*HandlesMouseDown)(void* elem, int x, int y, MouseButton btn);
|
||||
bool (*HandlesMouseUp)(void* elem, int x, int y, MouseButton btn);
|
||||
bool (*HandlesMouseMove)(void* elem, int x, int y);
|
||||
bool (*HandlesMouseScroll)(void* elem, float delta);
|
||||
void (*Reposition)(void* elem);
|
||||
};
|
||||
#define Widget_Layout struct WidgetVTABLE* VTABLE; \
|
||||
#define Widget_Layout const struct WidgetVTABLE* VTABLE; \
|
||||
int x, y, width, height; /* Top left corner, and dimensions, of this widget */ \
|
||||
bool active; /* Whether this widget is currently being moused over */ \
|
||||
bool disabled; /* Whether widget is prevented from being interacted with */ \
|
||||
@ -97,54 +91,55 @@ bool Widget_Contains(void* widget, int x, int y);
|
||||
|
||||
extern GfxResourceID Gui_GuiTex, Gui_GuiClassicTex, Gui_IconsTex;
|
||||
|
||||
/* Higher priority handles input first and draws on top */
|
||||
enum GuiPriority {
|
||||
GUI_PRIORITY_STATUS = 1,
|
||||
GUI_PRIORITY_DISCONNECT = 3,
|
||||
GUI_PRIORITY_URLWARNING = 5,
|
||||
GUI_PRIORITY_TEXPACK = 7,
|
||||
GUI_PRIORITY_TEXIDS = 9,
|
||||
GUI_PRIORITY_MENU = 11,
|
||||
GUI_PRIORITY_INVENTORY = 13,
|
||||
GUI_PRIORITY_HUD = 15,
|
||||
GUI_PRIORITY_LOADING = 17,
|
||||
GUI_PRIORITY_DISCONNECT = 50,
|
||||
GUI_PRIORITY_OLDLOADING = 45,
|
||||
GUI_PRIORITY_URLWARNING = 40,
|
||||
GUI_PRIORITY_TEXPACK = 35,
|
||||
GUI_PRIORITY_TEXIDS = 30,
|
||||
GUI_PRIORITY_MENU = 25,
|
||||
GUI_PRIORITY_INVENTORY = 20,
|
||||
GUI_PRIORITY_STATUS = 15,
|
||||
GUI_PRIORITY_HUD = 10,
|
||||
GUI_PRIORITY_LOADING = 5,
|
||||
};
|
||||
|
||||
extern struct Screen* Gui_Status;
|
||||
extern struct Screen* Gui_HUD;
|
||||
extern struct Screen* Gui_Active;
|
||||
#define GUI_MAX_OVERLAYS 4
|
||||
extern struct Screen* Gui_Overlays[GUI_MAX_OVERLAYS];
|
||||
extern int Gui_OverlaysCount;
|
||||
#define GUI_MAX_SCREENS 10
|
||||
extern struct Screen* Gui_Screens[GUI_MAX_SCREENS];
|
||||
extern int Gui_ScreensCount;
|
||||
|
||||
/* Calculates position of an element on a particular axis */
|
||||
/* For example, to calculate X position of a text widget on screen */
|
||||
int Gui_CalcPos(uint8_t anchor, int offset, int size, int axisLen);
|
||||
/* Returns whether the given rectangle contains the given point. */
|
||||
bool Gui_Contains(int recX, int recY, int width, int height, int x, int y);
|
||||
/* Gets the screen that the user is currently interacting with. */
|
||||
/* This means if an overlay is active, it will be over the top of other screens. */
|
||||
struct Screen* Gui_GetActiveScreen(void);
|
||||
/* Gets the non-overlay screen that the user is currently interacting with. */
|
||||
/* This means if an overlay is active, the screen under it is returned. */
|
||||
struct Screen* Gui_GetUnderlyingScreen(void);
|
||||
/* Shows HUD and Status screens. */
|
||||
void Gui_ShowDefault(void);
|
||||
|
||||
/* Frees the active screen if it is not NULL. */
|
||||
/* NOTE: You should usually use Gui_CloseActive instead. */
|
||||
CC_NOINLINE void Gui_FreeActive(void);
|
||||
/* Sets the active screen/menu that the user interacts with. */
|
||||
/* NOTE: This doesn't free old active screen - must call Gui_FreeActive() first */
|
||||
CC_NOINLINE void Gui_SetActive(struct Screen* screen);
|
||||
/* Shortcut for Gui_Close(Gui_Active) */
|
||||
CC_NOINLINE void Gui_CloseActive(void);
|
||||
/* Frees the given screen, and if == Gui_Active, calls Gui_SetActive(NULL) */
|
||||
CC_NOINLINE void Gui_Close(void* screen);
|
||||
/* Returns index of the given screen in the screens list, -1 if not */
|
||||
int Gui_Index(struct Screen* screen);
|
||||
/* Inserts a screen into the screen lists with the given priority. */
|
||||
/* NOTE: You MUST ensure a screen isn't added twice. Or use Gui_Replace. */
|
||||
void Gui_Add(struct Screen* screen, int priority);
|
||||
/* Removes the screen from the screens list. */
|
||||
void Gui_Remove(struct Screen* screen);
|
||||
/* Shorthand for Gui_Remove then Gui_Add. */
|
||||
void Gui_Replace(struct Screen* screen, int priority);
|
||||
|
||||
/* Returns highest priority screen that has grabbed input. */
|
||||
struct Screen* Gui_GetInputGrab(void);
|
||||
/* Returns highest priority screen that blocks world rendering. */
|
||||
struct Screen* Gui_GetBlocksWorld(void);
|
||||
/* Returns highest priority screen that is closable. */
|
||||
struct Screen* Gui_GetClosable(void);
|
||||
|
||||
void Gui_RefreshAll(void);
|
||||
void Gui_RefreshHud(void);
|
||||
void Gui_ShowOverlay(struct Screen* screen);
|
||||
/* Returns index of the given screen in the overlays list, -1 if not */
|
||||
int Gui_IndexOverlay(const void* screen);
|
||||
/* Removes given screen from the overlays list */
|
||||
void Gui_RemoveOverlay(const void* screen);
|
||||
void Gui_Refresh(struct Screen* s);
|
||||
|
||||
void Gui_RenderGui(double delta);
|
||||
void Gui_OnResize(void);
|
||||
|
||||
@ -153,8 +148,8 @@ struct TextAtlas {
|
||||
struct Texture tex;
|
||||
int offset, curX;
|
||||
float uScale;
|
||||
int16_t widths[TEXTATLAS_MAX_WIDTHS];
|
||||
int16_t offsets[TEXTATLAS_MAX_WIDTHS];
|
||||
short widths[TEXTATLAS_MAX_WIDTHS];
|
||||
short offsets[TEXTATLAS_MAX_WIDTHS];
|
||||
};
|
||||
void TextAtlas_Make(struct TextAtlas* atlas, const String* chars, const FontDesc* font, const String* prefix);
|
||||
void TextAtlas_Free(struct TextAtlas* atlas);
|
||||
@ -162,19 +157,17 @@ void TextAtlas_Add(struct TextAtlas* atlas, int charI, VertexP3fT2fC4b** vertice
|
||||
void TextAtlas_AddInt(struct TextAtlas* atlas, int value, VertexP3fT2fC4b** vertices);
|
||||
|
||||
|
||||
#define Elem_Init(elem) (elem)->VTABLE->Init(elem)
|
||||
#define Elem_Render(elem, delta) (elem)->VTABLE->Render(elem, delta)
|
||||
#define Elem_Free(elem) (elem)->VTABLE->Free(elem)
|
||||
#define Elem_Recreate(elem) (elem)->VTABLE->Recreate(elem)
|
||||
#define Elem_HandlesKeyPress(elem, key) (elem)->VTABLE->HandlesKeyPress(elem, key)
|
||||
#define Elem_HandlesKeyDown(elem, key, was) (elem)->VTABLE->HandlesKeyDown(elem, key, was)
|
||||
#define Elem_HandlesKeyUp(elem, key) (elem)->VTABLE->HandlesKeyUp(elem, key)
|
||||
#define Elem_Init(elem) (elem)->VTABLE->Init(elem)
|
||||
#define Elem_Render(elem, delta) (elem)->VTABLE->Render(elem, delta)
|
||||
#define Elem_Free(elem) (elem)->VTABLE->Free(elem)
|
||||
#define Elem_HandlesKeyPress(elem, key) (elem)->VTABLE->HandlesKeyPress(elem, key)
|
||||
#define Elem_HandlesKeyDown(elem, key) (elem)->VTABLE->HandlesKeyDown(elem, key)
|
||||
#define Elem_HandlesKeyUp(elem, key) (elem)->VTABLE->HandlesKeyUp(elem, key)
|
||||
#define Elem_HandlesMouseDown(elem, x, y, btn) (elem)->VTABLE->HandlesMouseDown(elem, x, y, btn)
|
||||
#define Elem_HandlesMouseUp(elem, x, y, btn) (elem)->VTABLE->HandlesMouseUp(elem, x, y, btn)
|
||||
#define Elem_HandlesMouseMove(elem, x, y) (elem)->VTABLE->HandlesMouseMove(elem, x, y)
|
||||
#define Elem_HandlesMouseScroll(elem, delta) (elem)->VTABLE->HandlesMouseScroll(elem, delta)
|
||||
|
||||
#define Screen_OnResize(screen) (screen)->VTABLE->OnResize(screen);
|
||||
#define Widget_Reposition(widget) (widget)->VTABLE->Reposition(widget);
|
||||
#define Elem_TryFree(elem) if ((elem)->VTABLE) { Elem_Free(elem); }
|
||||
#endif
|
||||
|
@ -62,10 +62,8 @@ static void InputHandler_ButtonStateChanged(MouseButton button, bool pressed) {
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_ScreenChanged(struct Screen* oldScreen, struct Screen* newScreen) {
|
||||
if (oldScreen && oldScreen->handlesAllInput) {
|
||||
input_lastClick = DateTime_CurrentUTC_MS();
|
||||
}
|
||||
void InputHandler_OnScreensChanged(void) {
|
||||
input_lastClick = DateTime_CurrentUTC_MS();
|
||||
|
||||
if (Server.SupportsPlayerClick) {
|
||||
input_pickingId = -1;
|
||||
@ -172,8 +170,7 @@ static bool InputHandler_HandleNonClassicKey(Key key) {
|
||||
Event_RaiseVoid(&UserEvents.HeldBlockChanged);
|
||||
}
|
||||
} else if (key == KeyBinds[KEYBIND_IDOVERLAY]) {
|
||||
if (Gui_OverlaysCount) return true;
|
||||
Gui_ShowOverlay(TexIdsOverlay_MakeInstance());
|
||||
TexIdsOverlay_Show();
|
||||
} else if (key == KeyBinds[KEYBIND_BREAK_LIQUIDS]) {
|
||||
InputHandler_Toggle(key, &Game_BreakableLiquids,
|
||||
" &eBreakable liquids is &aenabled",
|
||||
@ -185,8 +182,6 @@ static bool InputHandler_HandleNonClassicKey(Key key) {
|
||||
}
|
||||
|
||||
static bool InputHandler_HandleCoreKey(Key key) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
|
||||
if (key == KeyBinds[KEYBIND_HIDE_FPS]) {
|
||||
Gui_ShowFPS = !Gui_ShowFPS;
|
||||
} else if (key == KeyBinds[KEYBIND_FULLSCREEN]) {
|
||||
@ -206,9 +201,6 @@ static bool InputHandler_HandleCoreKey(Key key) {
|
||||
} else {
|
||||
InputHandler_CycleDistanceForwards(viewDists, count);
|
||||
}
|
||||
} else if (key == KeyBinds[KEYBIND_INVENTORY] && active == Gui_HUD) {
|
||||
Gui_FreeActive();
|
||||
InventoryScreen_Show();
|
||||
} else if (key == KEY_F5 && Game_ClassicMode) {
|
||||
int weather = Env.Weather == WEATHER_SUNNY ? WEATHER_RAINY : WEATHER_SUNNY;
|
||||
Env_SetWeather(weather);
|
||||
@ -331,16 +323,15 @@ void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right)
|
||||
|
||||
if (cooldown && delta < 250) return; /* 4 times per second */
|
||||
input_lastClick = now;
|
||||
if (Gui_GetInputGrab()) return;
|
||||
|
||||
if (Server.SupportsPlayerClick && !Gui_GetActiveScreen()->handlesAllInput) {
|
||||
if (Server.SupportsPlayerClick) {
|
||||
input_pickingId = -1;
|
||||
InputHandler_ButtonStateChanged(MOUSE_LEFT, left);
|
||||
InputHandler_ButtonStateChanged(MOUSE_RIGHT, right);
|
||||
InputHandler_ButtonStateChanged(MOUSE_MIDDLE, middle);
|
||||
}
|
||||
|
||||
if (Gui_GetActiveScreen()->handlesAllInput) return;
|
||||
|
||||
if (left) {
|
||||
/* always play delete animations, even if we aren't picking a block */
|
||||
HeldBlockRenderer_ClickAnim(true);
|
||||
@ -401,10 +392,15 @@ void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right)
|
||||
}
|
||||
|
||||
static void InputHandler_MouseWheel(void* obj, float delta) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
struct Screen* s;
|
||||
int i;
|
||||
struct Widget* widget;
|
||||
bool hotbar;
|
||||
if (Elem_HandlesMouseScroll(active, delta)) return;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesMouseScroll(s, delta)) return;
|
||||
}
|
||||
|
||||
hotbar = Key_IsAltPressed() || Key_IsControlPressed() || Key_IsShiftPressed();
|
||||
if (!hotbar && Camera.Active->Zoom(delta)) return;
|
||||
@ -415,31 +411,43 @@ static void InputHandler_MouseWheel(void* obj, float delta) {
|
||||
}
|
||||
|
||||
static void InputHandler_MouseMove(void* obj, int xDelta, int yDelta) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
/* In case MouseMove is called before game is fully initialised */
|
||||
if (active) Elem_HandlesMouseMove(active, Mouse_X, Mouse_Y);
|
||||
}
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
static void InputHandler_MouseDown(void* obj, int button) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
if (!Elem_HandlesMouseDown(active, Mouse_X, Mouse_Y, button)) {
|
||||
bool left = button == MOUSE_LEFT;
|
||||
bool middle = button == MOUSE_MIDDLE;
|
||||
bool right = button == MOUSE_RIGHT;
|
||||
InputHandler_PickBlocks(false, left, middle, right);
|
||||
} else {
|
||||
input_lastClick = DateTime_CurrentUTC_MS();
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesMouseMove(s, Mouse_X, Mouse_Y)) return;
|
||||
}
|
||||
}
|
||||
|
||||
static void InputHandler_MouseUp(void* obj, int button) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
if (!Elem_HandlesMouseUp(active, Mouse_X, Mouse_Y, button)) {
|
||||
if (Server.SupportsPlayerClick && button <= MOUSE_MIDDLE) {
|
||||
input_pickingId = -1;
|
||||
InputHandler_ButtonStateChanged(button, false);
|
||||
static void InputHandler_MouseDown(void* obj, int btn) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesMouseDown(s, Mouse_X, Mouse_Y, btn)) {
|
||||
input_lastClick = DateTime_CurrentUTC_MS(); return;
|
||||
}
|
||||
}
|
||||
|
||||
InputHandler_PickBlocks(false, btn == MOUSE_LEFT,
|
||||
btn == MOUSE_MIDDLE, btn == MOUSE_RIGHT);
|
||||
}
|
||||
|
||||
static void InputHandler_MouseUp(void* obj, int btn) {
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesMouseUp(s, Mouse_X, Mouse_Y, btn)) return;
|
||||
}
|
||||
|
||||
if (Server.SupportsPlayerClick && btn <= MOUSE_MIDDLE) {
|
||||
input_pickingId = -1;
|
||||
InputHandler_ButtonStateChanged(btn, false);
|
||||
}
|
||||
}
|
||||
|
||||
static bool InputHandler_SimulateMouse(Key key, bool pressed) {
|
||||
@ -456,18 +464,16 @@ static bool InputHandler_SimulateMouse(Key key, bool pressed) {
|
||||
}
|
||||
|
||||
static void InputHandler_KeyDown(void* obj, int key, bool was) {
|
||||
struct Screen* active;
|
||||
int idx;
|
||||
struct Screen* s;
|
||||
int i;
|
||||
struct HotkeyData* hkey;
|
||||
String text;
|
||||
|
||||
if (!was && InputHandler_SimulateMouse(key, true)) return;
|
||||
active = Gui_GetActiveScreen();
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (key == KEY_ESCAPE && active->closable) {
|
||||
if (key == KEY_ESCAPE && (s = Gui_GetClosable())) {
|
||||
/* Don't want holding down escape to go in and out of pause menu */
|
||||
if (!was) Gui_Close(active);
|
||||
if (!was) Gui_Remove(s);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -477,9 +483,14 @@ static void InputHandler_KeyDown(void* obj, int key, bool was) {
|
||||
Window_Close(); return;
|
||||
} else if (key == KeyBinds[KEYBIND_SCREENSHOT] && !was) {
|
||||
Game_ScreenshotRequested = true; return;
|
||||
} else if (Elem_HandlesKeyDown(active, key, was)) {
|
||||
return;
|
||||
} else if ((key == KEY_ESCAPE || key == KEY_PAUSE) && !active->handlesAllInput) {
|
||||
}
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesKeyDown(s, key)) return;
|
||||
}
|
||||
|
||||
if ((key == KEY_ESCAPE || key == KEY_PAUSE) && !Gui_GetInputGrab()) {
|
||||
#ifdef CC_BUILD_WEB
|
||||
/* Can't do this in KeyUp, because pressing escape without having */
|
||||
/* explicitly disabled mouse lock means a KeyUp event isn't sent. */
|
||||
@ -488,8 +499,7 @@ static void InputHandler_KeyDown(void* obj, int key, bool was) {
|
||||
/* closes the pause screen. Hence why the next KeyUp must be supressed. */
|
||||
suppressEscape = true;
|
||||
#endif
|
||||
Gui_FreeActive();
|
||||
Gui_SetActive(PauseScreen_MakeInstance()); return;
|
||||
PauseScreen_Show(); return;
|
||||
}
|
||||
|
||||
/* These should not be triggered multiple times when holding down */
|
||||
@ -497,42 +507,51 @@ static void InputHandler_KeyDown(void* obj, int key, bool was) {
|
||||
if (InputHandler_HandleCoreKey(key)) {
|
||||
} else if (LocalPlayer_HandlesKey(key)) {
|
||||
} else {
|
||||
idx = Hotkeys_FindPartial(key);
|
||||
if (idx == -1) return;
|
||||
i = Hotkeys_FindPartial(key);
|
||||
if (i == -1) return;
|
||||
|
||||
hkey = &HotkeysList[idx];
|
||||
hkey = &HotkeysList[i];
|
||||
text = StringsBuffer_UNSAFE_Get(&HotkeysText, hkey->TextIndex);
|
||||
|
||||
if (!hkey->StaysOpen) {
|
||||
Chat_Send(&text, false);
|
||||
} else if (!Gui_Active) {
|
||||
} else if (!Gui_GetInputGrab()) {
|
||||
HUDScreen_OpenInput(&text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InputHandler_KeyUp(void* obj, int key) {
|
||||
struct Screen* active;
|
||||
if (InputHandler_SimulateMouse(key, false)) return;
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
if (InputHandler_SimulateMouse(key, false)) return;
|
||||
if (key == KeyBinds[KEYBIND_ZOOM_SCROLL]) Game_SetFov(Game_DefaultFov);
|
||||
active = Gui_GetActiveScreen();
|
||||
|
||||
#ifdef CC_BUILD_WEB
|
||||
/* When closing menus (which reacquires mouse focus) in key down, */
|
||||
/* this still leaves the cursor visible. But if this is instead */
|
||||
/* done in key up, the cursor disappears as expected. */
|
||||
if (key == KEY_ESCAPE && active->closable) {
|
||||
if (key == KEY_ESCAPE && (s = Gui_GetClosable())) {
|
||||
if (suppressEscape) { suppressEscape = false; return; }
|
||||
Gui_Close(active); return;
|
||||
Gui_Remove(s); return;
|
||||
}
|
||||
#endif
|
||||
Elem_HandlesKeyUp(active, key);
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesKeyUp(s, key)) return;
|
||||
}
|
||||
}
|
||||
|
||||
static void InputHandler_KeyPress(void* obj, int keyChar) {
|
||||
struct Screen* active = Gui_GetActiveScreen();
|
||||
Elem_HandlesKeyPress(active, keyChar);
|
||||
struct Screen* s;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Gui_ScreensCount; i++) {
|
||||
s = Gui_Screens[i];
|
||||
if (s->VTABLE->HandlesKeyPress(s, keyChar)) return;
|
||||
}
|
||||
}
|
||||
|
||||
void InputHandler_Init(void) {
|
||||
|
@ -10,5 +10,5 @@ bool InputHandler_IsMousePressed(MouseButton button);
|
||||
bool InputHandler_SetFOV(int fov);
|
||||
void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right);
|
||||
void InputHandler_Init(void);
|
||||
void InputHandler_ScreenChanged(struct Screen* oldScreen, struct Screen* newScreen);
|
||||
void InputHandler_OnScreensChanged(void);
|
||||
#endif
|
||||
|
@ -235,7 +235,7 @@ static void LInput_BlendBoxTop(struct LInput* w) {
|
||||
}
|
||||
|
||||
static void LInput_DrawText(struct LInput* w, struct DrawTextArgs* args) {
|
||||
int hintHeight, y;
|
||||
int y, hintHeight;
|
||||
|
||||
if (w->Text.length || !w->HintText) {
|
||||
y = w->Y + (w->Height - w->_TextHeight) / 2;
|
||||
@ -244,7 +244,7 @@ static void LInput_DrawText(struct LInput* w, struct DrawTextArgs* args) {
|
||||
args->text = String_FromReadonly(w->HintText);
|
||||
args->font = Launcher_HintFont;
|
||||
|
||||
hintHeight = Drawer2D_MeasureText(args).Height;
|
||||
hintHeight = Drawer2D_TextHeight(args);
|
||||
y = w->Y + (w->Height - hintHeight) / 2;
|
||||
Drawer2D_DrawText(&Launcher_Framebuffer, args, w->X + 5, y);
|
||||
}
|
||||
|
2436
src/Menus.c
2436
src/Menus.c
File diff suppressed because it is too large
Load Diff
50
src/Menus.h
50
src/Menus.h
@ -7,33 +7,33 @@
|
||||
*/
|
||||
struct Screen;
|
||||
|
||||
struct Screen* PauseScreen_MakeInstance(void);
|
||||
struct Screen* OptionsGroupScreen_MakeInstance(void);
|
||||
struct Screen* ClassicOptionsScreen_MakeInstance(void);
|
||||
void PauseScreen_Show(void);
|
||||
void OptionsGroupScreen_Show(void);
|
||||
void ClassicOptionsScreen_Show(void);
|
||||
|
||||
struct Screen* ClassicKeyBindingsScreen_MakeInstance(void);
|
||||
struct Screen* ClassicHacksKeyBindingsScreen_MakeInstance(void);
|
||||
struct Screen* NormalKeyBindingsScreen_MakeInstance(void);
|
||||
struct Screen* HacksKeyBindingsScreen_MakeInstance(void);
|
||||
struct Screen* OtherKeyBindingsScreen_MakeInstance(void);
|
||||
struct Screen* MouseKeyBindingsScreen_MakeInstance(void);
|
||||
void ClassicKeyBindingsScreen_Show(void);
|
||||
void ClassicHacksKeyBindingsScreen_Show(void);
|
||||
void NormalKeyBindingsScreen_Show(void);
|
||||
void HacksKeyBindingsScreen_Show(void);
|
||||
void OtherKeyBindingsScreen_Show(void);
|
||||
void MouseKeyBindingsScreen_Show(void);
|
||||
|
||||
struct Screen* GenLevelScreen_MakeInstance(void);
|
||||
struct Screen* ClassicGenScreen_MakeInstance(void);
|
||||
struct Screen* LoadLevelScreen_MakeInstance(void);
|
||||
struct Screen* SaveLevelScreen_MakeInstance(void);
|
||||
struct Screen* TexturePackScreen_MakeInstance(void);
|
||||
struct Screen* FontListScreen_MakeInstance(void);
|
||||
struct Screen* HotkeyListScreen_MakeInstance(void);
|
||||
void GenLevelScreen_Show(void);
|
||||
void ClassicGenScreen_Show(void);
|
||||
void LoadLevelScreen_Show(void);
|
||||
void SaveLevelScreen_Show(void);
|
||||
void TexturePackScreen_Show(void);
|
||||
void FontListScreen_Show(void);
|
||||
void HotkeyListScreen_Show(void);
|
||||
|
||||
struct Screen* MiscOptionsScreen_MakeInstance(void);
|
||||
struct Screen* GuiOptionsScreen_MakeInstance(void);
|
||||
struct Screen* GraphicsOptionsScreen_MakeInstance(void);
|
||||
struct Screen* HacksSettingsScreen_MakeInstance(void);
|
||||
struct Screen* EnvSettingsScreen_MakeInstance(void);
|
||||
struct Screen* NostalgiaScreen_MakeInstance(void);
|
||||
void MiscOptionsScreen_Show(void);
|
||||
void GuiOptionsScreen_Show(void);
|
||||
void GraphicsOptionsScreen_Show(void);
|
||||
void HacksSettingsScreen_Show(void);
|
||||
void EnvSettingsScreen_Show(void);
|
||||
void NostalgiaScreen_Show(void);
|
||||
|
||||
struct Screen* UrlWarningOverlay_MakeInstance(const String* url);
|
||||
struct Screen* TexIdsOverlay_MakeInstance(void);
|
||||
struct Screen* TexPackOverlay_MakeInstance(const String* url);
|
||||
void UrlWarningOverlay_Show(const String* url);
|
||||
void TexIdsOverlay_Show(void);
|
||||
void TexPackOverlay_Show(const String* url);
|
||||
#endif
|
||||
|
@ -105,9 +105,9 @@ static int Program_Run(int argc, char** argv) {
|
||||
|
||||
int argsCount = Platform_GetCommandLineArgs(argc, argv, args);
|
||||
/* NOTE: Make sure to comment this out before pushing a commit */
|
||||
/* String rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565"); */
|
||||
/* String rawArgs = String_FromConst("UnknownShadow200"); */
|
||||
/* argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); */
|
||||
String rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565");
|
||||
//String rawArgs = String_FromConst("UnknownShadow200");
|
||||
argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
|
||||
|
||||
if (argsCount == 0) {
|
||||
#ifdef CC_BUILD_WEB
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
/* Classic state */
|
||||
static uint8_t classic_tabList[ENTITIES_MAX_COUNT >> 3];
|
||||
static struct Screen* classic_prevScreen;
|
||||
static bool classic_receivedFirstPos;
|
||||
|
||||
/* Map state */
|
||||
@ -424,13 +423,6 @@ static void Classic_StartLoading(void) {
|
||||
Event_RaiseVoid(&WorldEvents.NewMap);
|
||||
Stream_ReadonlyMemory(&map_part, NULL, 0);
|
||||
|
||||
classic_prevScreen = Gui_Active;
|
||||
if (classic_prevScreen == LoadingScreen_UNSAFE_RawPointer) {
|
||||
/* otherwise replacing LoadingScreen with LoadingScreen will cause issues */
|
||||
Gui_FreeActive();
|
||||
classic_prevScreen = NULL;
|
||||
}
|
||||
|
||||
LoadingScreen_Show(&Server.Name, &Server.MOTD);
|
||||
WoM_CheckMotd();
|
||||
classic_receivedFirstPos = false;
|
||||
@ -511,9 +503,7 @@ static void Classic_LevelFinalise(uint8_t* data) {
|
||||
int width, height, length;
|
||||
int loadingMs;
|
||||
|
||||
Gui_CloseActive();
|
||||
Gui_Active = classic_prevScreen;
|
||||
classic_prevScreen = NULL;
|
||||
Gui_Remove(LoadingScreen_UNSAFE_RawPointer);
|
||||
Camera_CheckFocus();
|
||||
|
||||
loadingMs = (int)(DateTime_CurrentUTC_MS() - map_receiveStart);
|
||||
|
520
src/Screens.c
520
src/Screens.c
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,20 @@
|
||||
struct Screen;
|
||||
struct Widget;
|
||||
|
||||
/* These always return false */
|
||||
bool Screen_FKey(void* elem, int key);
|
||||
bool Screen_FKeyPress(void* elem, char keyChar);
|
||||
bool Screen_FMouseScroll(void* elem, float delta);
|
||||
bool Screen_FMouse(void* elem, int x, int y, int btn);
|
||||
bool Screen_FMouseMove(void* elem, int x, int y);
|
||||
|
||||
/* These always return true */
|
||||
bool Screen_TKeyPress(void* elem, char keyChar);
|
||||
bool Screen_TKey(void* s, int key);
|
||||
bool Screen_TMouseScroll(void* screen, float delta);
|
||||
bool Screen_TMouse(void* screen, int x, int y, int btn);
|
||||
bool Screen_TMouseMove(void* elem, int x, int y);
|
||||
|
||||
void InventoryScreen_Show(void);
|
||||
void StatusScreen_Show(void);
|
||||
void LoadingScreen_Show(const String* title, const String* message);
|
||||
@ -14,13 +28,12 @@ void GeneratingScreen_Show(void);
|
||||
void HUDScreen_Show(void);
|
||||
void DisconnectScreen_Show(const String* title, const String* message);
|
||||
|
||||
/* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_MakeInstance() */
|
||||
extern struct Screen* InventoryScreen_UNSAFE_RawPointer;
|
||||
/* Raw pointer to loading screen. DO NOT USE THIS. Use LoadingScreen_MakeInstance() */
|
||||
extern struct Screen* LoadingScreen_UNSAFE_RawPointer;
|
||||
/* Opens chat input for the HUD with the given initial text. */
|
||||
void HUDScreen_OpenInput(const String* text);
|
||||
/* Appends text to the chat input in the HUD. */
|
||||
void HUDScreen_AppendInput(const String* text);
|
||||
void HUDScreen_SetChatlines(int lines);
|
||||
struct Widget* HUDScreen_GetHotbar(void);
|
||||
#endif
|
||||
|
@ -46,7 +46,7 @@ void Server_RetrieveTexturePack(const String* url) {
|
||||
if (!url->length || TextureCache_HasAccepted(url)) {
|
||||
World_ApplyTexturePack(url);
|
||||
} else {
|
||||
Gui_ShowOverlay(TexPackOverlay_MakeInstance(url));
|
||||
TexPackOverlay_Show(url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +139,6 @@ static void SPConnection_BeginConnect(void) {
|
||||
path = Game_Username;
|
||||
if (SP_HasDir(path) && File_Exists(&path)) {
|
||||
Map_LoadFrom(&path);
|
||||
Gui_CloseActive();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -147,8 +146,6 @@ static void SPConnection_BeginConnect(void) {
|
||||
World_SetDimensions(128, 64, 128);
|
||||
Gen_Vanilla = true;
|
||||
Gen_Seed = Random_Next(&rnd, Int32_MaxValue);
|
||||
|
||||
Gui_FreeActive();
|
||||
GeneratingScreen_Show();
|
||||
}
|
||||
|
||||
@ -316,7 +313,6 @@ static void MPConnection_BeginConnect(void) {
|
||||
MPConnection_FailConnect(res);
|
||||
} else {
|
||||
String_Format2(&title, "Connecting to %s:%i..", &Server.IP, &Server.Port);
|
||||
Gui_FreeActive();
|
||||
LoadingScreen_Show(&title, &String_Empty);
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ CC_VAR extern struct _ServerConnectionData {
|
||||
/* Sends a position update to the server. */
|
||||
void (*SendPosition)(Vec3 pos, float rotY, float headX);
|
||||
/* Sends raw data to the server. */
|
||||
/* NOTE: Prefer SendBlock/Position/Chat instead, this does not work in singleplayer. */
|
||||
/* NOTE: Prefer SendBlock/Position/Chat instead, this does NOT work in singleplayer. */
|
||||
void (*SendData)(const uint8_t* data, uint32_t len);
|
||||
|
||||
/* The current name of the server. (Shows as first line when loading) */
|
||||
@ -71,7 +71,7 @@ CC_VAR extern struct _ServerConnectionData {
|
||||
/* The current MOTD of the server. (Shows as second line when loading) */
|
||||
String MOTD;
|
||||
/* The software name the client identifies itself as being to the server. */
|
||||
/* By default this is the same as GAME_APP_NAME */
|
||||
/* By default this is GAME_APP_NAME. */
|
||||
String AppName;
|
||||
|
||||
/* Buffer to data to send to the server. */
|
||||
|
630
src/Widgets.c
630
src/Widgets.c
File diff suppressed because it is too large
Load Diff
@ -11,17 +11,17 @@
|
||||
/* A text label. */
|
||||
struct TextWidget {
|
||||
Widget_Layout
|
||||
struct Texture texture;
|
||||
|
||||
struct Texture tex;
|
||||
bool reducePadding;
|
||||
PackedCol col;
|
||||
};
|
||||
/* Resets state of the given text widget to default. */
|
||||
CC_NOINLINE void TextWidget_Make(struct TextWidget* w);
|
||||
/* Initialises a text widget. */
|
||||
CC_NOINLINE void TextWidget_Make(struct TextWidget* w,
|
||||
uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset);
|
||||
/* Draws the given text into a texture, then updates the position and size of this widget. */
|
||||
CC_NOINLINE void TextWidget_Set(struct TextWidget* w, const String* text, const FontDesc* font);
|
||||
/* Shorthand for TextWidget_Make then TextWidget_Set */
|
||||
CC_NOINLINE void TextWidget_Create(struct TextWidget* w, const String* text, const FontDesc* font);
|
||||
/* Shorthand for TextWidget_Set using String_FromReadonly */
|
||||
CC_NOINLINE void TextWidget_SetConst(struct TextWidget* w, const char* text, const FontDesc* font);
|
||||
|
||||
|
||||
typedef void (*Button_Get)(String* raw);
|
||||
@ -29,19 +29,19 @@ typedef void (*Button_Set)(const String* raw);
|
||||
/* A labelled button that can be clicked on. */
|
||||
struct ButtonWidget {
|
||||
Widget_Layout
|
||||
struct Texture texture;
|
||||
struct Texture tex;
|
||||
int minWidth;
|
||||
|
||||
const char* optName;
|
||||
Button_Get GetValue;
|
||||
Button_Set SetValue;
|
||||
};
|
||||
/* Resets state of the given button widget to default. */
|
||||
CC_NOINLINE void ButtonWidget_Make(struct ButtonWidget* w, int minWidth, Widget_LeftClick onClick);
|
||||
/* Initialises a button widget. */
|
||||
CC_NOINLINE void ButtonWidget_Make(struct ButtonWidget* w, int minWidth, Widget_LeftClick onClick,
|
||||
uint8_t horAnchor, uint8_t verAnchor, int xOffset, int yOffset);
|
||||
/* Draws the given text into a texture, then updates the position and size of this widget. */
|
||||
CC_NOINLINE void ButtonWidget_Set(struct ButtonWidget* w, const String* text, const FontDesc* font);
|
||||
/* Resets state of the given button widget, then calls ButtonWidget_Set */
|
||||
CC_NOINLINE void ButtonWidget_Create(struct ButtonWidget* w, int minWidth, const String* text, const FontDesc* font, Widget_LeftClick onClick);
|
||||
/* Shorthand for ButtonWidget_Set using String_FromReadonly */
|
||||
CC_NOINLINE void ButtonWidget_SetConst(struct ButtonWidget* w, const char* text, const FontDesc* font);
|
||||
|
||||
/* Clickable and draggable scrollbar. */
|
||||
struct ScrollbarWidget {
|
||||
@ -70,7 +70,7 @@ CC_NOINLINE void HotbarWidget_Create(struct HotbarWidget* w);
|
||||
/* A table of blocks. */
|
||||
struct TableWidget {
|
||||
Widget_Layout
|
||||
int elementsCount, elementsPerRow, rowsCount;
|
||||
int blocksCount, blocksPerRow, rowsCount;
|
||||
int lastCreatedIndex;
|
||||
FontDesc* font;
|
||||
int selectedIndex, cellSize;
|
||||
@ -78,7 +78,7 @@ struct TableWidget {
|
||||
GfxResourceID vb;
|
||||
bool pendingClose;
|
||||
|
||||
BlockID elements[BLOCK_COUNT];
|
||||
BlockID blocks[BLOCK_COUNT];
|
||||
struct ScrollbarWidget scroll;
|
||||
struct Texture descTex;
|
||||
int lastX, lastY;
|
||||
@ -88,8 +88,10 @@ CC_NOINLINE void TableWidget_Create(struct TableWidget* w);
|
||||
/* Sets the selected block in the table to the given block. */
|
||||
/* Also adjusts scrollbar and moves cursor to be over the given block. */
|
||||
CC_NOINLINE void TableWidget_SetBlockTo(struct TableWidget* w, BlockID block);
|
||||
CC_NOINLINE void TableWidget_RecreateBlocks(struct TableWidget* w);
|
||||
CC_NOINLINE void TableWidget_OnInventoryChanged(struct TableWidget* w);
|
||||
CC_NOINLINE void TableWidget_MakeDescTex(struct TableWidget* w, BlockID block);
|
||||
CC_NOINLINE void TableWidget_Recreate(struct TableWidget* w);
|
||||
|
||||
|
||||
#define INPUTWIDGET_MAX_LINES 3
|
||||
@ -103,11 +105,11 @@ struct InputWidget {
|
||||
bool (*AllowedChar)(void* elem, char c);
|
||||
|
||||
String text;
|
||||
String lines[INPUTWIDGET_MAX_LINES]; /* raw text of each line */
|
||||
Size2D lineSizes[INPUTWIDGET_MAX_LINES]; /* size of each line in pixels */
|
||||
String lines[INPUTWIDGET_MAX_LINES]; /* raw text of each line */
|
||||
int lineWidths[INPUTWIDGET_MAX_LINES]; /* Width of each line in pixels */
|
||||
int lineHeight;
|
||||
struct Texture inputTex;
|
||||
String prefix;
|
||||
int prefixWidth, prefixHeight;
|
||||
int prefixWidth;
|
||||
bool convertPercents;
|
||||
|
||||
uint8_t padding;
|
||||
@ -126,6 +128,8 @@ CC_NOINLINE void InputWidget_Clear(struct InputWidget* w);
|
||||
CC_NOINLINE void InputWidget_AppendString(struct InputWidget* w, const String* text);
|
||||
/* Tries appending the given character, then updates the input texture. */
|
||||
CC_NOINLINE void InputWidget_Append(struct InputWidget* w, char c);
|
||||
/* Redraws text and recalculates associated state. */
|
||||
CC_NOINLINE void InputWidget_UpdateText(struct InputWidget* w);
|
||||
|
||||
|
||||
struct MenuInputDesc;
|
||||
@ -185,7 +189,8 @@ struct ChatInputWidget {
|
||||
char _origBuffer[INPUTWIDGET_MAX_LINES * INPUTWIDGET_LEN];
|
||||
};
|
||||
|
||||
CC_NOINLINE void ChatInputWidget_Create(struct ChatInputWidget* w, FontDesc* font);
|
||||
CC_NOINLINE void ChatInputWidget_Create(struct ChatInputWidget* w);
|
||||
CC_NOINLINE void ChatInputWidget_SetFont(struct ChatInputWidget* w, FontDesc* font);
|
||||
|
||||
|
||||
/* Retrieves the text for the i'th line in the group */
|
||||
@ -198,17 +203,16 @@ struct TextGroupWidget {
|
||||
Widget_Layout
|
||||
int lines, defaultHeight;
|
||||
FontDesc* font;
|
||||
bool placeholderHeight[TEXTGROUPWIDGET_MAX_LINES];
|
||||
/* Whether a line has zero height when that line has no text in it. */
|
||||
bool collapsible[TEXTGROUPWIDGET_MAX_LINES];
|
||||
bool underlineUrls;
|
||||
struct Texture* textures;
|
||||
TextGroupWidget_Get GetLine;
|
||||
void* getLineObj;
|
||||
};
|
||||
|
||||
CC_NOINLINE void TextGroupWidget_Create(struct TextGroupWidget* w, int lines, FontDesc* font, struct Texture* textures, TextGroupWidget_Get getLine);
|
||||
/* Sets whether the given line has non-zero height when that line has no text in it. */
|
||||
/* By default, all lines are placeholder lines. */
|
||||
CC_NOINLINE void TextGroupWidget_SetUsePlaceHolder(struct TextGroupWidget* w, int index, bool placeHolder);
|
||||
CC_NOINLINE void TextGroupWidget_Create(struct TextGroupWidget* w, int lines, struct Texture* textures, TextGroupWidget_Get getLine);
|
||||
CC_NOINLINE void TextGroupWidget_SetFont(struct TextGroupWidget* w, FontDesc* font);
|
||||
/* Deletes first line, then moves all other lines upwards, then redraws last line. */
|
||||
/* NOTE: GetLine must also adjust the lines it returns for this to behave properly. */
|
||||
CC_NOINLINE void TextGroupWidget_ShiftUp(struct TextGroupWidget* w);
|
||||
@ -246,8 +250,7 @@ CC_NOINLINE void PlayerListWidget_GetNameUnder(struct PlayerListWidget* w, int m
|
||||
|
||||
typedef void (*SpecialInputAppendFunc)(void* userData, char c);
|
||||
struct SpecialInputTab {
|
||||
int itemsPerRow, charsPerItem;
|
||||
Size2D titleSize;
|
||||
int itemsPerRow, charsPerItem, titleWidth;
|
||||
String title, contents;
|
||||
};
|
||||
|
||||
@ -259,12 +262,14 @@ struct SpecialInputWidget {
|
||||
struct InputWidget* target;
|
||||
struct Texture tex;
|
||||
FontDesc* font;
|
||||
int titleHeight;
|
||||
struct SpecialInputTab tabs[5];
|
||||
String colString;
|
||||
char _colBuffer[DRAWER2D_MAX_COLS * 4];
|
||||
};
|
||||
|
||||
CC_NOINLINE void SpecialInputWidget_Create(struct SpecialInputWidget* w, FontDesc* font, struct InputWidget* target);
|
||||
CC_NOINLINE void SpecialInputWidget_Redraw(struct SpecialInputWidget* w);
|
||||
CC_NOINLINE void SpecialInputWidget_UpdateCols(struct SpecialInputWidget* w);
|
||||
CC_NOINLINE void SpecialInputWidget_SetActive(struct SpecialInputWidget* w, bool active);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user