diff --git a/GDD.org b/GDD.org new file mode 100644 index 0000000..a4699c8 --- /dev/null +++ b/GDD.org @@ -0,0 +1,7 @@ +#+TITLE: Projekt Gry "Wschód" + +* Świat gry +** Historia i czas +Wschód. Od początku 2027 do sierpnia. Lubelską jeżdżą namiętnie +pojazdy wojskowe transportujące czołgi, haubice, i gigantyczne +anteny. diff --git a/TODO.org b/TODO.org new file mode 100644 index 0000000..d922514 --- /dev/null +++ b/TODO.org @@ -0,0 +1,49 @@ +#+TITLE: Wschód TODO + +* UI system +** TODO Flowbox proper weighing +** DONE Entry cursor +** DONE Reset UI state (hovered, clicked, focused) on lose UI focus +** DONE Entry UTF-8 support +** TODO UI system major refactoring and redesign +** DONE Think about the UI on_xxx_down/up handling (solved) +** DONE Revamp UI event system +** DONE Implement vtables (something else was done) +** DONE Split the UI code into several files +** DONE UI style system +** DONE Layout weight + absolute size mixing possibility +** DONE Scissoring of out-of-bounds UI elements +** DONE On mouse enter, on mouse leave, and on mouse move callbacks +** DONE Button widget +** TODO Tooltip rendering +** DONE Borders +** DONE Padding/margin +** DONE Aspect ratios +** DONE Checkbox widget +** DONE Spinner widget (ints) +** DONE Scrollable widget +** DONE Stacking glScissor() from parents +** DONE Progress bar widget +** DONE Scroll bar widget +** DONE FlowLayout widget +** DONE Multiline text widget +** DONE Text entry widget +** TODO Movable and resizable windows +** TODO Loading UI from a file or script +** DONE Fix scrollable scrolling being a bit weird +* Entity system +** TODO Entity hit testing +** TODO Entity on hover UI label, outline +** TODO Meshing together N entities for less drawcalls +** TODO Sky/sun/clouds drawing seperate from other entities +** TODO Optimize entity rendering and ticking; it's a huge bottleneck +** TODO Ticking system revamp; ticking calculation when out of tick radius and coming back +* Chunk system +** TODO Chunk queue/heap sorted by distance to player +* Misc. +** TODO Better sky/cloud system, perhaps a hemisphere +** TODO Sun system +* Overall game structure +** TODO Resource packs with shaders, textures, entity templates +** TODO Map pack with heightmap data, materialmap data, entities and their placements +** TODO Guile/Lua integration diff --git a/game/src/entity/entity.c b/game/src/entity/entity.c index 233e674..8188659 100644 --- a/game/src/entity/entity.c +++ b/game/src/entity/entity.c @@ -4,7 +4,7 @@ Entity * Entity_new () { Entity *e = g_new0 (Entity, 1); - e->cull_distance = 100; /* To avoid FPEs. */ + e->cull_distance = 100; e->visible = true; /* Usually are. */ e->origin = ORIGIN_BOTTOM; /* Usually is. */ return e; diff --git a/game/src/entity/entity.h b/game/src/entity/entity.h index 6ee3230..dd75ec9 100644 --- a/game/src/entity/entity.h +++ b/game/src/entity/entity.h @@ -1,10 +1,5 @@ #pragma once -/* TODO: In the future, if entities are out of the tick radius, when - they reappear, calculate what would happen to them during the time - they were out of the radius. Useful for growing plants and - whatnot. */ - #include #include @@ -21,11 +16,7 @@ typedef struct Entity gboolean wavy; void *userdata; - void (*on_tick) (struct Entity *self); - gboolean tick_me_i_dont_care; /* Tick this entity regardless of the - distance and other - predicates. Useful for NPCs. */ vec3 position; vec3 rotation; diff --git a/game/src/ui/#widget_core.h# b/game/src/ui/#widget_core.h# new file mode 100644 index 0000000..a64dfec --- /dev/null +++ b/game/src/ui/#widget_core.h# @@ -0,0 +1,209 @@ +#pragma once + +#include +#include + +#include "widget_fw.h" +#include "widget_render.h" +#include "widget_layout.h" +#include "widget_style.h" +#include "widget_ops.h" + +#include "../util.h" +#include "../resources.h" +#include "../flags.h" +#include "../gl/mesh.h" +#include "../gl/program.h" + +#define WIDGET_FOREACH_CHILD(widget, i, child) \ + for (unsigned int i = 0; i < widget->children->len && \ + ((child = g_array_index(widget->children, Widget *, i)), 1); ++i) + +typedef enum WidgetKind + { + WIDGET_PLAIN, + WIDGET_LABEL, + WIDGET_SCROLLBAR, + WIDGET_PROGRESS, + WIDGET_ENTRY, + + WIDGET_MULTILINE_TEXT, + + WIDGET_CONTAINER, + WIDGET_SCROLLABLE, + WIDGET_FLOWBOX + } WidgetKind; + +typedef enum WidgetIcon + { + ICON_NONE = -1, + ICON_CHECKBOX_UNCHECKED = 0, + ICON_CHECKBOX_CHECKED, + ICON_MINUS, + ICON_PLUS, + ICON_ARROW_LEFT, + ICON_ARROW_RIGHT, + ICON_ARROW_UP, + ICON_ARROW_DOWN + } WidgetIcon; + +typedef enum WidgetEvent + { + EVENT_NONE = -1, /* Don't use. */ + EVENT_TICK = 0, + EVENT_LEFT_DOWN, + EVENT_LEFT_UP, + EVENT_RIGHT_DOWN, + EVENT_RIGHT_UP, + EVENT_MOUSE_ENTER, + EVENT_MOUSE_LEAVE, + EVENT_MOUSE_MOVE, + EVENT_SCROLL_UP, + EVENT_SCROLL_DOWN, + EVENT_FOCUS_GAINED, + EVENT_FOCUS_LOST, + EVENT_TEXT_INPUT, + + EVENT_COUNT + } WidgetEvent; + +typedef enum TextAlignment + { + TEXT_ALIGN_LEFT, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT + } TextAlignment; + +typedef struct LabelWidget +{ + GString *text; + TextAlignment text_alignment; +} LabelWidget; + +typedef struct ScrollbarWidget +{ + struct Widget *target; + gboolean horizontal; + /* Used for input. */ + gboolean dragging; + float drag_offset; +} ScrollbarWidget; + +typedef struct ProgressWidget +{ + gboolean horizontal; + float min, max, *ptr; +} ProgressWidget; + +typedef struct EntryWidget +{ + GString *ghost_text; + GString *content; + /* cursor_position is in UTF-8 characters. */ + int cursor_position; +} EntryWidget; + +typedef struct MultilineTextWidget +{ + GString *text; + GArray *lines; + float line_height; + TextAlignment text_alignment; +} MultilineTextWidget; + +typedef struct ContainerWidget +{ + gboolean horizontal; +} ContainerWidget; + +typedef struct ScrollableWidget +{ + gboolean layout_horizontal; + gboolean layout_vertical; + + float scroll_amount; + vec2 scroll_position; + vec2 content_size; +} ScrollableWidget; + +typedef struct FlowBoxWidget +{ + gboolean horizontal; +} FlowBoxWidget; + +typedef struct Widget +{ + struct Widget *parent; + GArray *children; + + WidgetKind kind; + union + { + LabelWidget label; + ScrollbarWidget scrollbar; + ProgressWidget progress; + MultilineTextWidget multiline_text; + EntryWidget entry; + + ContainerWidget container; + ScrollableWidget scrollable; + FlowBoxWidget flowbox; + }; + + gboolean visible; + gboolean layout_dirty; + gboolean hovered, clicked, focused; + + vec2 position; + vec2 size; + float layout_weight; + float aspect_ratio; + + WidgetStyle *style; + WidgetIcon icon; + + void (*do_layout) (struct Widget *); + void (*do_render) (struct Widget *, mat4, int); + + void (*on_event[EVENT_COUNT]) (struct Widget *, SDL_Event *sdl_event, void *); + void *event_data[EVENT_COUNT]; + + void (*on_key[SDL_SCANCODE_COUNT]) (struct Widget *, SDL_Event *null, void *); + void *key_data[SDL_SCANCODE_COUNT]; +} Widget; + +Widget *Widget_plain_new (); +Widget *Widget_test_new (float size); +Widget *Widget_titlebar_new () +Widget *Widget_label_new (const char *text, TextAlignment alignment); +Widget *Widget_scrollbar_new (Widget *target, gboolean horizontal); +Widget *Widget_progress_new (gboolean horizontal, float min, float max, float *ptr); +Widget *Widget_multiline_text_new (const char *text, float line_height, TextAlignment alignment); +Widget *Widget_entry_new (const char *ghost_text); +Widget *Widget_container_new (gboolean horizontal); +Widget *Widget_scrollable_new (); +Widget *Widget_flowbox_new (gboolean horizontal); + +void Widget_add_child (Widget *parent, Widget *child); +void Widget_add_child_weighed (Widget *parent, Widget *child, + float layout_weight); +void Widget_add_child_flowbox (Widget *parent, Widget *child, + float layout_weight, float cross_axis_size); + +void Widget_set_on_event (Widget *widget, WidgetEvent event, void (*on_event) (Widget *, SDL_Event *, void *), void *userdata); +void Widget_set_on_key (Widget *widget, SDL_Scancode key, void (*on_key) (Widget *, SDL_Event *, void *), void *userdata); +void Widget_set_style (Widget *widget, WidgetStyle style); + +void Widget_label_set_text (Widget *widget, const char *text); +void Widget_label_printf (Widget *widget, const char *format, ...); + +void Widget_entry_input_text (Widget *widget, const char *text); + +void Widget_scrollable_scroll (Widget *widget, vec2 direction); + +Widget *Widget_find_xy_event (Widget *widget, vec2 pos, WidgetEvent event); +Widget *Widget_find_xy (Widget *widget, vec2 point); + +void Widget_tick (Widget *widget); +void Widget_render (Widget *widget, mat4 projection, int window_height); +void Widget_free (Widget *widget); diff --git a/game/src/ui/.#widget_core.h b/game/src/ui/.#widget_core.h new file mode 120000 index 0000000..033778c --- /dev/null +++ b/game/src/ui/.#widget_core.h @@ -0,0 +1 @@ +emssej@Komputer-Ze-Smieci.2278:1750505438 \ No newline at end of file diff --git a/game/src/ui/uiman.c b/game/src/ui/uiman.c index b7b8b0e..b96ab02 100644 --- a/game/src/ui/uiman.c +++ b/game/src/ui/uiman.c @@ -18,15 +18,6 @@ static Widget *hovered_widget = NULL; static Widget *clicked_widget = NULL; static Widget *focused_widget = NULL; -const char *lorem_ipsum = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut " - "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " - "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " - "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in " - "culpa qui officia deserunt mollit anim id est laborum." - " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - "!@#$%^&*()_+{}[]'\";:,<.>/?\\|`~"; - void uiman_init () { @@ -55,29 +46,6 @@ uiman_init () Widget_add_child_flowbox (debug_menu, Widget_composite_checkbox_make ("Flight", "flight_enabled"), 1./2., 20); Widget_add_child (ui_root, debug_menu); - - Widget *console = Widget_container_new (FALSE); - VEC2_SETI (console->position, 418, 32); - VEC2_SETI (console->size, 350, 200); - console->style->layout_padding = 8; - console->style->background_image = RESTEX ("terrain4"); - - Widget *scrollable_container = Widget_container_new (TRUE); - Widget *scrollable = Widget_scrollable_new (); - scrollable->scrollable.layout_horizontal = TRUE; - Widget_add_child_weighed (scrollable, Widget_multiline_text_new (lorem_ipsum, 20, TEXT_ALIGN_LEFT), 1); - Widget *scrollbar = Widget_scrollbar_new (scrollable, FALSE); - scrollbar->size[0] = 20; - Widget_add_child_weighed (scrollable_container, scrollable, 1); - Widget_add_child (scrollable_container, scrollbar); - Widget_add_child_weighed (console, scrollable_container, 1); - - Widget *entry = Widget_entry_new ("Command..."); - entry->style->background_image = RESTEX ("terrain2"); - entry->size[1] = 20; - Widget_add_child (console, entry); - - Widget_add_child (ui_root, console); } void @@ -150,6 +118,8 @@ uiman_cb_switch_focus (SDL_Event *event, void *data) hovered_widget = NULL; _uiman_set_focused (focused_widget, FALSE); focused_widget = NULL; + _uiman_set_clicked (clicked_widget, FALSE); + clicked_widget = NULL; return TRUE; } diff --git a/game/src/ui/widget_core.h b/game/src/ui/widget_core.h index 718693d..eee2662 100644 --- a/game/src/ui/widget_core.h +++ b/game/src/ui/widget_core.h @@ -26,7 +26,7 @@ typedef enum WidgetKind WIDGET_SCROLLBAR, WIDGET_PROGRESS, WIDGET_ENTRY, - + WIDGET_MULTILINE_TEXT, WIDGET_CONTAINER, @@ -95,14 +95,6 @@ typedef struct ProgressWidget float min, max, *ptr; } ProgressWidget; -typedef struct MultilineTextWidget -{ - GString *text; - GArray *lines; - float line_height; - TextAlignment text_alignment; -} MultilineTextWidget; - typedef struct EntryWidget { GString *ghost_text; @@ -111,6 +103,14 @@ typedef struct EntryWidget int cursor_position; } EntryWidget; +typedef struct MultilineTextWidget +{ + GString *text; + GArray *lines; + float line_height; + TextAlignment text_alignment; +} MultilineTextWidget; + typedef struct ContainerWidget { gboolean horizontal; diff --git a/game_map.png b/game_map.png new file mode 100644 index 0000000..2e343d2 Binary files /dev/null and b/game_map.png differ