~rycwo/forge

ref: HEAD forge/src/gui_layout.c -rw-r--r-- 3.8 KiB
d7ee94d6Ryan Chan Fix missing cd in .build.yml 14 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// This file is part of Forge, the foundation library for Forge tools.
//
// Copyright (C) 2021 Ryan Chan <rycwo@posteo.net>
// SPDX-License-Identifier: GPL-3.0-only
//
// This Source Code Form is subject to the terms of the GNU General Public
// License v3.0 only. You should have received a copy of the license along with
// this program. If not, see <https://www.gnu.org/licenses/>.

#include "forge/gui_layout.h"

#include <assert.h>

#include "forge/matrix.h"
#include "forge/stretchy_buffer.h"
#include "forge/vector.h"

static void
push_vec4(struct fg_vec4_buffer* buffer, fg_vec4 const value) {
	assert(buffer->size < buffer->capacity);
	fg_vec4_copy(buffer->buf[buffer->size++], value);
}

static void
pop_vec4(struct fg_vec4_buffer* buffer, fg_vec4 value) {
	assert(buffer->size > 0);
	fg_vec4_copy(value, buffer->buf[buffer->size - 1]);
	buffer->size--;
}

void
fg_gui_top_layout_container(
		struct fg_gui_context const* context,
		fg_vec4 rect,
		bool absolute) {
	int const top = context->layout.size - 1;
	if (absolute)
		fg_vec4_set(
				rect,
				context->layout_top[0],
				context->layout_top[1],
				context->layout.buf[top][2],
				context->layout.buf[top][3]);
	else
		fg_vec4_copy(rect, context->layout.buf[top]);
}

void
fg_push_gui_layout_container(
		struct fg_gui_context* context,
		fg_vec4 const rect,
		bool absolute) {
	fg_vec4 container;
	if (absolute) {
		fg_vec4_set(
				container,
				rect[0] - context->layout_top[0],
				rect[1] - context->layout_top[1],
				rect[2],
				rect[3]);
		fg_vec2_set(context->layout_top, rect[0], rect[1]);
	}
	else {
		fg_vec4_copy(container, rect);
		fg_vec2_set(
				context->layout_top,
				context->layout_top[0] + rect[0],
				context->layout_top[1] + rect[1]);
	}
	push_vec4(&context->layout, container);
}

void
fg_pop_gui_layout_container(
		struct fg_gui_context* context,
		fg_vec4 rect,
		bool absolute) {
	fg_gui_top_layout_container(context, rect, absolute);
	fg_vec4 container;
	pop_vec4(&context->layout, container);
	fg_vec2_set(
			context->layout_top,
			context->layout_top[0] - container[0],
			context->layout_top[1] - container[1]);
	// Reset next position to zero (relative to top container)
	fg_vec2_set(
			context->next_pos,
			context->layout_top[0],
			context->layout_top[1]);
}

void
fg_set_next_gui_position(
		struct fg_gui_context* context,
		fg_vec2 const pos,
		bool absolute) {
	if (absolute)
		fg_vec2_copy(context->next_pos, pos);
	else
		fg_vec2_set(
				context->next_pos,
				context->layout_top[0] + pos[0],
				context->layout_top[1] + pos[1]);
}

void
fg_pop_next_gui_position(
		struct fg_gui_context* context,
		fg_vec2 pos,
		bool absolute) {
	if (absolute)
		fg_vec2_copy(pos, context->next_pos);
	else
		fg_vec2_set(
				pos,
				context->next_pos[0] - context->layout_top[0],
				context->next_pos[1] - context->layout_top[1]);
	// Reset position to zero (relative to top container) in absolute coords
	fg_vec2_set(
			context->next_pos,
			context->layout_top[0],
			context->layout_top[1]);
}

void
fg_set_gui_transform(struct fg_gui_context* context, fg_mat4 const transform) {
	// Transforms cannot be "nested", new transforms replace the previous one
	fg_mat4_copy(context->transform, transform);
	context->transform_active = true;
}

void
fg_set_gui_transform_identity(struct fg_gui_context* context) {
	fg_mat4_identity(context->transform);
	context->transform_active = false;
}

void
fg_begin_gui_clip(struct fg_gui_context* context, fg_vec4 const rect) {
	// Clips cannot be nested. The existing clip must end first.
	assert(!context->clip);
	assert(context->clips.size < context->clips.capacity);
	int const j = context->clips.size++;
	for (int i = 0; i < 4; ++i)
		context->clips.buf[j * 4 + i] = (float)rect[i];
	context->clip = j;
}

void
fg_end_gui_clip(struct fg_gui_context* context) {
	assert(context->clip);
	context->clip = 0;
}