M README.md => README.md +28 -37
@@ 1,20 1,22 @@
**Forge** is a suite of artist tools for creating 2d/3d content. The tools are
-simple and [**really fast**](). They are developed with an emphasis on clarity
-and simplicity. Forge software is, and always will be, committed to being
-[free][].
+developed with an emphasis on clarity and simplicity.
Popular content creation applications are monolithic, they all tend to do a
-large number of things rather poorly.
+large number of things rather poorly. This project aims to provide individual,
+purpose-built tools that each solve a particular problem well.
-Forge aims to provide individual, **purpose-built** tools that each solve a
-particular problem well. The magic here is in the flexible data model that allow
-multiple tools to read and write different attributes of the same data
-**simultaneously**. This enables artist teams to collaborate in real-time and
-creates the opportunity for seamless workflows between each stage of the content
-creation pipeline. No more saving of your work to some intercharge format (OBJ,
-Alembic, etc.) in order to transfer it between content creation packages.
+Forge is the name of both the overarching project, and the foundation library
+that Forge tools are built upon. The library provides a common framework for
+programmers to develop digital content creation tools (sometimes abbreviated as
+DCCs). It includes basic support for: linear algebra; geometry processing;
+shading and rendering; and so on. It also provides a fundamental module for
+building responsive graphical user interfaces.
+
+Forge software is, and always will be, committed to being [free][]. Read the
+[docs][] for more information.
[free]: https://www.fsf.org/about/what-is-free-software
+[docs]: https://docs.polyforge.org/
## Overview
@@ 42,32 44,22 @@ Forge projects build using [Meson][meson].
[meson]: https://mesonbuild.com/
-## Mailing list
+### Preprocessor defines
-Subscribe to release and security announcements at [forge-announce][].
+`FG_REAL_64` — Set [`fg_real`][fg_real] to `double` (64-bit). This subsequently
+switches the `fg_vecn`/`fg_matn` coefficient types and the types used by various
+math operations.
-[forge-announce]: https://lists.sr.ht/~rycwo/forge-announce/
+[fg_real]: #
## Contributing
-### Submitting changes
-
-Patches should be submitted to [forge-devel][].
+Patches should be submitted to [forge-devel][]. Please read through the [Style
+Guide][style-guide] and [Contribution Guide][contrib-guide] prior to submission.
+[contrib-guide]: https://docs.polyforge.org/contrib-guide
[forge-devel]: https://lists.sr.ht/~rycwo/forge-devel/
-
-### Formatting your commits
-
-Work as you like locally, then use [`git rebase`][git-rebase]
-([man][git-rebase-man]) to tidy-up your changes before submitting patches.
-
-Each commit should represent an atomic unit of work and leave the repo in a
-working state. Commit messages should have sufficient detail to double as
-details release notes (see [PostgreSQL][postgres]).
-
-[git-rebase-man]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
-[git-rebase]: https://git-rebase.io/
-[postgres]: https://drewdevault.com/2021/08/05/In-praise-of-Postgres.html
+[style-guide]: https://docs.polyforge.org/style-guide
## License
@@ 78,11 70,10 @@ only](LICENSE) [(more info)][gpl-v3], unless otherwise specified.
### Third-party licenses
-[PCG](https://www.pcg-random.org/)
-- [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)
-
-[FreeType 2](https://www.freetype.org/index.html)
-- [Freetype Project License](https://www.freetype.org/license.html)
+- [PCG](https://www.pcg-random.org/) ([Apache License 2.0][])
+- [FreeType 2](https://www.freetype.org/index.html) ([Freetype Project License][])
+- [Manrope](https://manropefont.com/), [Inter](https://rsms.me/inter/) ([SIL Open Font License 1.1][])
-[Manrope](https://manropefont.com/), [Inter](https://rsms.me/inter/)
-- [SIL Open Font License 1.1](https://scripts.sil.org/OFL)
+[Apache License 2.0]: https://git.sr.ht/~rycwo/forge/tree/master/item/src
+[Freetype Project License]: https://www.freetype.org/license.html
+[SIL Open Font License 1.1]: https://scripts.sil.org/OFL
M include/forge/collection.h => include/forge/collection.h +3 -3
@@ 17,8 17,8 @@
/*
* Handle to a memory pool block.
*
- * Use `fg_access_memory_pool_block` to retrieve a pointer to the raw memory for
- * the block.
+ * Use [[fg_access_memory_pool_block]] to retrieve a pointer to the raw memory
+ * for the block.
*/
struct fg_handle {
int32_t id;
@@ 38,7 38,7 @@ struct fg_handle {
* A free list is used to keep track of holes in the buffer to enable constant
* time "alloc" and "free" of individual blocks at runtime. No actual
* allocations/frees occur besides the initial allocation made by
- * `fg_alloc_memory_pool`.
+ * [[fg_alloc_memory_pool]].
*/
struct fg_memory_pool {
struct fg_allocator alloc;
M include/forge/gui_basic.h => include/forge/gui_basic.h +23 -22
@@ 13,19 13,20 @@
#include <stdbool.h>
#include <stdint.h>
+#include "forge/collection.h"
#include "forge/gui_type.h"
#include "forge/type.h"
/*
* Set the active layer to draw proceeding GUI elements to.
*
- * Only two layers are supported at the moment (see `fg_gui_layer`):
- * `FG_GUI_LAYER_BASE`, and `FG_GUI_LAYER_OVERLAY`.
+ * Only two layers are supported at the moment (see [[fg_gui_layer]]):
+ * [[FG_GUI_LAYER_BASE]], and [[FG_GUI_LAYER_OVERLAY]].
*
- * Elements drawn in `FG_GUI_LAYER_OVERLAY` are always drawn on-top of elements
- * in `FG_GUI_LAYER_BASE`. The active layer must always be restored to
- * `FG_GUI_LAYER_BASE` by the end of the frame or a fatal error will be raised
- * on `commit_gui_frame`.
+ * Elements drawn in [[FG_GUI_LAYER_OVERLAY]] are always drawn on-top of
+ * elements in [[FG_GUI_LAYER_BASE]]. The active layer must always be restored
+ * to [[FG_GUI_LAYER_BASE]] by the end of the frame or a fatal error will be
+ * thrown on [[commit_gui_frame]].
*/
void
fg_set_gui_layer(struct fg_gui_context* context, int layer);
@@ 42,11 43,11 @@ fg_gui_rect(
/*
* Push a container onto the layout stack.
*
- * Unlike `fg_push_gui_layout_container`, this is intended to behave like other
- * GUI element functions. It respects `fg_set_next_gui_position` and it draws
- * the container according to the given style.
+ * Unlike [[fg_push_gui_layout_container]], this is intended to behave like
+ * other GUI element functions. It respects [[fg_set_next_gui_position]] and it
+ * draws the container according to the given style.
*
- * This should be bookended by a call to `fg_end_gui_container`.
+ * This should be bookended by a call to [[fg_end_gui_container]].
*/
void
fg_begin_gui_container(
@@ 58,13 59,13 @@ fg_begin_gui_container(
* Pop the top container off the layout stack.
*
* It is an error end a GUI container this without a matching previous call to
- * `fg_begin_gui_container`.
+ * [[fg_begin_gui_container]].
*/
void
fg_end_gui_container(struct fg_gui_context* context);
/*
- * States for `fg_gui_button`.
+ * States for [[fg_gui_button]].
*/
enum fg_gui_button_state {
FG_GUI_BUTTON_STATE_NONE = 0,
@@ 76,8 77,8 @@ enum fg_gui_button_state {
};
/*
- * State bitflags for `fg_gui_button`.
- * See `struct fg_gui_button_style`.
+ * State bitflags for [[fg_gui_button]].
+ * See struct [[fg_gui_button_style]].
*/
enum fg_gui_button_style_state {
FG_GUI_BUTTON_STYLE_NONE = 0,
@@ 91,25 92,25 @@ enum fg_gui_button_style_state {
};
/* Style struct for each possible button state.
- * See `fg_gui_button`.
+ * See [[fg_gui_button]].
*/
struct fg_gui_button_style {
/*
* Array of styles for each button state.
* At the very least a style must be provided for the button's default
- * state `FG_GUI_BUTTON_STATE_NONE`.
+ * state [[FG_GUI_BUTTON_STATE_NONE]].
*/
struct fg_gui_style style[FG_GUI_BUTTON_STATE_Size];
/*
* Styles defined in the `style` array.
- * This should be a bitwise OR of `enum fg_gui_button_style_state` variants
- * for each style set in the `style` array.
+ * This should be a bitwise OR of enum [[fg_gui_button_style_state]]
+ * variants for each style set in the `style` array.
*/
int states;
};
/*
- * Flags for `fg_gui_button`.
+ * Flags for [[fg_gui_button]].
*/
enum fg_gui_button_flag {
FG_GUI_BUTTON_DEFAULT = 0,
@@ 120,7 121,7 @@ enum fg_gui_button_flag {
* Basic button element.
*
* Styles can be configured for each possible button state with
- * `struct fg_gui_button_style`.
+ * struct [[fg_gui_button_style]].
*
* ```c
* struct fg_gui_button_style const button_style = {
@@ 133,14 134,14 @@ enum fg_gui_button_flag {
* ```
*
* At the very least a style must be provided for the button's default state
- * `FG_GUI_BUTTON_STATE_NONE`.
+ * [[FG_GUI_BUTTON_STATE_NONE]].
*
* Returns true if the button was triggered on the current frame.
*
* The default button trigger is determined by a basic sequence of events: left
* mouse button is pressed while positioned over button → left mouse button is
* **released** while positioned over button. If
- * `FG_GUI_BUTTON_TRIGGER_ON_PRESS` is specified, then the trigger happens
+ * [[FG_GUI_BUTTON_TRIGGER_ON_PRESS]] is specified, then the trigger happens
* immediately when the mouse button is **pressed** instead.
*/
bool
M include/forge/gui_context.h => include/forge/gui_context.h +3 -5
@@ 15,13 15,11 @@
/*
* Buffer initialization configuration.
- * See `fg_init_gui`.
+ * See [[fg_init_gui]].
*/
struct fg_gui_buffer_desc {
// Capacity of basic primitive buffer.
int rect_buffer_size;
- // Capacity of text primitive buffer.
- int text_buffer_size;
// Capacity of line primitive buffer.
int line_buffer_size;
// Capacity of layout container stack.
@@ 70,11 68,11 @@ fg_commit_gui_frame(struct fg_gui_context* context);
* Draw GUI elements.
*
* This should only be called once per-frame at any time after
- * `fg_commit_gui_frame`.
+ * [[fg_commit_gui_frame]].
*
* Any draw state that is modified as a result of this call should be restored
* before control is returned to the caller. The graphics backend is a separate
- * implementation that can be customized as needed, e.g. `gui_opengl_46.h`.
+ * implementation that can be customized as needed, e.g. [[gui_opengl_46.h]].
*/
void
fg_draw_gui_frame(struct fg_gui_context* context);
M include/forge/gui_type.h => include/forge/gui_type.h +19 -17
@@ 22,7 22,7 @@
* Input information for the current frame.
*
* Users are expected to update this struct by parsing inputs polled from the OS
- * and passing them to the corresponding functions from `forge/gui_input.h`.
+ * and passing them to the corresponding functions from [[gui_input.h]].
*
* [GLFW](https://www.glfw.org/) example:
*
@@ 71,7 71,7 @@ struct fg_gui_input {
/*
* GUI element draw layer.
- * See `fg_set_gui_layer`.
+ * See [[fg_set_gui_layer]].
*/
enum fg_gui_layer {
FG_GUI_LAYER_BASE = 0,
@@ 80,7 80,7 @@ enum fg_gui_layer {
};
/*
- * Style feature bitflags for `struct fg_gui_style`.
+ * Style feature bitflags for struct [[fg_gui_style]].
*/
enum fg_gui_style_flag {
FG_GUI_STLYE_DEFAULT = 0,
@@ 97,13 97,13 @@ struct fg_gui_style {
float border_width;
// Rounded corner radius in pixels.
float corner_radius;
- // Flags to indicate style features. See `enum fg_gui_style_flag`.
+ // Flags to indicate style features. See enum [[fg_gui_style_flag]].
int flags;
};
/*
* Packed rect representation.
- * Struct members are packed to reduce GPU throughput.
+ * Struct members are packed to increase GPU throughput.
*/
struct fg_gui_rect {
// Adhere to std430 shader storage buffer alignment rules
@@ 116,8 116,10 @@ struct fg_gui_rect {
*
* The rect was originally being compressed into four half (16-bit) floats,
* but the rounding becomes pretty harsh past 1024 so it was reverted back
- * to single-precision floats. We could look at eventually implementing
- * better quantization with more even distribution up to say 8K resolution.
+ * to single-precision floats.
+ *
+ * TODO: We could look at eventually implementing better quantization with
+ * more even distribution up to say 8K resolution.
*/
float rect[4];
// unorm4x8: R, G, B, A.
@@ 144,11 146,11 @@ struct fg_gui_rect {
* Buffer memory is allocated once at the start of the program lifetime and
* re-used each frame, similar to a [memory pool][]. There is no risk of
* fragmentation in its usage as the array is reset at the beginning of each
- * frame with `fg_begin_gui_frame`: rects are appended to the front of the
+ * frame with [[fg_begin_gui_frame]]: rects are appended to the front of the
* array, overwriting elements from the previous frame.
*
- * We make full use of the buffer by writing `FG_GUI_LAYER_BASE` elements to the
- * front of the buffer and `FG_GUI_LAYER_OVERLAY` elements to the back.
+ * We make full use of the buffer by writing [[FG_GUI_LAYER_BASE]] elements to
+ * the front of the buffer and [[FG_GUI_LAYER_OVERLAY]] elements to the back.
*
* [memory pool]: https://en.wikipedia.org/wiki/Memory_pool
*/
@@ 163,9 165,9 @@ struct fg_gui_rect_buffer {
* Monolithic struct storing GUI state.
*
* Most GUI functions receive the context as the first parameter. The context
- * stores global state for GUI modules. Use `fg_init_gui` to create a context
- * struct at the start of the program, eventually followed by `fg_terminate_gui`
- * to cleanup the context at the end of the program.
+ * stores global state for GUI modules. Use [[fg_init_gui]] to create a context
+ * struct at the start of the program, eventually followed by
+ * [[fg_terminate_gui]] to cleanup the context at the end of the program.
*/
struct fg_gui_context {
struct fg_allocator alloc;
@@ 192,19 194,19 @@ struct fg_gui_context {
uint64_t hover;
// Id of the actual item hovered on the current frame. We introduce a single
// frame delay in order to correctly resolve interaction of overlapping
- // elements. See `fg_gui_item_hovered` for implementation details.
+ // elements. See [[fg_gui_item_hovered]] for implementation details.
uint64_t next_hover;
// Layer of the `next_hover` item.
int next_hover_layer;
- // Currently active layer. See `enum fg_gui_layer`.
+ // Currently active layer. See enum [[fg_gui_layer]].
int layer;
// Index of the active clip buffer element.
int clip;
- // Number of elements pushed to base layer, `FG_GUI_LAYER_BASE`.
+ // Number of elements pushed to base layer, [[FG_GUI_LAYER_BASE]].
int32_t base_count;
- // Number of elements pushed to overlay layer, `FG_GUI_LAYER_OVERLAY`.
+ // Number of elements pushed to overlay layer, [[FG_GUI_LAYER_OVERLAY]].
int32_t overlay_count;
// Clip rects.
M include/forge/gui_window.h => include/forge/gui_window.h +36 -29
@@ 22,17 22,17 @@
* module: forge/gui_window.h
*
* Windows are stored and managed by a persistent window manager (see
- * `fg_window_manager`) which organizes windows in a tree.
+ * [[fg_window_manager]]) which organizes windows in a tree.
*
* ## Layout
*
* Window layout and drawing are handled separately. The layout is expected to
* be modified through the functions:
*
- * - `fg_insert_root_window` (this should only be called once)
- * - `fg_insert_window`
- * - `fg_delete_window`
- * - `fg_resize_window_viewport`
+ * - [[fg_insert_root_window]] (this should only be called once)
+ * - [[fg_insert_window]]
+ * - [[fg_delete_window]]
+ * - [[fg_resize_window_viewport]]
*
* ## Drawing
*
@@ 89,18 89,18 @@
* float const width = ...;
* float const height = ...;
*
- * struct fg_handle const win_0 = fg_insert_root_window(
+ * struct fg_window_handle const win_0 = fg_insert_root_window(
* &wm,
* (struct fg_window){fg_hash_string("win_0", ...), "win_0"});
*
- * struct fg_handle const win_1 = fg_insert_window(
+ * struct fg_window_handle const win_1 = fg_insert_window(
* &wm,
* win_0,
* (struct fg_window){fg_hash_string("win_1", ...), "win_1"},
* (struct fg_window_tile_split){width * 0.55, FG_WINDOW_TILE_SPLIT_X},
* FG_WINDOW_TILE_LU);
*
- * struct fg_handle const win_2 = fg_insert_window(
+ * struct fg_window_handle const win_2 = fg_insert_window(
* &wm,
* win_1,
* (struct fg_window){fg_hash_string("win_2", ...), "win_2"},
@@ 167,6 167,13 @@ struct fg_window {
};
/*
+ * Strong typedef for window.
+ */
+struct fg_window_handle {
+ struct fg_handle handle;
+};
+
+/*
* Struct with split properties.
*/
struct fg_window_tile_split {
@@ 175,7 182,7 @@ struct fg_window_tile_split {
// changes in window/monitor size does not affect layout arrangement on
// de-serialization.
fg_real size;
- // Axis across which this split occurs. See `fg_window_tile_split_axis`.
+ // Axis across which this split occurs. See [[fg_window_tile_split_axis]].
int axis;
};
@@ 188,13 195,13 @@ struct fg_window_tile {
struct {
// Properties of this branch/split.
struct fg_window_tile_split split;
- struct fg_handle lhs;
- struct fg_handle rhs;
+ struct fg_window_handle lhs;
+ struct fg_window_handle rhs;
};
// Window at the current node.
struct fg_window window;
};
- struct fg_handle parent;
+ struct fg_window_handle parent;
// Indicate whether this node is a split or window.
bool leaf;
};
@@ 204,18 211,18 @@ struct fg_window_tile {
*
* The tree of windows can be traversed via the `root` node. Members of the
* window manager should not be accessed directly. Instead use the API functions
- * provided for window management and drawing (see `forge/gui_window.h`).
+ * provided for window management and drawing (see [[gui_window.h]]).
*/
struct fg_window_manager {
- // Pool of `fg_window_tile`.
+ // Pool of [[fg_window_tile]].
// Order of structs in this buffer is insignificant. The tree structure can
// be traversed via the `root` node.
struct fg_memory_pool nodes;
// Root of the window tree.
- struct fg_handle root;
+ struct fg_window_handle root;
// TODO. May be useful to highlight selected window, perform actions on a
// given window with a gamepad, etc.
- struct fg_handle active;
+ struct fg_window_handle active;
};
/*
@@ 245,9 252,9 @@ struct fg_window_manager {
* }
* ```
*
- * `user_data` for the callback can be provided when calling `fg_gui_windows`.
+ * `user_data` for the callback can be provided when calling [[fg_gui_windows]].
*
- * See `forge/gui_window.h`.
+ * See [[gui_window.h]].
*/
struct fg_gui_window_draw_callback {
void (*draw)(
@@ 277,22 284,22 @@ fg_terminate_window_manager(struct fg_window_manager* wm);
* Insert root window.
* It is an error to call this when there is already a root window.
*/
-struct fg_handle
+struct fg_window_handle
fg_insert_root_window(struct fg_window_manager* wm, struct fg_window window);
/*
* Insert a window at the given tile.
*
- * The `side` should be specified using `fg_window_tile_side`.
+ * The `side` should be specified using [[fg_window_tile_side]].
*
* Window insertion splits an existing window into two. The newly created window
* is returned and the original window (now occupying the other split) handle is
* updated.
*/
-struct fg_handle
+struct fg_window_handle
fg_insert_window(
struct fg_window_manager* wm,
- struct fg_handle node,
+ struct fg_window_handle node,
struct fg_window window,
struct fg_window_tile_split split,
int side);
@@ 304,7 311,7 @@ fg_insert_window(
* for windows (leaf nodes).
*/
void
-fg_delete_window(struct fg_window_manager* wm, struct fg_handle node);
+fg_delete_window(struct fg_window_manager* wm, struct fg_window_handle node);
/*
* Resize the window viewport.
@@ 315,7 322,7 @@ fg_resize_window_viewport(struct fg_window_manager* wm, fg_vec2 const scale);
/*
* Draw windows from the given window manager `wm`.
- * See `forge/gui_window.h`.
+ * See [[gui_window.h]].
*/
void
fg_gui_windows(
@@ 331,7 338,7 @@ fg_gui_windows(
* Draw an interactable handle that can be used to adjust a window split.
*
* In the current state of the API this is used internally during window drawing
- * and should not be required outside of `fg_gui_windows`.
+ * and should not be required outside of [[fg_gui_windows]].
*/
void
fg_gui_window_split(
@@ 344,11 351,11 @@ fg_gui_window_split(
/*
* Begin window drawing.
*
- * Required prior to invoking the associated `fg_gui_window_draw_callback` for
+ * Required prior to invoking the associated [[fg_gui_window_draw_callback]] for
* the given window.
*
* In the current state of the API this is used internally during window drawing
- * and should not be required outside of `fg_gui_windows`.
+ * and should not be required outside of [[fg_gui_windows]].
*/
void
fg_begin_gui_window(
@@ 360,11 367,11 @@ fg_begin_gui_window(
/*
* End window drawing.
*
- * Required after invoking the associated `fg_gui_window_draw_callback` for
+ * Required after invoking the associated [[fg_gui_window_draw_callback]] for
* the given window.
*
* In the current state of the API this is used internally during window drawing
- * and should not be required outside of `fg_gui_windows`.
+ * and should not be required outside of [[fg_gui_windows]].
*/
void
fg_end_gui_window(struct fg_gui_context* context);
M include/forge/hash_table.h => include/forge/hash_table.h +2 -2
@@ 37,7 37,7 @@
* Allocate storage for the hash table.
*
* If unsure about the capacity, leave it at zero and the hash table will grow
- * automatically on insertion based on `FG_HASH_TABLE_INIT_CAPACITY`.
+ * automatically on insertion based on [[FG_HASH_TABLE_INIT_CAPACITY]].
*/
void
fg_alloc_hash_table(
@@ 64,7 64,7 @@ fg_lookup_hash_table_entry(
* Insert key/value pair into the hash table.
*
* The table will dynamically grow when the load factor passes
- * `FG_HASH_TABLE_MAX_LOAD_FACTOR` (default 0.6).
+ * [[FG_HASH_TABLE_MAX_LOAD_FACTOR]] (default 0.6).
*/
void
fg_insert_hash_table_entry(
M include/forge/math.h.in => include/forge/math.h.in +1 -1
@@ 28,7 28,7 @@ fg_clamp{{$suffix}}({{$type}} value, {{$type}} lower, {{$type}} upper) {
{{end -}}
-// Select math functions to match the precision of fg_real
+// Select math functions to match the precision of [[fg_real]]
#ifndef FG_REAL_64
#define fg_clamp (fg_clampf)
#else
M include/forge/memory_pool.h => include/forge/memory_pool.h +4 -4
@@ 36,9 36,9 @@ fg_free_memory_pool(struct fg_memory_pool* pool);
* Allocate a single block from the memory pool.
*
* This does not perform any further heap allocations than those already made in
- * an initial call to `fg_alloc_memory_pool`. Instead it finds the next free
+ * an initial call to [[fg_alloc_memory_pool]]. Instead it finds the next free
* block in constant O(1) time and returns a handle which can be used with
- * `fg_access_memory_pool_block` to retrieve a pointer to the raw memory.
+ * [[fg_access_memory_pool_block]] to retrieve a pointer to the raw memory.
*/
struct fg_handle
fg_alloc_memory_pool_block(struct fg_memory_pool* pool);
@@ 55,8 55,8 @@ fg_free_memory_pool_block(
* Get pointer to raw memory for the given block.
*
* Block memory will exactly match the block size initially provided to
- * `fg_alloc_memory_pool`. Users are expected to respect this when manipulating
- * the memory returned from this function.
+ * [[fg_alloc_memory_pool]]. Users are expected to respect this when
+ * manipulating the memory returned from this function.
*
* Block access is not reference counted in any way. It is up to the user to
* ensure the block is not freed during use.
M include/forge/meson.build => include/forge/meson.build +1 -0
@@ 3,6 3,7 @@
tmplgen = find_program('tmplgen')
+# Remember to update include/forge/install.sh!
tmpl_headers = [
'math.h.in',
'matrix.h.in',
M include/forge/type.h.in => include/forge/type.h.in +2 -2
@@ 29,7 29,7 @@
* Base real type for math coefficients and operations.
*
* By default real values are single-precision (32-bit) floating-point values.
- * Define `FG_REAL_64` to use double-precision (64-bit).
+ * Define [[FG_REAL_64]] to use double-precision (64-bit).
*/
#ifndef FG_REAL_64
typedef float fg_real;
@@ 74,7 74,7 @@ typedef fg_real fg_mat4[16];
{{- range $n := list 2 3 4 -}}
/*
- * Convenience struct for arrays of `fg_{{$type}}{{$n}}`.
+ * Convenience struct for arrays of [[fg_{{$type}}{{$n}}]].
*/
struct fg_{{$type}}{{$n}}_buffer {
fg_{{$type}}{{$n}}* buf;
R include/forge/stb_sprintf.h => include/stb_sprintf.h +0 -0
M meson.build => meson.build +27 -25
@@ 3,7 3,7 @@ project(
'c',
version : '0.1.0',
license : 'GPL-3.0-only',
- meson_version: '>=0.54.0',
+ meson_version: '>=0.56.0',
default_options : [
'warning_level=3', # Enables -Wall, -Wextra, etc.
'c_std=c11',
@@ 11,9 11,29 @@ project(
deps = [
dependency('GL'),
- dependency('glew', version : '>=2.1.0'),
+ dependency('glew', version : '>=2.2.0')
]
+srcs = files([
+ 'src/compare_float.c',
+ 'src/gui_basic.c',
+ 'src/gui_context.c',
+ 'src/gui_draw.c',
+ 'src/gui_graph.c',
+ 'src/gui_input.c',
+ 'src/gui_layout.c',
+ 'src/gui_opengl_46.c',
+ 'src/gui_util.c',
+ 'src/gui_window.c',
+ 'src/hash_table.c',
+ 'src/memory_pool.c',
+ 'src/murmur_hash.c',
+ 'src/pack_float.c',
+ 'src/pcg_basic.c',
+ 'src/random_double.c',
+ 'src/stb_sprintf.c',
+])
+
# https://mesonbuild.com/howtox.html#add-math-library-lm-portably
cc = meson.get_compiler('c')
deps += cc.find_library('m', required : false)
@@ 44,7 64,9 @@ spirv_gen = generator(
spirv_binary = spirv_gen.process(
files([
'shader/gui_rect.vert.glsl',
- 'shader/gui_rect.frag.glsl'
+ 'shader/gui_rect.frag.glsl',
+ 'shader/gui_line.vert.glsl',
+ 'shader/gui_line.frag.glsl'
]))
# Headers must be generated from inside include/forge for two reasons relating
@@ 65,33 87,14 @@ spirv_binary = spirv_gen.process(
# Generated headers can thus be found in build/include/forge (assuming 'build'
# is your build directory).
-# Declares:
-# gen_headers: list[custom_tgt]
+# Declares: gen_headers list[custom_tgt]
subdir('include/forge')
includes = include_directories('include')
lib = library(
meson.project_name(),
- files([
- 'src/compare_float.c',
- 'src/gui_basic.c',
- 'src/gui_context.c',
- 'src/gui_draw.c',
- 'src/gui_graph.c',
- 'src/gui_input.c',
- 'src/gui_layout.c',
- 'src/gui_opengl_46.c',
- 'src/gui_util.c',
- 'src/gui_window.c',
- 'src/hash_table.c',
- 'src/memory_pool.c',
- 'src/murmur_hash.c',
- 'src/pack_float.c',
- 'src/pcg_basic.c',
- 'src/random_double.c',
- 'src/stb_sprintf.c',
- ]),
+ srcs,
gen_headers,
spirv_binary,
version : meson.project_version(),
@@ 132,7 135,6 @@ install_headers(
'include/forge/pack_float.h',
'include/forge/pcg_basic.h',
'include/forge/random_double.h',
- 'include/forge/stb_sprintf.h',
'include/forge/stretchy_buffer.h',
]),
subdir : meson.project_name())
M src/gui_context.c => src/gui_context.c +3 -3
@@ 39,7 39,7 @@ fg_init_gui(
fg_mat4_identity(context->transform);
context->transform_active = false;
- // FIXME(ryc): Receive clip buffer size as argument
+ // FIXME: Receive clip buffer size as argument
// Default clip is initialized in begin_gui_frame
context->clips.buf = (float*)alloc->alloc(sizeof(float) * 4 * 128);
context->clips.capacity = 128;
@@ 104,8 104,8 @@ fg_commit_gui_frame(struct fg_gui_context* context) {
// Items in the overlay layer are written to the back of the primitive
// buffers in reverse order. The order of the overlay items must be reversed
- // to respect the expected draw order. They also need to be contiguous with
- // the base layer items to simplify GPU operations.
+ // to respect the expected draw order. They are also placed contiguously
+ // with base layer items to simplify GPU operations.
for (int i = 0; i < context->rects.size_back; ++i)
context->rects.prims[context->rects.size_front + i]
M src/gui_window.c => src/gui_window.c +47 -37
@@ 12,6 12,8 @@
#include <assert.h>
#include <string.h>
+#include "stb_sprintf.h"
+
#include "forge/gui_basic.h"
#include "forge/gui_draw.h"
#include "forge/gui_input.h"
@@ 19,18 21,19 @@
#include "forge/hash_table.h"
#include "forge/input.h"
#include "forge/memory_pool.h"
-#include "forge/stb_sprintf.h"
static inline struct fg_window_tile*
-get_window_tile(struct fg_window_manager const* wm, struct fg_handle handle) {
+get_window_tile(
+ struct fg_window_manager const* wm,
+ struct fg_window_handle handle) {
return (struct fg_window_tile*)(
- fg_access_memory_pool_block(&wm->nodes, handle));
+ fg_access_memory_pool_block(&wm->nodes, handle.handle));
}
static void
resize_window(
struct fg_window_manager* wm,
- struct fg_handle node,
+ struct fg_window_handle node,
fg_vec2 const scale) {
struct fg_window_tile* tile = get_window_tile(wm, node);
if (tile->leaf)
@@ 44,15 47,15 @@ static void
draw_gui_window(
struct fg_gui_context* context,
struct fg_window_manager* wm,
- struct fg_handle node,
+ struct fg_window_handle node,
struct fg_gui_style const* style,
struct fg_gui_window_draw_callback const* cb,
void* user_data,
fg_real spacing,
uint64_t seed) {
- // FIXME(rycwo): Although the recursion depth will be probably never be
- // enough to cause a stack overflow, an iterative version of this algorithm
- // would be preferred.
+ // FIXME: Although the recursion depth will be probably never be enough to
+ // cause a stack overflow, an iterative version of this algorithm would be
+ // preferred.
struct fg_window_tile* tile = get_window_tile(wm, node);
@@ 60,7 63,7 @@ draw_gui_window(
fg_gui_top_layout_container(context, container, false);
if (tile->leaf) {
- // FIXME(rycwo): Spacing to system window edges and in-between
+ // FIXME: Spacing to system window edges and in-between
// windows is consistent.
fg_real const half_space = spacing * 0.5;
fg_set_next_gui_position(
@@ 75,15 78,15 @@ draw_gui_window(
container[2] - spacing,
container[3] - spacing
});
- // TODO(rycwo): Draw window decorations (title bar, close button, etc.)
+ // TODO: Draw window decorations (title bar, close button, etc.)
cb->draw(context, &tile->window, user_data);
fg_end_gui_window(context);
return;
}
- // FIXME(rycwo)
+ // FIXME
static char name[32];
- stbsp_snprintf(&name[0], 32, u8"split_%d", node.id);
+ stbsp_snprintf(&name[0], 32, "split_%d", node.handle.id);
int const i = tile->split.axis;
int const j = i ^ 1;
@@ 146,10 149,12 @@ fg_terminate_window_manager(struct fg_window_manager* wm) {
fg_free_memory_pool(&wm->nodes);
}
-struct fg_handle
+struct fg_window_handle
fg_insert_root_window(struct fg_window_manager* wm, struct fg_window window) {
- assert(!fg_handle_valid(&wm->nodes, wm->root));
- struct fg_handle const root_hdl = fg_alloc_memory_pool_block(&wm->nodes);
+ assert(!fg_handle_valid(&wm->nodes, wm->root.handle));
+ struct fg_window_handle const root_hdl = {
+ fg_alloc_memory_pool_block(&wm->nodes)
+ };
struct fg_window_tile* root = get_window_tile(wm, root_hdl);
memset(root, 0, sizeof(struct fg_window_tile));
root->window = window;
@@ 157,19 162,21 @@ fg_insert_root_window(struct fg_window_manager* wm, struct fg_window window) {
return root_hdl;
}
-struct fg_handle
+struct fg_window_handle
fg_insert_window(
struct fg_window_manager* wm,
- struct fg_handle node,
+ struct fg_window_handle node,
struct fg_window window,
struct fg_window_tile_split split,
int side) {
- assert(fg_handle_valid(&wm->nodes, node));
+ assert(fg_handle_valid(&wm->nodes, node.handle));
struct fg_window_tile* other = get_window_tile(wm, node);
assert(other->leaf);
- struct fg_handle const branch_hdl = fg_alloc_memory_pool_block(&wm->nodes);
+ struct fg_window_handle const branch_hdl = {
+ fg_alloc_memory_pool_block(&wm->nodes)
+ };
struct fg_window_tile* branch = get_window_tile(wm, branch_hdl);
branch->split = split;
@@ 177,10 184,10 @@ fg_insert_window(
// Parent the branch under the parent. If there isn't a valid
// parent then we assume we are splitting the root tile.
- struct fg_handle const parent_hdl = other->parent;
- if (fg_handle_valid(&wm->nodes, parent_hdl)) {
+ struct fg_window_handle const parent_hdl = other->parent;
+ if (fg_handle_valid(&wm->nodes, parent_hdl.handle)) {
struct fg_window_tile* parent = get_window_tile(wm, parent_hdl);
- if (parent->lhs.id == node.id)
+ if (parent->lhs.handle.id == node.handle.id)
parent->lhs = branch_hdl;
else
parent->rhs = branch_hdl;
@@ 190,7 197,9 @@ fg_insert_window(
wm->root = branch_hdl;
// Parent the other and new windows under the branch
- struct fg_handle const new_hdl = fg_alloc_memory_pool_block(&wm->nodes);
+ struct fg_window_handle const new_hdl = {
+ fg_alloc_memory_pool_block(&wm->nodes)
+ };
struct fg_window_tile* new = get_window_tile(wm, new_hdl);
new->window = window;
@@ 211,29 220,30 @@ fg_insert_window(
}
void
-fg_delete_window(struct fg_window_manager* wm, struct fg_handle node) {
+fg_delete_window(struct fg_window_manager* wm, struct fg_window_handle node) {
struct fg_window_tile* window = get_window_tile(wm, node);
assert(window->leaf);
- if (node.id == wm->root.id) {
- fg_free_memory_pool_block(&wm->nodes, node);
- memset(&wm->root, 0, sizeof(struct fg_handle));
+ if (node.handle.id == wm->root.handle.id) {
+ fg_free_memory_pool_block(&wm->nodes, node.handle);
+ memset(&wm->root, 0, sizeof(struct fg_window_handle));
return;
}
- struct fg_handle const branch_hdl = window->parent;
+ struct fg_window_handle const branch_hdl = window->parent;
struct fg_window_tile* branch = get_window_tile(wm, branch_hdl);
- struct fg_handle const other_hdl = (branch->lhs.id == node.id)
+ struct fg_window_handle const other_hdl
+ = (branch->lhs.handle.id == node.handle.id)
? branch->rhs : branch->lhs;
struct fg_window_tile* other = get_window_tile(wm, other_hdl);
// Parent the remaining window under the parent. If there isn't
// a valid parent then we assume the window is the new root.
- struct fg_handle const parent_hdl = branch->parent;
- if (fg_handle_valid(&wm->nodes, parent_hdl)) {
+ struct fg_window_handle const parent_hdl = branch->parent;
+ if (fg_handle_valid(&wm->nodes, parent_hdl.handle)) {
struct fg_window_tile* parent = get_window_tile(wm, parent_hdl);
- if (parent->lhs.id == branch_hdl.id)
+ if (parent->lhs.handle.id == branch_hdl.handle.id)
parent->lhs = other_hdl;
else
parent->rhs = other_hdl;
@@ 242,13 252,13 @@ fg_delete_window(struct fg_window_manager* wm, struct fg_handle node) {
else
wm->root = other_hdl;
- fg_free_memory_pool_block(&wm->nodes, node);
- fg_free_memory_pool_block(&wm->nodes, branch_hdl);
+ fg_free_memory_pool_block(&wm->nodes, node.handle);
+ fg_free_memory_pool_block(&wm->nodes, branch_hdl.handle);
}
void
fg_resize_window_viewport(struct fg_window_manager* wm, fg_vec2 const scale) {
- if (!fg_handle_valid(&wm->nodes, wm->root))
+ if (!fg_handle_valid(&wm->nodes, wm->root.handle))
return;
resize_window(wm, wm->root, scale);
}
@@ 262,7 272,7 @@ fg_gui_windows(
void* user_data,
fg_real spacing,
uint64_t seed) {
- if (!fg_handle_valid(&wm->nodes, wm->root))
+ if (!fg_handle_valid(&wm->nodes, wm->root.handle))
return;
fg_vec4 container;
@@ 335,7 345,7 @@ fg_begin_gui_window(
struct fg_gui_style const* style,
fg_vec2 const size) {
assert(id != 0);
- // TODO(rycwo): Interaction
+ // TODO: Interaction
fg_begin_gui_container(context, style, size);
}
M src/stb_sprintf.c => src/stb_sprintf.c +1 -1
@@ 7,4 7,4 @@
* about defining anything.
*/
#define STB_SPRINTF_IMPLEMENTATION
-#include "forge/stb_sprintf.h"
+#include "stb_sprintf.h"