More UI features & leaderboards for level time
This commit is contained in:
		
							
								
								
									
										2
									
								
								app.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								app.c
									
									
									
									
									
								
							@@ -37,6 +37,7 @@ App *app_NewApp() {
 | 
				
			|||||||
	ui_RebuildUI(app->ui);
 | 
						ui_RebuildUI(app->ui);
 | 
				
			||||||
	ui_PushState(app->ui, ui_TitleMenu);
 | 
						ui_PushState(app->ui, ui_TitleMenu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						app->current_level = NULL;
 | 
				
			||||||
	app->switch_level  = NULL;
 | 
						app->switch_level  = NULL;
 | 
				
			||||||
	app->timescale     = 1.0;
 | 
						app->timescale     = 1.0;
 | 
				
			||||||
	app->clear_color   = RGB(40, 40, 40);
 | 
						app->clear_color   = RGB(40, 40, 40);
 | 
				
			||||||
@@ -83,6 +84,7 @@ void app_Advance(App *app, Duration deltaTime) {
 | 
				
			|||||||
		physics_Advance(app->physics, delta_game);
 | 
							physics_Advance(app->physics, delta_game);
 | 
				
			||||||
		entity_Advance(app->entity, delta_game);
 | 
							entity_Advance(app->entity, delta_game);
 | 
				
			||||||
		camera_Advance(app->camera, delta_game);
 | 
							camera_Advance(app->camera, delta_game);
 | 
				
			||||||
 | 
							app->level_playtime.microseconds += deltaTime.microseconds;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ui_Advance(app->ui, deltaTime);
 | 
						ui_Advance(app->ui, deltaTime);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								app.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								app.h
									
									
									
									
									
								
							@@ -28,7 +28,9 @@ typedef struct _App {
 | 
				
			|||||||
	System_GameTime *time;
 | 
						System_GameTime *time;
 | 
				
			||||||
	System_UI       *ui;
 | 
						System_UI       *ui;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char    *current_level;
 | 
				
			||||||
	char    *switch_level;
 | 
						char    *switch_level;
 | 
				
			||||||
 | 
						Duration level_playtime;
 | 
				
			||||||
	double   timescale;
 | 
						double   timescale;
 | 
				
			||||||
	uint32_t clear_color;
 | 
						uint32_t clear_color;
 | 
				
			||||||
	bool     wantQuit, debugOn;
 | 
						bool     wantQuit, debugOn;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ void app_DebugText(App *app, vector_Vector *vec_string) {
 | 
				
			|||||||
	PUSH_STRING(buf);
 | 
						PUSH_STRING(buf);
 | 
				
			||||||
	snprintf(
 | 
						snprintf(
 | 
				
			||||||
		buf, sizeof(buf) - 1,
 | 
							buf, sizeof(buf) - 1,
 | 
				
			||||||
		"Particle count[0]: %d\n\nUI Stack:\n", tree_Count(app->particle->parts[0]));
 | 
							"Particle count[0]: %d\n\nCurrent Level: %s\nPlaytime: %.4lfs\n\nUI Stack:\n", tree_Count(app->particle->parts[0]), (app->current_level ? app->current_level : "NULL"), duration_Seconds(app->level_playtime));
 | 
				
			||||||
	PUSH_STRING(buf);
 | 
						PUSH_STRING(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (int i = 0; i < vector_Size(app->ui->state); i++) {
 | 
						for (int i = 0; i < vector_Size(app->ui->state); i++) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -238,6 +238,7 @@ void _app_SwitchLevel(App *app) {
 | 
				
			|||||||
	entity_Clear(app->entity);
 | 
						entity_Clear(app->entity);
 | 
				
			||||||
	particle_Clear(app->particle);
 | 
						particle_Clear(app->particle);
 | 
				
			||||||
	app->camera->target              = NULL;
 | 
						app->camera->target              = NULL;
 | 
				
			||||||
 | 
						app->level_playtime.microseconds = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Read every line
 | 
						// Read every line
 | 
				
			||||||
	char linebuf[512];
 | 
						char linebuf[512];
 | 
				
			||||||
@@ -253,7 +254,9 @@ void _app_SwitchLevel(App *app) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(app->switch_level);
 | 
						if (app->current_level)
 | 
				
			||||||
 | 
							free(app->current_level);
 | 
				
			||||||
 | 
						app->current_level = app->switch_level;
 | 
				
			||||||
	app->switch_level  = NULL;
 | 
						app->switch_level  = NULL;
 | 
				
			||||||
	fclose(f);
 | 
						fclose(f);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
#include "player.h"
 | 
					#include "player.h"
 | 
				
			||||||
#include "render_util.h"
 | 
					#include "render_util.h"
 | 
				
			||||||
#include "types.h"
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					#include "ui.h"
 | 
				
			||||||
#include "util/assert.h"
 | 
					#include "util/assert.h"
 | 
				
			||||||
#include "util/rand.h"
 | 
					#include "util/rand.h"
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@@ -171,7 +172,7 @@ void misc_thinker_ChangeLevel(App *app, Entity *e, Duration deltaTime) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger);
 | 
						Box2 worldbox = ABSOLUTE_BOX(e, e->misc->trigger);
 | 
				
			||||||
	if (box2_Intersects(worldbox, playerbox, NULL))
 | 
						if (box2_Intersects(worldbox, playerbox, NULL))
 | 
				
			||||||
		app_QueueLoadLevel(app, e->misc->change_level);
 | 
							ui_EnterIntermission(app->ui, e->misc->change_level);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								types.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								types.c
									
									
									
									
									
								
							@@ -107,6 +107,14 @@ Box2 box2_FromCenter(Vec2 center, Vec2 size) {
 | 
				
			|||||||
			.y = center.y - size.y / 2.0}};
 | 
								.y = center.y - size.y / 2.0}};
 | 
				
			||||||
	return box;
 | 
						return box;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					Box2 box2_FromPivot(Vec2 position, Vec2 pivot, Vec2 size) {
 | 
				
			||||||
 | 
						Box2 box = {
 | 
				
			||||||
 | 
							.size    = size,
 | 
				
			||||||
 | 
							.lefttop = {
 | 
				
			||||||
 | 
								.x = position.x - size.x * pivot.x,
 | 
				
			||||||
 | 
								.y = position.y - size.y * pivot.y}};
 | 
				
			||||||
 | 
						return box;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Box2 box2_Offset(Box2 box, Vec2 offset) {
 | 
					Box2 box2_Offset(Box2 box, Vec2 offset) {
 | 
				
			||||||
	box.lefttop = vec2_Add(box.lefttop, offset);
 | 
						box.lefttop = vec2_Add(box.lefttop, offset);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								types.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								types.h
									
									
									
									
									
								
							@@ -70,6 +70,12 @@ static inline Box2 box2(double x, double y, double width, double height) {
 | 
				
			|||||||
	b.size.y    = height;
 | 
						b.size.y    = height;
 | 
				
			||||||
	return b;
 | 
						return b;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					static inline Box2 box2v(Vec2 lefttop, Vec2 size) {
 | 
				
			||||||
 | 
						Box2 b;
 | 
				
			||||||
 | 
						b.lefttop = lefttop;
 | 
				
			||||||
 | 
						b.size    = size;
 | 
				
			||||||
 | 
						return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Intersection test.
 | 
					// Intersection test.
 | 
				
			||||||
@@ -79,6 +85,7 @@ bool box2_Contains(const Box2 box, const Vec2 point);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Vec2 box2_Center(Box2 box);
 | 
					Vec2 box2_Center(Box2 box);
 | 
				
			||||||
Box2 box2_FromCenter(Vec2 center, Vec2 size);
 | 
					Box2 box2_FromCenter(Vec2 center, Vec2 size);
 | 
				
			||||||
 | 
					Box2 box2_FromPivot(Vec2 position, Vec2 pivot, Vec2 size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Box2 box2_Offset(Box2 box, Vec2 offset);
 | 
					Box2 box2_Offset(Box2 box, Vec2 offset);
 | 
				
			||||||
Box2 box2_OffsetX(Box2 box, double offsetX);
 | 
					Box2 box2_OffsetX(Box2 box, double offsetX);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								ui.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								ui.c
									
									
									
									
									
								
							@@ -12,7 +12,9 @@ const char *ui_StateTitle[ui_StateCount] = {
 | 
				
			|||||||
	"Pause Menu",
 | 
						"Pause Menu",
 | 
				
			||||||
	"Jack's Escape (ver. 3.141592) - Title",
 | 
						"Jack's Escape (ver. 3.141592) - Title",
 | 
				
			||||||
	"Select Level",
 | 
						"Select Level",
 | 
				
			||||||
	"Options"};
 | 
						"Options",
 | 
				
			||||||
 | 
						"Level Finished",
 | 
				
			||||||
 | 
						"Leaderboards"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline double dabs(double x) { return x > 0 ? x : -x; }
 | 
					static inline double dabs(double x) { return x > 0 ? x : -x; }
 | 
				
			||||||
@@ -32,6 +34,7 @@ void ui_DeleteSystem(System_UI *sys) {
 | 
				
			|||||||
	for (int i = 0; i < ui_StateCount; i++)
 | 
						for (int i = 0; i < ui_StateCount; i++)
 | 
				
			||||||
		for (int j = 0; j < vector_Size(sys->parts[i]); j++) {
 | 
							for (int j = 0; j < vector_Size(sys->parts[i]); j++) {
 | 
				
			||||||
			ui_Part *part = (ui_Part *)vector_At(sys->parts[i], j);
 | 
								ui_Part *part = (ui_Part *)vector_At(sys->parts[i], j);
 | 
				
			||||||
 | 
								if (part->free)
 | 
				
			||||||
				part->free(sys, part, part->user);
 | 
									part->free(sys, part, part->user);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	for (int i = 0; i < ui_StateCount; i++)
 | 
						for (int i = 0; i < ui_StateCount; i++)
 | 
				
			||||||
@@ -102,6 +105,7 @@ void ui_Advance(System_UI *sys, Duration deltaTime) {
 | 
				
			|||||||
			part->progress = dmax(part->progress - UI_BUTTON_HOVER_SPEED * duration_Seconds(deltaTime), 0.0);
 | 
								part->progress = dmax(part->progress - UI_BUTTON_HOVER_SPEED * duration_Seconds(deltaTime), 0.0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (part->update)
 | 
				
			||||||
			part->update(sys, part, part->user, deltaTime);
 | 
								part->update(sys, part, part->user, deltaTime);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										50
									
								
								ui.h
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								ui.h
									
									
									
									
									
								
							@@ -17,6 +17,8 @@ typedef enum {
 | 
				
			|||||||
	ui_TitleMenu,
 | 
						ui_TitleMenu,
 | 
				
			||||||
	ui_SceneSelect,
 | 
						ui_SceneSelect,
 | 
				
			||||||
	ui_Options,
 | 
						ui_Options,
 | 
				
			||||||
 | 
						ui_InterMission,
 | 
				
			||||||
 | 
						ui_Leaderboards,
 | 
				
			||||||
	ui_StateCount // Keep at last
 | 
						ui_StateCount // Keep at last
 | 
				
			||||||
} ui_State;
 | 
					} ui_State;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -34,7 +36,7 @@ typedef struct _ui_Part {
 | 
				
			|||||||
	uintptr_t user;                                                                            // user data
 | 
						uintptr_t user;                                                                            // user data
 | 
				
			||||||
	void (*draw)(System_UI *sys, struct _ui_Part *part, uintptr_t user);                       // called when the UI is to be drawn
 | 
						void (*draw)(System_UI *sys, struct _ui_Part *part, uintptr_t user);                       // called when the UI is to be drawn
 | 
				
			||||||
	void (*update)(System_UI *sys, struct _ui_Part *part, uintptr_t user, Duration deltatime); // called when the element is to be updated
 | 
						void (*update)(System_UI *sys, struct _ui_Part *part, uintptr_t user, Duration deltatime); // called when the element is to be updated
 | 
				
			||||||
	void (*free)(System_UI *sys, struct _ui_Part *part, uintptr_t user);                       // called when the element is to be deleted
 | 
						void (*free)(System_UI *sys, struct _ui_Part *part, uintptr_t user);                       // called when the element is to be deleted, dont free part!
 | 
				
			||||||
} ui_Part;
 | 
					} ui_Part;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UI system with its own state machine.
 | 
					// UI system with its own state machine.
 | 
				
			||||||
@@ -59,10 +61,15 @@ void ui_Render(System_UI *sys);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void     ui_PushState(System_UI *sys, ui_State push_state);
 | 
					void     ui_PushState(System_UI *sys, ui_State push_state);
 | 
				
			||||||
void     ui_PopState(System_UI *sys);
 | 
					void     ui_PopState(System_UI *sys);
 | 
				
			||||||
 | 
					 | 
				
			||||||
ui_State ui_CurrentState(System_UI *sys);
 | 
					ui_State ui_CurrentState(System_UI *sys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Called when the level is finished
 | 
				
			||||||
 | 
					// If next_level is NULL, there are no next level and the
 | 
				
			||||||
 | 
					// button returns to title screen
 | 
				
			||||||
 | 
					void ui_EnterIntermission(System_UI *sys, const char *next_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UI_PADDING    (16)
 | 
					#define UI_PADDING    (16)
 | 
				
			||||||
#define UI_BACKGROUND (0)
 | 
					#define UI_BACKGROUND (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -96,6 +103,45 @@ ui_Part ui_Button_NewLeftAligned(Box2 box, const char *label, ui_ActionCallback
 | 
				
			|||||||
// ui_Part ui_Button_NewColored(Box2 box, const char *label, uint32_t bg, uint32_t hover, uint32_t clicked, ui_ActionCallback callback, uintptr_t data);
 | 
					// ui_Part ui_Button_NewColored(Box2 box, const char *label, uint32_t bg, uint32_t hover, uint32_t clicked, ui_ActionCallback callback, uintptr_t data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						char *label; // Allocated & copied, NULL means no label
 | 
				
			||||||
 | 
						int   align; // <0: left aligned; ==0: center aligned; >0: right aligned
 | 
				
			||||||
 | 
					} ui_Label;
 | 
				
			||||||
 | 
					ui_Part ui_Label_New(Box2 box, const char *label, int alignment);
 | 
				
			||||||
 | 
					void    ui_Label_SetLabel(ui_Part *part, const char *label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Creates a new box fill with the given color
 | 
				
			||||||
 | 
					ui_Part ui_Fill_New(Box2 box, uint32_t color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Box organizer
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
						vector_Vector *rows;        // vector of vector_Vector* of Box2
 | 
				
			||||||
 | 
						vector_Vector *row_counts;  // vector of Ints
 | 
				
			||||||
 | 
						double         width;       // Total width, excluding external padding
 | 
				
			||||||
 | 
						double         line_height; // Line height
 | 
				
			||||||
 | 
						Vec2           position;    // Position of the entire bounding box on screen
 | 
				
			||||||
 | 
						Vec2           pivot;       // Pivot or Origin of the position, [0, 1]
 | 
				
			||||||
 | 
					} ui_BoxBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UI_BOXBUILDER_DEFAULT_LINEHEIGHT (48)
 | 
				
			||||||
 | 
					#define UI_BOXBUILDER_DEFAULT_WIDTH      (400)
 | 
				
			||||||
 | 
					#define UI_BOXBUILDER_DEFAULT_PIVOT_X    (0.5)
 | 
				
			||||||
 | 
					#define UI_BOXBUILDER_DEFAULT_PIVOT_Y    (0.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ui_BoxBuilder *ui_BoxBuilder_New();
 | 
				
			||||||
 | 
					void           ui_BoxBuilder_Delete(ui_BoxBuilder *builder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set that this row should have this many columns
 | 
				
			||||||
 | 
					void ui_BoxBuilder_SetCount(ui_BoxBuilder *builder, int row, int num_cols);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Assemble everything
 | 
				
			||||||
 | 
					void ui_BoxBuilder_Assemble(ui_BoxBuilder *builder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Every number starts from 1
 | 
				
			||||||
 | 
					Box2 ui_BoxBuilder_At(ui_BoxBuilder *builder, int row, int col);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										99
									
								
								ui_boxbuilder.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								ui_boxbuilder.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					#include "util/vector.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ui_BoxBuilder *ui_BoxBuilder_New() {
 | 
				
			||||||
 | 
						ui_BoxBuilder *builder = zero_malloc(sizeof(ui_BoxBuilder));
 | 
				
			||||||
 | 
						builder->line_height   = UI_BOXBUILDER_DEFAULT_LINEHEIGHT;
 | 
				
			||||||
 | 
						builder->width         = UI_BOXBUILDER_DEFAULT_WIDTH;
 | 
				
			||||||
 | 
						builder->pivot         = vec2(UI_BOXBUILDER_DEFAULT_PIVOT_X, UI_BOXBUILDER_DEFAULT_PIVOT_Y);
 | 
				
			||||||
 | 
						builder->row_counts    = vector_Create(sizeof(int));
 | 
				
			||||||
 | 
						// builder->rows          = vector_Create(sizeof(vector_Vector *));
 | 
				
			||||||
 | 
						return builder;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void ui_BoxBuilder_Delete(ui_BoxBuilder *builder) {
 | 
				
			||||||
 | 
						vector_Destroy(builder->row_counts);
 | 
				
			||||||
 | 
						for (int i = 0; i < vector_Size(builder->rows); i++) {
 | 
				
			||||||
 | 
							vector_Vector *vr = *((vector_Vector **)vector_At(builder->rows, i));
 | 
				
			||||||
 | 
							if (vr)
 | 
				
			||||||
 | 
								vector_Destroy(vr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vector_Destroy(builder->rows);
 | 
				
			||||||
 | 
						free(builder);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Set that this row should have this many columns
 | 
				
			||||||
 | 
					void ui_BoxBuilder_SetCount(ui_BoxBuilder *builder, int row, int num_cols) {
 | 
				
			||||||
 | 
						if (vector_Size(builder->row_counts) < row) {
 | 
				
			||||||
 | 
							size_t old_size = vector_Size(builder->row_counts);
 | 
				
			||||||
 | 
							vector_Resize(builder->row_counts, row);
 | 
				
			||||||
 | 
							// Set the new parts to zero
 | 
				
			||||||
 | 
							for (int i = old_size; i < row; i++)
 | 
				
			||||||
 | 
								*((int *)vector_At(builder->row_counts, i)) = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*((int *)vector_At(builder->row_counts, row - 1)) = num_cols;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Assemble everything
 | 
				
			||||||
 | 
					void ui_BoxBuilder_Assemble(ui_BoxBuilder *builder) {
 | 
				
			||||||
 | 
						if (builder->rows) {
 | 
				
			||||||
 | 
							// Free the previous vectors
 | 
				
			||||||
 | 
							for (int i = 0; i < vector_Size(builder->rows); i++) {
 | 
				
			||||||
 | 
								vector_Vector *vr = *((vector_Vector **)vector_At(builder->rows, i));
 | 
				
			||||||
 | 
								if (vr)
 | 
				
			||||||
 | 
									vector_Destroy(vr);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							vector_Clear(builder->rows);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							builder->rows = vector_Create(sizeof(vector_Vector *));
 | 
				
			||||||
 | 
						vector_Resize(builder->rows, vector_Size(builder->row_counts));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double cursor_y = 0.0;
 | 
				
			||||||
 | 
						for (int i = 0; i < vector_Size(builder->row_counts); i++) {
 | 
				
			||||||
 | 
							int row_count = *((int *)vector_At(builder->row_counts, i));
 | 
				
			||||||
 | 
							if (row_count == 0) {
 | 
				
			||||||
 | 
								*(vector_Vector **)vector_At(builder->rows, i) = NULL;
 | 
				
			||||||
 | 
								cursor_y += UI_PADDING;
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							vector_Vector *row = vector_Create(sizeof(Box2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*(vector_Vector **)vector_At(builder->rows, i) = row;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Append every box
 | 
				
			||||||
 | 
							double total_width = builder->width - UI_PADDING * (row_count - 1);
 | 
				
			||||||
 | 
							double avg_width   = total_width / row_count;
 | 
				
			||||||
 | 
							for (int i = 0; i < row_count; i++) {
 | 
				
			||||||
 | 
								Box2 box = {
 | 
				
			||||||
 | 
									.lefttop = {.x = i * (avg_width + UI_PADDING), .y = cursor_y},
 | 
				
			||||||
 | 
									.size    = {.x = avg_width, .y = builder->line_height}};
 | 
				
			||||||
 | 
								vector_Push(row, &box);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cursor_y += builder->line_height + UI_PADDING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int  row_num  = vector_Size(builder->row_counts);
 | 
				
			||||||
 | 
						Vec2 max_size = {
 | 
				
			||||||
 | 
							.x = builder->width,
 | 
				
			||||||
 | 
							.y = builder->line_height * row_num + UI_PADDING * (row_num - 1)};
 | 
				
			||||||
 | 
						Box2 max_box = box2_FromPivot(builder->position, builder->pivot, max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Move every box
 | 
				
			||||||
 | 
						for (int i = 0; i < vector_Size(builder->row_counts); i++) {
 | 
				
			||||||
 | 
							int row_count = *((int *)vector_At(builder->row_counts, i));
 | 
				
			||||||
 | 
							if (row_count == 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							vector_Vector *row = *(vector_Vector **)vector_At(builder->rows, i);
 | 
				
			||||||
 | 
							for (int i = 0; i < row_count; i++) {
 | 
				
			||||||
 | 
								Box2 *box    = (Box2 *)vector_At(row, i);
 | 
				
			||||||
 | 
								box->lefttop = vec2_Add(box->lefttop, max_box.lefttop);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Every number starts from 1
 | 
				
			||||||
 | 
					Box2 ui_BoxBuilder_At(ui_BoxBuilder *builder, int row, int col) {
 | 
				
			||||||
 | 
						return *(Box2 *)vector_At(*(vector_Vector **)vector_At(builder->rows, row - 1), col - 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										113
									
								
								ui_build.c
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								ui_build.c
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include "render_util.h"
 | 
				
			||||||
#include "ui.h"
 | 
					#include "ui.h"
 | 
				
			||||||
#include "app.h"
 | 
					#include "app.h"
 | 
				
			||||||
#include "util/vector.h"
 | 
					#include "util/vector.h"
 | 
				
			||||||
@@ -17,7 +18,7 @@ static void _ui_Action_ResumeGame(System_UI *sys, ui_Part *part, uintptr_t data)
 | 
				
			|||||||
static void _ui_Action_ReturnToTitle(System_UI *sys, ui_Part *part, uintptr_t data) {
 | 
					static void _ui_Action_ReturnToTitle(System_UI *sys, ui_Part *part, uintptr_t data) {
 | 
				
			||||||
	while (vector_Size(sys->state) > 0 && ui_CurrentState(sys) != ui_TitleMenu) {
 | 
						while (vector_Size(sys->state) > 0 && ui_CurrentState(sys) != ui_TitleMenu) {
 | 
				
			||||||
		INFO("popping \"%s\"", ui_StateTitle[ui_CurrentState(sys)]);
 | 
							INFO("popping \"%s\"", ui_StateTitle[ui_CurrentState(sys)]);
 | 
				
			||||||
		ui_Action_PopState(sys, part, data);
 | 
							ui_Action_PopState(sys, part, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sys->super->paused = false;
 | 
						sys->super->paused = false;
 | 
				
			||||||
	if (vector_Size(sys->state) == 0)
 | 
						if (vector_Size(sys->state) == 0)
 | 
				
			||||||
@@ -46,6 +47,42 @@ static void _ui_Action_Quit(System_UI *sys, ui_Part *part, uintptr_t data) {
 | 
				
			|||||||
	sys->super->wantQuit = true;
 | 
						sys->super->wantQuit = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void _ui_Action_ReplayLevel(System_UI *sys, ui_Part *part, uintptr_t data) {
 | 
				
			||||||
 | 
						_ui_Action_SelectLevel(sys, part, (uintptr_t)sys->super->current_level);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void _ui_Action_EndIntermission(System_UI *sys, ui_Part *part, uintptr_t data) {
 | 
				
			||||||
 | 
						if (!data)
 | 
				
			||||||
 | 
							// next mission string is NULL, return to title
 | 
				
			||||||
 | 
							_ui_Action_ReturnToTitle(sys, part, 0);
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							// load next level
 | 
				
			||||||
 | 
							// should be able to just use this
 | 
				
			||||||
 | 
							_ui_Action_SelectLevel(sys, part, data);
 | 
				
			||||||
 | 
							free((void *)data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ui_EnterIntermission(System_UI *sys, const char *next_level) {
 | 
				
			||||||
 | 
						// Let's malloc & copy this next_level string
 | 
				
			||||||
 | 
						// And hide it in the last part of this state
 | 
				
			||||||
 | 
						// It must be a button, so put the string in the callback data
 | 
				
			||||||
 | 
						ui_Part *last_part = vector_Back(sys->parts[ui_InterMission]);
 | 
				
			||||||
 | 
						if (((ui_Button *)last_part->user)->callback_data)
 | 
				
			||||||
 | 
							free((void *)((ui_Button *)last_part->user)->callback_data);
 | 
				
			||||||
 | 
						if (!next_level || strlen(next_level) == 0)
 | 
				
			||||||
 | 
							((ui_Button *)last_part->user)->callback_data = 0;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							((ui_Button *)last_part->user)->callback_data = (uintptr_t)copy_malloc(next_level);
 | 
				
			||||||
 | 
						ui_PushState(sys, ui_InterMission);
 | 
				
			||||||
 | 
						sys->super->paused = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to update the UI elements in this State
 | 
				
			||||||
 | 
						//  0            1            2             3             4           5              6                 7              8     9
 | 
				
			||||||
 | 
						// "Level Time" <level_time> "Record Time" <record_time> <seperator> <replay_level> <return_to_title> <leaderboards> <sep> <next_level>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PUSH_UI(part) \
 | 
					#define PUSH_UI(part) \
 | 
				
			||||||
	_p0 = (part);     \
 | 
						_p0 = (part);     \
 | 
				
			||||||
@@ -105,19 +142,23 @@ void ui_RebuildUI(System_UI *sys) {
 | 
				
			|||||||
	p = sys->parts[ui_Paused];
 | 
						p = sys->parts[ui_Paused];
 | 
				
			||||||
	vector_Clear(p);
 | 
						vector_Clear(p);
 | 
				
			||||||
	PUSH_UI(ui_Button_New(
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
		box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300), vec2(400, 40)),
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 250), vec2(400, 40)),
 | 
				
			||||||
		"Resume Game",
 | 
							"Resume Game",
 | 
				
			||||||
		&_ui_Action_ResumeGame, 0))
 | 
							&_ui_Action_ResumeGame, 0))
 | 
				
			||||||
	PUSH_UI(ui_Button_New(
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
		box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300 + (40 + UI_PADDING)), vec2(400, 40)),
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 250 + (40 + UI_PADDING)), vec2(400, 40)),
 | 
				
			||||||
		"Reselect Level",
 | 
							"Reselect Level",
 | 
				
			||||||
		&ui_Action_PushState, (uintptr_t)ui_SceneSelect))
 | 
							&ui_Action_PushState, (uintptr_t)ui_SceneSelect))
 | 
				
			||||||
	PUSH_UI(ui_Button_New(
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
		box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300 + 2 * (40 + UI_PADDING)), vec2(400, 40)),
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 250 + 2 * (40 + UI_PADDING)), vec2(400, 40)),
 | 
				
			||||||
 | 
							"Leaderboard for This Level",
 | 
				
			||||||
 | 
							&ui_Action_PushState, (uintptr_t)ui_Leaderboards))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 250 + 3 * (40 + UI_PADDING)), vec2(400, 40)),
 | 
				
			||||||
		"Options",
 | 
							"Options",
 | 
				
			||||||
		&ui_Action_PushState, (uintptr_t)ui_Options))
 | 
							&ui_Action_PushState, (uintptr_t)ui_Options))
 | 
				
			||||||
	PUSH_UI(ui_Button_New(
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
		box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300 + 3 * (40 + UI_PADDING) + UI_PADDING), vec2(400, 40)),
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 250 + 4 * (40 + UI_PADDING) + UI_PADDING), vec2(400, 40)),
 | 
				
			||||||
		"Return to Title",
 | 
							"Return to Title",
 | 
				
			||||||
		&_ui_Action_ReturnToTitle, 0))
 | 
							&_ui_Action_ReturnToTitle, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,4 +170,66 @@ void ui_RebuildUI(System_UI *sys) {
 | 
				
			|||||||
		box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300), vec2(600, 50)),
 | 
							box2_FromCenter(vec2(SCREEN_WIDTH / 2.0, 300), vec2(600, 50)),
 | 
				
			||||||
		"Return",
 | 
							"Return",
 | 
				
			||||||
		&ui_Action_PopState, 0))
 | 
							&ui_Action_PopState, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// InterMission
 | 
				
			||||||
 | 
						p = sys->parts[ui_InterMission];
 | 
				
			||||||
 | 
						vector_Clear(p);
 | 
				
			||||||
 | 
						ui_BoxBuilder *builder = ui_BoxBuilder_New();
 | 
				
			||||||
 | 
						builder->line_height   = 36;
 | 
				
			||||||
 | 
						builder->pivot         = vec2(0.5, 0.625);
 | 
				
			||||||
 | 
						builder->position      = vec2(SCREEN_WIDTH / 2.0, SCREEN_HEIGHT / 2.0);
 | 
				
			||||||
 | 
						ui_BoxBuilder_SetCount(builder, 1, 1);
 | 
				
			||||||
 | 
						ui_BoxBuilder_SetCount(builder, 2, 1);
 | 
				
			||||||
 | 
						ui_BoxBuilder_SetCount(builder, 4, 2);
 | 
				
			||||||
 | 
						ui_BoxBuilder_SetCount(builder, 5, 1);
 | 
				
			||||||
 | 
						ui_BoxBuilder_SetCount(builder, 7, 1);
 | 
				
			||||||
 | 
						ui_BoxBuilder_Assemble(builder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PUSH_UI(ui_Label_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 1, 1),
 | 
				
			||||||
 | 
							"Time in This Level", -1))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Label_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 1, 1),
 | 
				
			||||||
 | 
							"00:00.00", 1))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Label_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 2, 1),
 | 
				
			||||||
 | 
							"Record Time", -1))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Label_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 2, 1),
 | 
				
			||||||
 | 
							"00:00.00", 1))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Fill_New(
 | 
				
			||||||
 | 
							box2v(
 | 
				
			||||||
 | 
								vec2_Add(
 | 
				
			||||||
 | 
									ui_BoxBuilder_At(builder, 4, 1).lefttop,
 | 
				
			||||||
 | 
									vec2(0, -UI_PADDING)),
 | 
				
			||||||
 | 
								vec2(builder->width, 1.0)),
 | 
				
			||||||
 | 
							RGB(128, 128, 128)));
 | 
				
			||||||
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 4, 1),
 | 
				
			||||||
 | 
							"Replay Level",
 | 
				
			||||||
 | 
							&_ui_Action_ReplayLevel, 0))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 4, 2),
 | 
				
			||||||
 | 
							"Back to Title",
 | 
				
			||||||
 | 
							&_ui_Action_ReturnToTitle, 0))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 5, 1),
 | 
				
			||||||
 | 
							"View Leaderboards for Level",
 | 
				
			||||||
 | 
							&ui_Action_PushState, (uintptr_t)ui_Leaderboards))
 | 
				
			||||||
 | 
						PUSH_UI(ui_Fill_New(
 | 
				
			||||||
 | 
							box2v(
 | 
				
			||||||
 | 
								vec2_Add(
 | 
				
			||||||
 | 
									ui_BoxBuilder_At(builder, 7, 1).lefttop,
 | 
				
			||||||
 | 
									vec2(0, -UI_PADDING)),
 | 
				
			||||||
 | 
								vec2(builder->width, 1.0)),
 | 
				
			||||||
 | 
							RGB(128, 128, 128)));
 | 
				
			||||||
 | 
						PUSH_UI(ui_Button_New(
 | 
				
			||||||
 | 
							ui_BoxBuilder_At(builder, 7, 1),
 | 
				
			||||||
 | 
							"Proceed to Next Level",
 | 
				
			||||||
 | 
							&_ui_Action_EndIntermission, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p = sys->parts[ui_Leaderboards];
 | 
				
			||||||
 | 
						vector_Clear(p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								ui_label.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								ui_label.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void _ui_Fill_Draw(System_UI *sys, ui_Part *part, uintptr_t user);  // Defined in ui_render.cpp
 | 
				
			||||||
 | 
					void _ui_Label_Draw(System_UI *sys, ui_Part *part, uintptr_t user); // Defined in ui_render.cpp
 | 
				
			||||||
 | 
					void _ui_Label_Free(System_UI *sys, ui_Part *part, uintptr_t user) {
 | 
				
			||||||
 | 
						ui_Label *label = (ui_Label *)part->user;
 | 
				
			||||||
 | 
						if (label->label)
 | 
				
			||||||
 | 
							free(label->label);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ui_Part ui_Label_New(Box2 box, const char *label_text, int alignment) {
 | 
				
			||||||
 | 
						ui_Label *label = zero_malloc(sizeof(ui_Label));
 | 
				
			||||||
 | 
						if (label_text && strlen(label_text) > 0)
 | 
				
			||||||
 | 
							label->label = copy_malloc(label_text);
 | 
				
			||||||
 | 
						label->align = alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ui_Part part = {
 | 
				
			||||||
 | 
							.box      = box,
 | 
				
			||||||
 | 
							.progress = .0f,
 | 
				
			||||||
 | 
							.hovered  = false,
 | 
				
			||||||
 | 
							.user     = (uintptr_t)label,
 | 
				
			||||||
 | 
							.draw     = &_ui_Label_Draw,
 | 
				
			||||||
 | 
							.update   = NULL,
 | 
				
			||||||
 | 
							.free     = &_ui_Label_Free};
 | 
				
			||||||
 | 
						return part;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void ui_Label_SetLabel(ui_Part *part, const char *label_text) {
 | 
				
			||||||
 | 
						ui_Label *label = (ui_Label *)part->user;
 | 
				
			||||||
 | 
						size_t    len;
 | 
				
			||||||
 | 
						if (label_text && (len = strlen(label_text)) > 0) {
 | 
				
			||||||
 | 
							if (label->label) {
 | 
				
			||||||
 | 
								label->label = realloc(label->label, len + 1);
 | 
				
			||||||
 | 
								memcpy(label->label, label_text, len + 1);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								label->label = copy_malloc(label_text);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (label->label) {
 | 
				
			||||||
 | 
								free(label->label);
 | 
				
			||||||
 | 
								label->label = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ui_Part ui_Fill_New(Box2 box, uint32_t color) {
 | 
				
			||||||
 | 
						ui_Part part = {
 | 
				
			||||||
 | 
							.box      = box,
 | 
				
			||||||
 | 
							.progress = .0f,
 | 
				
			||||||
 | 
							.hovered  = false,
 | 
				
			||||||
 | 
							.user     = (uintptr_t)color,
 | 
				
			||||||
 | 
							.draw     = &_ui_Fill_Draw,
 | 
				
			||||||
 | 
							.update   = NULL,
 | 
				
			||||||
 | 
							.free     = NULL};
 | 
				
			||||||
 | 
						return part;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -34,6 +34,7 @@ extern "C" void ui_Render(System_UI *sys) {
 | 
				
			|||||||
	if (sys->bg.size.x > sys->bg_target.size.x * 0.9)
 | 
						if (sys->bg.size.x > sys->bg_target.size.x * 0.9)
 | 
				
			||||||
		for (int i = 0; i < vector_Size(sys->parts[layer]); i++) {
 | 
							for (int i = 0; i < vector_Size(sys->parts[layer]); i++) {
 | 
				
			||||||
			ui_Part *part = (ui_Part *)vector_At(sys->parts[layer], i);
 | 
								ui_Part *part = (ui_Part *)vector_At(sys->parts[layer], i);
 | 
				
			||||||
 | 
								if (part->draw)
 | 
				
			||||||
				part->draw(sys, part, part->user);
 | 
									part->draw(sys, part, part->user);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -66,14 +67,46 @@ extern "C" void _ui_Button_Draw(System_UI *sys, ui_Part *part, void *user) {
 | 
				
			|||||||
	setfillcolor(color_final);
 | 
						setfillcolor(color_final);
 | 
				
			||||||
	settextcolor(RGB(255, 255, 255));
 | 
						settextcolor(RGB(255, 255, 255));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Box2 padded_box = part->box;
 | 
					 | 
				
			||||||
	padded_box.lefttop.x += UI_PADDING;
 | 
					 | 
				
			||||||
	padded_box.size.x -= 2 * UI_PADDING;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	solidrectangle(
 | 
						solidrectangle(
 | 
				
			||||||
		(int)round(part->box.lefttop.x),
 | 
							(int)round(part->box.lefttop.x),
 | 
				
			||||||
		(int)round(part->box.lefttop.y),
 | 
							(int)round(part->box.lefttop.y),
 | 
				
			||||||
		(int)round(part->box.lefttop.x + part->box.size.x),
 | 
							(int)round(part->box.lefttop.x + part->box.size.x),
 | 
				
			||||||
		(int)round(part->box.lefttop.y + part->box.size.y));
 | 
							(int)round(part->box.lefttop.y + part->box.size.y));
 | 
				
			||||||
	render_DrawTextEx(b->label, padded_box, (b->left_aligned ? DT_LEFT : DT_CENTER) | DT_VCENTER | DT_SINGLELINE);
 | 
						if (b->left_aligned) {
 | 
				
			||||||
 | 
							Box2 padded_box = part->box;
 | 
				
			||||||
 | 
							padded_box.lefttop.x += UI_PADDING;
 | 
				
			||||||
 | 
							padded_box.size.x -= 2 * UI_PADDING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							render_DrawTextEx(b->label, padded_box, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							render_DrawTextEx(b->label, part->box, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" void _ui_Label_Draw(System_UI *sys, ui_Part *part, uintptr_t user) {
 | 
				
			||||||
 | 
						ui_Label *label = (ui_Label *)user;
 | 
				
			||||||
 | 
						if (!label->label || strlen(label->label) == 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Box2 padded_box = part->box;
 | 
				
			||||||
 | 
						padded_box.lefttop.x += UI_PADDING;
 | 
				
			||||||
 | 
						padded_box.size.x -= 2 * UI_PADDING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setbkcolor(0);
 | 
				
			||||||
 | 
						settextcolor(RGB(255, 255, 255));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (label->align < 0)
 | 
				
			||||||
 | 
							render_DrawTextEx(label->label, padded_box, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
 | 
				
			||||||
 | 
						else if (label->align > 0)
 | 
				
			||||||
 | 
							render_DrawTextEx(label->label, padded_box, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
 | 
				
			||||||
 | 
						else // align == 0
 | 
				
			||||||
 | 
							render_DrawTextEx(label->label, padded_box, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" void _ui_Fill_Draw(System_UI *sys, ui_Part *part, uintptr_t user) {
 | 
				
			||||||
 | 
						setfillcolor(part->user);
 | 
				
			||||||
 | 
						solidrectangle(
 | 
				
			||||||
 | 
							(int)round(part->box.lefttop.x),
 | 
				
			||||||
 | 
							(int)round(part->box.lefttop.y),
 | 
				
			||||||
 | 
							(int)round(part->box.lefttop.x + part->box.size.x),
 | 
				
			||||||
 | 
							(int)round(part->box.lefttop.y + part->box.size.y));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user