ui, fix cutting bug, appearance animations, add f32_round
This commit is contained in:
@@ -51,7 +51,7 @@ int main(int argc, char **argv) {
|
|||||||
" -I ../src"
|
" -I ../src"
|
||||||
" /Zi /FC /nologo /Oi"
|
" /Zi /FC /nologo /Oi"
|
||||||
" /WX /W3 /wd4200 /diagnostics:column"
|
" /WX /W3 /wd4200 /diagnostics:column"
|
||||||
" /link /incremental:no"
|
" /link /incremental:no /DEBUG:FULL"
|
||||||
);
|
);
|
||||||
if (ok != 0) return ok;
|
if (ok != 0) return ok;
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ int main(int argc, char **argv) {
|
|||||||
" -I ../src"
|
" -I ../src"
|
||||||
" /Zi /FC /nologo /Oi"
|
" /Zi /FC /nologo /Oi"
|
||||||
" /WX /W3 /wd4200 /diagnostics:column"
|
" /WX /W3 /wd4200 /diagnostics:column"
|
||||||
" /link /incremental:no"
|
" /link /incremental:no /DEBUG:FULL"
|
||||||
);
|
);
|
||||||
if (ok != 0) return ok;
|
if (ok != 0) return ok;
|
||||||
|
|
||||||
|
|||||||
@@ -36,13 +36,21 @@ fn_inline f32 f32_floor(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_floorf(
|
|||||||
fn_inline f64 f64_floor(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_floor(x), floor(x)); }
|
fn_inline f64 f64_floor(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_floor(x), floor(x)); }
|
||||||
fn_inline f32 f32_abs(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabsf(x), fabsf(x)); }
|
fn_inline f32 f32_abs(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabsf(x), fabsf(x)); }
|
||||||
fn_inline f64 f64_abs(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabs(x), fabs(x)); }
|
fn_inline f64 f64_abs(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_fabs(x), fabs(x)); }
|
||||||
fn_inline f32 f32_round(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_roundf(x), roundf(x)); }
|
// fn_inline f32 f32_round(f32 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_roundf(x), roundf(x)); }
|
||||||
fn_inline f64 f64_round(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_round(x), round(x)); }
|
fn_inline f64 f64_round(f64 x) { return IF_PLATFORM_CLANG_ELSE(__builtin_round(x), round(x)); }
|
||||||
fn_inline f64 f64_mod(f64 a, f64 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmod(a, b), fmod(a, b)); }
|
fn_inline f64 f64_mod(f64 a, f64 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmod(a, b), fmod(a, b)); }
|
||||||
fn_inline f32 f32_mod(f32 a, f32 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmodf(a, b), fmodf(a, b)); }
|
fn_inline f32 f32_mod(f32 a, f32 b) { return IF_PLATFORM_CLANG_ELSE(__builtin_fmodf(a, b), fmodf(a, b)); }
|
||||||
|
|
||||||
/*
|
/* https://gitlab.com/nakst/essence/-/blob/master/shared/math.cpp
|
||||||
https://gitlab.com/nakst/essence/-/blob/master/shared/math.cpp
|
**
|
||||||
|
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
** SOFTWARE.
|
||||||
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn f64 f64_exp2(f64 x) {
|
fn f64 f64_exp2(f64 x) {
|
||||||
@@ -161,3 +169,48 @@ fn f64 f64_pow(f64 x, f64 y) {
|
|||||||
fn f32 f32_pow(f32 x, f32 y) {
|
fn f32 f32_pow(f32 x, f32 y) {
|
||||||
return f32_exp2(y * f32_log2(x));
|
return f32_exp2(y * f32_log2(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
/* https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libm/common/s_round.c;hb=master
|
||||||
|
* ====================================================
|
||||||
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||||
|
* Permission to use, copy, modify, and distribute this
|
||||||
|
* software is freely granted, provided that this notice
|
||||||
|
* is preserved.
|
||||||
|
* ====================================================
|
||||||
|
**/
|
||||||
|
f32 f32_round(f32 x) {
|
||||||
|
u32 w = F32_TO_U32(x);
|
||||||
|
/* Most significant word, least significant word. */
|
||||||
|
int exponent_less_127;
|
||||||
|
|
||||||
|
/* Extract exponent field. */
|
||||||
|
exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
|
||||||
|
|
||||||
|
if (exponent_less_127 < 23) {
|
||||||
|
if (exponent_less_127 < 0) {
|
||||||
|
w &= 0x80000000;
|
||||||
|
if (exponent_less_127 == -1)
|
||||||
|
/* Result is +1.0 or -1.0. */
|
||||||
|
w |= ((u32)127 << 23);
|
||||||
|
} else {
|
||||||
|
unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
|
||||||
|
if ((w & exponent_mask) == 0)
|
||||||
|
/* x has an integral value. */
|
||||||
|
return x;
|
||||||
|
|
||||||
|
w += 0x00400000 >> exponent_less_127;
|
||||||
|
w &= ~exponent_mask;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (exponent_less_127 == 128)
|
||||||
|
/* x is NaN or infinite. */
|
||||||
|
return x + x;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
x = U32_TO_F32(w);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|||||||
@@ -544,4 +544,9 @@ fn f32 f32_ease_out_cubic(f32 x) {
|
|||||||
|
|
||||||
fn f32 f32_ease_out_n(f32 x, f32 n) {
|
fn f32 f32_ease_out_n(f32 x, f32 n) {
|
||||||
return 1.f - f32_pow(1.f - x, n);
|
return 1.f - f32_pow(1.f - x, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn r2f32_t r2f32_lerp(r2f32_t a, r2f32_t b, f32 t) {
|
||||||
|
r2f32_t result = { .min = {f32_lerp(a.min.x, b.min.x, t), f32_lerp(a.min.y, b.min.y, t)}, .max = {f32_lerp(a.max.x, b.max.x, t), f32_lerp(a.max.y, b.max.y, t)} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
@@ -259,43 +259,51 @@ fn_inline r3i64_t r3i64_center_halfdim(v3i64_t center, v3i64_t halfdim) { return
|
|||||||
fn r2f32_t r2f32_cut_left(r2f32_t *r, f32 value) {
|
fn r2f32_t r2f32_cut_left(r2f32_t *r, f32 value) {
|
||||||
f32 minx = r->min.x;
|
f32 minx = r->min.x;
|
||||||
r->min.x = MIN(r->min.x + value, r->max.x);
|
r->min.x = MIN(r->min.x + value, r->max.x);
|
||||||
return (r2f32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_right(r2f32_t *r, f32 value) {
|
fn r2f32_t r2f32_cut_right(r2f32_t *r, f32 value) {
|
||||||
f32 maxx = r->max.x;
|
f32 maxx = r->max.x;
|
||||||
r->max.x = MAX(r->min.x, r->max.x - value);
|
r->max.x = MAX(r->min.x, r->max.x - value);
|
||||||
return (r2f32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_top(r2f32_t *r, f32 value) { /* Y is down */
|
fn r2f32_t r2f32_cut_top(r2f32_t *r, f32 value) { /* Y is down */
|
||||||
f32 miny = r->min.y;
|
f32 miny = r->min.y;
|
||||||
r->min.y = MIN(r->max.y, r->min.y + value);
|
r->min.y = MIN(r->max.y, r->min.y + value);
|
||||||
return (r2f32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_bottom(r2f32_t *r, f32 value) { /* Y is down */
|
fn r2f32_t r2f32_cut_bottom(r2f32_t *r, f32 value) { /* Y is down */
|
||||||
f32 maxy = r->max.y;
|
f32 maxy = r->max.y;
|
||||||
r->max.y = MAX(r->min.y, r->max.y - value);
|
r->max.y = MAX(r->min.y, r->max.y - value);
|
||||||
return (r2f32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f32_t r2f32_cut_left_no_squash(r2f32_t *r, f32 value) {
|
fn r2f32_t r2f32_cut_left_no_squash(r2f32_t *r, f32 value) {
|
||||||
f32 minx = r->min.x;
|
f32 minx = r->min.x;
|
||||||
r->min.x = r->min.x + value;
|
r->min.x = r->min.x + value;
|
||||||
return (r2f32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_right_no_squash(r2f32_t *r, f32 value) {
|
fn r2f32_t r2f32_cut_right_no_squash(r2f32_t *r, f32 value) {
|
||||||
f32 maxx = r->max.x;
|
f32 maxx = r->max.x;
|
||||||
r->max.x = r->max.x - value;
|
r->max.x = r->max.x - value;
|
||||||
return (r2f32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_top_no_squash(r2f32_t *r, f32 value) { /* Y is down */
|
fn r2f32_t r2f32_cut_top_no_squash(r2f32_t *r, f32 value) { /* Y is down */
|
||||||
f32 miny = r->min.y;
|
f32 miny = r->min.y;
|
||||||
r->min.y = r->min.y + value;
|
r->min.y = r->min.y + value;
|
||||||
return (r2f32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f32_t r2f32_cut_bottom_no_squash(r2f32_t *r, f32 value) { /* Y is down */
|
fn r2f32_t r2f32_cut_bottom_no_squash(r2f32_t *r, f32 value) { /* Y is down */
|
||||||
f32 maxy = r->max.y;
|
f32 maxy = r->max.y;
|
||||||
r->max.y = r->max.y - value;
|
r->max.y = r->max.y - value;
|
||||||
return (r2f32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f32_t r2f32_add_left(r2f32_t *r, f32 value) {
|
fn r2f32_t r2f32_add_left(r2f32_t *r, f32 value) {
|
||||||
@@ -358,6 +366,7 @@ fn r2f32_t r2f32_get_bottom(const r2f32_t *r, f32 value) { /* Y is down */
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn_inline r2f32_t r2f32_shrink(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_add(rect.min, value), v2f32_sub(rect.max, value) }; }
|
fn_inline r2f32_t r2f32_shrink(r2f32_t rect, v2f32_t value) { return (r2f32_t){ v2f32_add(rect.min, value), v2f32_sub(rect.max, value) }; }
|
||||||
fn_inline r2f32_t r2f32_shrinks(r2f32_t rect, f32 value) { return (r2f32_t){ v2f32_adds(rect.min, value), v2f32_subs(rect.max, value) }; }
|
fn_inline r2f32_t r2f32_shrinks(r2f32_t rect, f32 value) { return (r2f32_t){ v2f32_adds(rect.min, value), v2f32_subs(rect.max, value) }; }
|
||||||
fn_inline v2f32_t r2f32_get_size(r2f32_t r) { return (v2f32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
fn_inline v2f32_t r2f32_get_size(r2f32_t r) { return (v2f32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
||||||
@@ -370,43 +379,51 @@ fn_inline r2f32_t r2f32_union(r2f32_t a, r2f32_t b) { return (r2f32_t){ .min.x =
|
|||||||
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
|
||||||
f64 minx = r->min.x;
|
f64 minx = r->min.x;
|
||||||
r->min.x = MIN(r->min.x + value, r->max.x);
|
r->min.x = MIN(r->min.x + value, r->max.x);
|
||||||
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
|
||||||
f64 maxx = r->max.x;
|
f64 maxx = r->max.x;
|
||||||
r->max.x = MAX(r->min.x, r->max.x - value);
|
r->max.x = MAX(r->min.x, r->max.x - value);
|
||||||
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 miny = r->min.y;
|
f64 miny = r->min.y;
|
||||||
r->min.y = MIN(r->max.y, r->min.y + value);
|
r->min.y = MIN(r->max.y, r->min.y + value);
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 maxy = r->max.y;
|
f64 maxy = r->max.y;
|
||||||
r->max.y = MAX(r->min.y, r->max.y - value);
|
r->max.y = MAX(r->min.y, r->max.y - value);
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
|
||||||
f64 minx = r->min.x;
|
f64 minx = r->min.x;
|
||||||
r->min.x = r->min.x + value;
|
r->min.x = r->min.x + value;
|
||||||
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
|
||||||
f64 maxx = r->max.x;
|
f64 maxx = r->max.x;
|
||||||
r->max.x = r->max.x - value;
|
r->max.x = r->max.x - value;
|
||||||
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 miny = r->min.y;
|
f64 miny = r->min.y;
|
||||||
r->min.y = r->min.y + value;
|
r->min.y = r->min.y + value;
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 maxy = r->max.y;
|
f64 maxy = r->max.y;
|
||||||
r->max.y = r->max.y - value;
|
r->max.y = r->max.y - value;
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
|
||||||
@@ -469,6 +486,7 @@ fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
|
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
|
||||||
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
|
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
|
||||||
fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
||||||
@@ -481,43 +499,51 @@ fn_inline r2f64_t r2f64_union(r2f64_t a, r2f64_t b) { return (r2f64_t){ .min.x =
|
|||||||
fn r2i32_t r2i32_cut_left(r2i32_t *r, i32 value) {
|
fn r2i32_t r2i32_cut_left(r2i32_t *r, i32 value) {
|
||||||
i32 minx = r->min.x;
|
i32 minx = r->min.x;
|
||||||
r->min.x = MIN(r->min.x + value, r->max.x);
|
r->min.x = MIN(r->min.x + value, r->max.x);
|
||||||
return (r2i32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2i32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_right(r2i32_t *r, i32 value) {
|
fn r2i32_t r2i32_cut_right(r2i32_t *r, i32 value) {
|
||||||
i32 maxx = r->max.x;
|
i32 maxx = r->max.x;
|
||||||
r->max.x = MAX(r->min.x, r->max.x - value);
|
r->max.x = MAX(r->min.x, r->max.x - value);
|
||||||
return (r2i32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2i32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_top(r2i32_t *r, i32 value) { /* Y is down */
|
fn r2i32_t r2i32_cut_top(r2i32_t *r, i32 value) { /* Y is down */
|
||||||
i32 miny = r->min.y;
|
i32 miny = r->min.y;
|
||||||
r->min.y = MIN(r->max.y, r->min.y + value);
|
r->min.y = MIN(r->max.y, r->min.y + value);
|
||||||
return (r2i32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2i32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_bottom(r2i32_t *r, i32 value) { /* Y is down */
|
fn r2i32_t r2i32_cut_bottom(r2i32_t *r, i32 value) { /* Y is down */
|
||||||
i32 maxy = r->max.y;
|
i32 maxy = r->max.y;
|
||||||
r->max.y = MAX(r->min.y, r->max.y - value);
|
r->max.y = MAX(r->min.y, r->max.y - value);
|
||||||
return (r2i32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2i32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2i32_t r2i32_cut_left_no_squash(r2i32_t *r, i32 value) {
|
fn r2i32_t r2i32_cut_left_no_squash(r2i32_t *r, i32 value) {
|
||||||
i32 minx = r->min.x;
|
i32 minx = r->min.x;
|
||||||
r->min.x = r->min.x + value;
|
r->min.x = r->min.x + value;
|
||||||
return (r2i32_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2i32_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_right_no_squash(r2i32_t *r, i32 value) {
|
fn r2i32_t r2i32_cut_right_no_squash(r2i32_t *r, i32 value) {
|
||||||
i32 maxx = r->max.x;
|
i32 maxx = r->max.x;
|
||||||
r->max.x = r->max.x - value;
|
r->max.x = r->max.x - value;
|
||||||
return (r2i32_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2i32_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_top_no_squash(r2i32_t *r, i32 value) { /* Y is down */
|
fn r2i32_t r2i32_cut_top_no_squash(r2i32_t *r, i32 value) { /* Y is down */
|
||||||
i32 miny = r->min.y;
|
i32 miny = r->min.y;
|
||||||
r->min.y = r->min.y + value;
|
r->min.y = r->min.y + value;
|
||||||
return (r2i32_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2i32_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i32_t r2i32_cut_bottom_no_squash(r2i32_t *r, i32 value) { /* Y is down */
|
fn r2i32_t r2i32_cut_bottom_no_squash(r2i32_t *r, i32 value) { /* Y is down */
|
||||||
i32 maxy = r->max.y;
|
i32 maxy = r->max.y;
|
||||||
r->max.y = r->max.y - value;
|
r->max.y = r->max.y - value;
|
||||||
return (r2i32_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2i32_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2i32_t r2i32_add_left(r2i32_t *r, i32 value) {
|
fn r2i32_t r2i32_add_left(r2i32_t *r, i32 value) {
|
||||||
@@ -580,6 +606,7 @@ fn r2i32_t r2i32_get_bottom(const r2i32_t *r, i32 value) { /* Y is down */
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn_inline r2i32_t r2i32_shrink(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_add(rect.min, value), v2i32_sub(rect.max, value) }; }
|
fn_inline r2i32_t r2i32_shrink(r2i32_t rect, v2i32_t value) { return (r2i32_t){ v2i32_add(rect.min, value), v2i32_sub(rect.max, value) }; }
|
||||||
fn_inline r2i32_t r2i32_shrinks(r2i32_t rect, i32 value) { return (r2i32_t){ v2i32_adds(rect.min, value), v2i32_subs(rect.max, value) }; }
|
fn_inline r2i32_t r2i32_shrinks(r2i32_t rect, i32 value) { return (r2i32_t){ v2i32_adds(rect.min, value), v2i32_subs(rect.max, value) }; }
|
||||||
fn_inline v2i32_t r2i32_get_size(r2i32_t r) { return (v2i32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
fn_inline v2i32_t r2i32_get_size(r2i32_t r) { return (v2i32_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
||||||
@@ -592,43 +619,51 @@ fn_inline r2i32_t r2i32_union(r2i32_t a, r2i32_t b) { return (r2i32_t){ .min.x =
|
|||||||
fn r2i64_t r2i64_cut_left(r2i64_t *r, i64 value) {
|
fn r2i64_t r2i64_cut_left(r2i64_t *r, i64 value) {
|
||||||
i64 minx = r->min.x;
|
i64 minx = r->min.x;
|
||||||
r->min.x = MIN(r->min.x + value, r->max.x);
|
r->min.x = MIN(r->min.x + value, r->max.x);
|
||||||
return (r2i64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2i64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_right(r2i64_t *r, i64 value) {
|
fn r2i64_t r2i64_cut_right(r2i64_t *r, i64 value) {
|
||||||
i64 maxx = r->max.x;
|
i64 maxx = r->max.x;
|
||||||
r->max.x = MAX(r->min.x, r->max.x - value);
|
r->max.x = MAX(r->min.x, r->max.x - value);
|
||||||
return (r2i64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2i64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_top(r2i64_t *r, i64 value) { /* Y is down */
|
fn r2i64_t r2i64_cut_top(r2i64_t *r, i64 value) { /* Y is down */
|
||||||
i64 miny = r->min.y;
|
i64 miny = r->min.y;
|
||||||
r->min.y = MIN(r->max.y, r->min.y + value);
|
r->min.y = MIN(r->max.y, r->min.y + value);
|
||||||
return (r2i64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2i64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_bottom(r2i64_t *r, i64 value) { /* Y is down */
|
fn r2i64_t r2i64_cut_bottom(r2i64_t *r, i64 value) { /* Y is down */
|
||||||
i64 maxy = r->max.y;
|
i64 maxy = r->max.y;
|
||||||
r->max.y = MAX(r->min.y, r->max.y - value);
|
r->max.y = MAX(r->min.y, r->max.y - value);
|
||||||
return (r2i64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2i64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2i64_t r2i64_cut_left_no_squash(r2i64_t *r, i64 value) {
|
fn r2i64_t r2i64_cut_left_no_squash(r2i64_t *r, i64 value) {
|
||||||
i64 minx = r->min.x;
|
i64 minx = r->min.x;
|
||||||
r->min.x = r->min.x + value;
|
r->min.x = r->min.x + value;
|
||||||
return (r2i64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2i64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_right_no_squash(r2i64_t *r, i64 value) {
|
fn r2i64_t r2i64_cut_right_no_squash(r2i64_t *r, i64 value) {
|
||||||
i64 maxx = r->max.x;
|
i64 maxx = r->max.x;
|
||||||
r->max.x = r->max.x - value;
|
r->max.x = r->max.x - value;
|
||||||
return (r2i64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2i64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_top_no_squash(r2i64_t *r, i64 value) { /* Y is down */
|
fn r2i64_t r2i64_cut_top_no_squash(r2i64_t *r, i64 value) { /* Y is down */
|
||||||
i64 miny = r->min.y;
|
i64 miny = r->min.y;
|
||||||
r->min.y = r->min.y + value;
|
r->min.y = r->min.y + value;
|
||||||
return (r2i64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2i64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2i64_t r2i64_cut_bottom_no_squash(r2i64_t *r, i64 value) { /* Y is down */
|
fn r2i64_t r2i64_cut_bottom_no_squash(r2i64_t *r, i64 value) { /* Y is down */
|
||||||
i64 maxy = r->max.y;
|
i64 maxy = r->max.y;
|
||||||
r->max.y = r->max.y - value;
|
r->max.y = r->max.y - value;
|
||||||
return (r2i64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2i64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2i64_t r2i64_add_left(r2i64_t *r, i64 value) {
|
fn r2i64_t r2i64_add_left(r2i64_t *r, i64 value) {
|
||||||
@@ -691,6 +726,7 @@ fn r2i64_t r2i64_get_bottom(const r2i64_t *r, i64 value) { /* Y is down */
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn_inline r2i64_t r2i64_shrink(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_add(rect.min, value), v2i64_sub(rect.max, value) }; }
|
fn_inline r2i64_t r2i64_shrink(r2i64_t rect, v2i64_t value) { return (r2i64_t){ v2i64_add(rect.min, value), v2i64_sub(rect.max, value) }; }
|
||||||
fn_inline r2i64_t r2i64_shrinks(r2i64_t rect, i64 value) { return (r2i64_t){ v2i64_adds(rect.min, value), v2i64_subs(rect.max, value) }; }
|
fn_inline r2i64_t r2i64_shrinks(r2i64_t rect, i64 value) { return (r2i64_t){ v2i64_adds(rect.min, value), v2i64_subs(rect.max, value) }; }
|
||||||
fn_inline v2i64_t r2i64_get_size(r2i64_t r) { return (v2i64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
fn_inline v2i64_t r2i64_get_size(r2i64_t r) { return (v2i64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
||||||
|
|||||||
@@ -207,43 +207,51 @@ for basic_type in basic_types:
|
|||||||
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_left(r2f64_t *r, f64 value) {
|
||||||
f64 minx = r->min.x;
|
f64 minx = r->min.x;
|
||||||
r->min.x = MIN(r->min.x + value, r->max.x);
|
r->min.x = MIN(r->min.x + value, r->max.x);
|
||||||
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_right(r2f64_t *r, f64 value) {
|
||||||
f64 maxx = r->max.x;
|
f64 maxx = r->max.x;
|
||||||
r->max.x = MAX(r->min.x, r->max.x - value);
|
r->max.x = MAX(r->min.x, r->max.x - value);
|
||||||
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_top(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 miny = r->min.y;
|
f64 miny = r->min.y;
|
||||||
r->min.y = MIN(r->max.y, r->min.y + value);
|
r->min.y = MIN(r->max.y, r->min.y + value);
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_bottom(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 maxy = r->max.y;
|
f64 maxy = r->max.y;
|
||||||
r->max.y = MAX(r->min.y, r->max.y - value);
|
r->max.y = MAX(r->min.y, r->max.y - value);
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_left_no_squash(r2f64_t *r, f64 value) {
|
||||||
f64 minx = r->min.x;
|
f64 minx = r->min.x;
|
||||||
r->min.x = r->min.x + value;
|
r->min.x = r->min.x + value;
|
||||||
return (r2f64_t){ .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
r2f64_t result = { .min = {.x = minx, .y = r->min.y}, .max = {.x = r->min.x, .y =r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_cut_right_no_squash(r2f64_t *r, f64 value) {
|
||||||
f64 maxx = r->max.x;
|
f64 maxx = r->max.x;
|
||||||
r->max.x = r->max.x - value;
|
r->max.x = r->max.x - value;
|
||||||
return (r2f64_t){ .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
r2f64_t result = { .min = {.x = r->max.x, .y = r->min.y}, .max = {.x = maxx, .y = r->max.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_top_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 miny = r->min.y;
|
f64 miny = r->min.y;
|
||||||
r->min.y = r->min.y + value;
|
r->min.y = r->min.y + value;
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = miny}, .max = {.x = r->max.x, .y = r->min.y} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
fn r2f64_t r2f64_cut_bottom_no_squash(r2f64_t *r, f64 value) { /* Y is down */
|
||||||
f64 maxy = r->max.y;
|
f64 maxy = r->max.y;
|
||||||
r->max.y = r->max.y - value;
|
r->max.y = r->max.y - value;
|
||||||
return (r2f64_t){ .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
r2f64_t result = { .min = {.x = r->min.x, .y = r->max.y}, .max = {.x = r->max.x, .y = maxy} };
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
|
fn r2f64_t r2f64_add_left(r2f64_t *r, f64 value) {
|
||||||
@@ -306,6 +314,7 @@ fn r2f64_t r2f64_get_bottom(const r2f64_t *r, f64 value) { /* Y is down */
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
|
fn_inline r2f64_t r2f64_shrink(r2f64_t rect, v2f64_t value) { return (r2f64_t){ v2f64_add(rect.min, value), v2f64_sub(rect.max, value) }; }
|
||||||
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
|
fn_inline r2f64_t r2f64_shrinks(r2f64_t rect, f64 value) { return (r2f64_t){ v2f64_adds(rect.min, value), v2f64_subs(rect.max, value) }; }
|
||||||
fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
fn_inline v2f64_t r2f64_get_size(r2f64_t r) { return (v2f64_t){r.max.x - r.min.x, r.max.y - r.min.y}; }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
rn_atlas_t *rn_create_atlas(ma_arena_t *arena, v2i32_t size) {
|
fn rn_atlas_t *rn_create_atlas(ma_arena_t *arena, v2i32_t size) {
|
||||||
rn_atlas_t *result = ma_push_type(arena, rn_atlas_t);
|
rn_atlas_t *result = ma_push_type(arena, rn_atlas_t);
|
||||||
result->size = size;
|
result->size = size;
|
||||||
result->inverse_size.x = 1.f / (f32)result->size.x;
|
result->inverse_size.x = 1.f / (f32)result->size.x;
|
||||||
@@ -22,7 +22,7 @@ rn_atlas_t *rn_create_atlas(ma_arena_t *arena, v2i32_t size) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
r2f32_t rn_pack_bitmap(rn_atlas_t *atlas, u8 *bitmap, i32 width, i32 height) {
|
fn r2f32_t rn_pack_bitmap(rn_atlas_t *atlas, u8 *bitmap, i32 width, i32 height) {
|
||||||
// Packing into a texture atlas
|
// Packing into a texture atlas
|
||||||
// @Inefficient The algorithm is a simplest thing I had in mind, first we advance
|
// @Inefficient The algorithm is a simplest thing I had in mind, first we advance
|
||||||
// through the atlas in X packing consecutive glyphs. After we get to the end of the row
|
// through the atlas in X packing consecutive glyphs. After we get to the end of the row
|
||||||
@@ -59,7 +59,7 @@ r2f32_t rn_pack_bitmap(rn_atlas_t *atlas, u8 *bitmap, i32 width, i32 height) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rn_font_t *rn_create_font(ma_arena_t *arena) {
|
fn rn_font_t *rn_create_font(ma_arena_t *arena) {
|
||||||
rn_font_t *font = ma_push_type(arena, rn_font_t);
|
rn_font_t *font = ma_push_type(arena, rn_font_t);
|
||||||
font->first_char = ' ';
|
font->first_char = ' ';
|
||||||
font->last_char = '~';
|
font->last_char = '~';
|
||||||
@@ -68,7 +68,7 @@ rn_font_t *rn_create_font(ma_arena_t *arena) {
|
|||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 rn_reload_font_atlas(rn_font_t *font, s8_t font_data, rn_atlas_t *atlas, i32 size) {
|
fn b32 rn_reload_font_atlas(rn_font_t *font, s8_t font_data, rn_atlas_t *atlas, i32 size) {
|
||||||
font->glyph_count = 0;
|
font->glyph_count = 0;
|
||||||
stbtt_fontinfo stb_font;
|
stbtt_fontinfo stb_font;
|
||||||
i32 success = stbtt_InitFont(&stb_font, (const unsigned char *)font_data.str, 0);
|
i32 success = stbtt_InitFont(&stb_font, (const unsigned char *)font_data.str, 0);
|
||||||
@@ -107,7 +107,7 @@ b32 rn_reload_font_atlas(rn_font_t *font, s8_t font_data, rn_atlas_t *atlas, i32
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rn_glyph_t *rn_get_glyph(rn_font_t *font, u32 codepoint) {
|
fn rn_glyph_t *rn_get_glyph(rn_font_t *font, u32 codepoint) {
|
||||||
b32 is_in_range = codepoint >= font->first_char && codepoint <= font->last_char;
|
b32 is_in_range = codepoint >= font->first_char && codepoint <= font->last_char;
|
||||||
if (is_in_range) {
|
if (is_in_range) {
|
||||||
u32 index = codepoint - font->first_char;
|
u32 index = codepoint - font->first_char;
|
||||||
|
|||||||
273
src/ui/ui.c
273
src/ui/ui.c
@@ -84,6 +84,10 @@ fn u64 ui_hash_from_stack(void) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn b32 ui_id_is_null(ui_id_t id) {
|
||||||
|
return id.value == 0;
|
||||||
|
}
|
||||||
|
|
||||||
fn ui_id_t ui_id(s8_t string) {
|
fn ui_id_t ui_id(s8_t string) {
|
||||||
string = ui_get_hash_string(string);
|
string = ui_get_hash_string(string);
|
||||||
u64 string_hash = hash_data(string);
|
u64 string_hash = hash_data(string);
|
||||||
@@ -193,14 +197,17 @@ fn ui_box_t *ui_build_box_from_string(ui_code_loc_t loc, ui_box_flags_t flags, s
|
|||||||
if (ui->padding_stack && (axis == ui_axis2_x || axis == ui_axis2_y)) {
|
if (ui->padding_stack && (axis == ui_axis2_x || axis == ui_axis2_y)) {
|
||||||
string_size.e[axis] += ui_top_padding();
|
string_size.e[axis] += ui_top_padding();
|
||||||
}
|
}
|
||||||
r2f32_t rect = ui_next_rect(ui->lop_stack->value, &ui->top->rect, string_size);
|
if (box->flags.dont_compute_rect == false) {
|
||||||
ui_set_rect(box, rect);
|
r2f32_t rect = ui_next_rect(ui_top_lop(), &ui->top->rect, string_size);
|
||||||
|
ui_set_rect(box, rect, ui_top_lop());
|
||||||
|
}
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ui_boxf(...) ui__boxf(UILOC, __VA_ARGS__)
|
#define ui_boxf(...) ui__boxf(UILOC, __VA_ARGS__)
|
||||||
fn ui_box_t *ui__boxf(ui_code_loc_t loc, ui_box_flags_t flags, char *str, ...) {
|
fn ui_box_t *ui__boxf(ui_code_loc_t loc, ui_box_flags_t flags, char *str, ...) {
|
||||||
S8_FMT(tcx.temp, str, string);
|
S8_FMT(tcx.temp, str, string);
|
||||||
|
flags.dont_compute_rect = true;
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, flags, string);
|
ui_box_t *box = ui_build_box_from_string(loc, flags, string);
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
@@ -221,6 +228,7 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) {
|
|||||||
|
|
||||||
if (ui_is_active_box(box)) {
|
if (ui_is_active_box(box)) {
|
||||||
result.dragging = true;
|
result.dragging = true;
|
||||||
|
result.drag = ui->event->mouse_delta;
|
||||||
if (ev_left_up(ev)) {
|
if (ev_left_up(ev)) {
|
||||||
if (ui_is_hot_box(box)) {
|
if (ui_is_hot_box(box)) {
|
||||||
result.clicked = true;
|
result.clicked = true;
|
||||||
@@ -230,7 +238,25 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) {
|
|||||||
}
|
}
|
||||||
} else if (ui_is_hot_box(box) && ev_left_down(ev)) {
|
} else if (ui_is_hot_box(box) && ev_left_down(ev)) {
|
||||||
ui->active = box->id;
|
ui->active = box->id;
|
||||||
ui->focus = box->id;
|
if (box->flags.keyboard_nav) {
|
||||||
|
ui->focus = box->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ui_is_focused_box(box)) {
|
||||||
|
if (ev->kind == app_event_kind_key_down && ev->key == app_key_left) {
|
||||||
|
result.drag.x -= 1;
|
||||||
|
result.dragging = true;
|
||||||
|
result.clicked = true;
|
||||||
|
} else if (ev->kind == app_event_kind_key_down && ev->key == app_key_right) {
|
||||||
|
result.drag.x += 1;
|
||||||
|
result.dragging = true;
|
||||||
|
result.clicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->kind == app_event_kind_key_down && ev->key == app_key_enter) {
|
||||||
|
result.clicked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inside) {
|
if (inside) {
|
||||||
@@ -243,7 +269,14 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn void ui_text_input_draw(ui_box_t *box) {
|
fn void ui_text_input_draw(ui_box_t *box) {
|
||||||
r2f32_t rect = box->final_rect;
|
r2f32_t rect = box->full_rect;
|
||||||
|
f32 appear_t = f32_ease_out_n(f32_clamp01(box->appear_t*8), 10);
|
||||||
|
|
||||||
|
if (!ui_id_is_null(box->id)) {
|
||||||
|
v2f32_t size = v2f32_divs(r2f32_get_size(rect), 2);
|
||||||
|
r2f32_t smaller_rect = r2f32_shrink(rect, size);
|
||||||
|
rect = r2f32_lerp(smaller_rect, rect, appear_t);
|
||||||
|
}
|
||||||
|
|
||||||
v4f32_t background_color = box->background_color;
|
v4f32_t background_color = box->background_color;
|
||||||
v4f32_t text_color = box->text_color;
|
v4f32_t text_color = box->text_color;
|
||||||
@@ -266,7 +299,7 @@ fn void ui_text_input_draw(ui_box_t *box) {
|
|||||||
rn_draw_rect(rect, background_color);
|
rn_draw_rect(rect, background_color);
|
||||||
rn_draw_rect_border(rect, border_color, box->border_thickness);
|
rn_draw_rect_border(rect, border_color, box->border_thickness);
|
||||||
|
|
||||||
ui_text_input_t *ti = &box->text_input;
|
ui_text_input_t *ti = box->text_input;
|
||||||
s8_t string = s8(ti->str, ti->len);
|
s8_t string = s8(ti->str, ti->len);
|
||||||
v2f32_t pos = ui_aligned_text_pos(box->text_align, rect, string);
|
v2f32_t pos = ui_aligned_text_pos(box->text_align, rect, string);
|
||||||
rn_draw_string(rn_state.main_font, pos, text_color, string);
|
rn_draw_string(rn_state.main_font, pos, text_color, string);
|
||||||
@@ -302,7 +335,7 @@ fn i32 ui_text_replace(ui_text_input_t *ti, r1i32_t range, s8_t string) {
|
|||||||
assert(change_size >= 0);
|
assert(change_size >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *begin_remove = ti->str + range.min;
|
u8 *begin_remove = (u8 *)ti->str + range.min;
|
||||||
u8 *end_remove = begin_remove + size_to_remove;
|
u8 *end_remove = begin_remove + size_to_remove;
|
||||||
i32 remain_len = (i32)ti->len - (range.min + size_to_remove);
|
i32 remain_len = (i32)ti->len - (range.min + size_to_remove);
|
||||||
|
|
||||||
@@ -329,13 +362,11 @@ fn_test void ui_test_text_replace(void) {
|
|||||||
assert(s8_are_equal(ti.string, s8_lit("qaer")));
|
assert(s8_are_equal(ti.string, s8_lit("qaer")));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_signal_t ui_text_input(ui_code_loc_t loc, char *buffer, i32 buffer_size) {
|
fn ui_signal_t ui_text_input(ui_code_loc_t loc, ui_text_input_t *ti) {
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true }, s8_lit("text_input"));
|
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true, .keyboard_nav = true }, s8_lit("text_input"));
|
||||||
|
box->text_input = ti;
|
||||||
box->custom_draw = ui_text_input_draw;
|
box->custom_draw = ui_text_input_draw;
|
||||||
|
|
||||||
ui_text_input_t *ti = &box->text_input;
|
|
||||||
ti->str = buffer;
|
|
||||||
ti->cap = buffer_size;
|
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
if (ui_is_focused_box(box)) {
|
if (ui_is_focused_box(box)) {
|
||||||
app_event_t *ev = ui->event;
|
app_event_t *ev = ui->event;
|
||||||
@@ -392,7 +423,7 @@ fn ui_signal_t ui_text_input(ui_code_loc_t loc, char *buffer, i32 buffer_size) {
|
|||||||
#define ui_button(...) ui__button(UILOC, __VA_ARGS__)
|
#define ui_button(...) ui__button(UILOC, __VA_ARGS__)
|
||||||
fn ui_signal_t ui__button(ui_code_loc_t loc, char *str, ...) {
|
fn ui_signal_t ui__button(ui_code_loc_t loc, char *str, ...) {
|
||||||
S8_FMT(tcx.temp, str, string);
|
S8_FMT(tcx.temp, str, string);
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true }, string);
|
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true, .keyboard_nav = true }, string);
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
@@ -400,7 +431,7 @@ fn ui_signal_t ui__button(ui_code_loc_t loc, char *str, ...) {
|
|||||||
#define ui_radio_button(...) ui__radio_button(UILOC, __VA_ARGS__)
|
#define ui_radio_button(...) ui__radio_button(UILOC, __VA_ARGS__)
|
||||||
fn ui_signal_t ui__radio_button(ui_code_loc_t loc, i32 *value, i32 value_clicked, char *str, ...) {
|
fn ui_signal_t ui__radio_button(ui_code_loc_t loc, i32 *value, i32 value_clicked, char *str, ...) {
|
||||||
S8_FMT(tcx.temp, str, string);
|
S8_FMT(tcx.temp, str, string);
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true }, string);
|
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true, .keyboard_nav = true }, string);
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
if (signal.clicked) *value = value_clicked;
|
if (signal.clicked) *value = value_clicked;
|
||||||
// @todo?
|
// @todo?
|
||||||
@@ -411,7 +442,7 @@ fn ui_signal_t ui__radio_button(ui_code_loc_t loc, i32 *value, i32 value_clicked
|
|||||||
#define ui_label_button(...) ui__label_button(UILOC, __VA_ARGS__)
|
#define ui_label_button(...) ui__label_button(UILOC, __VA_ARGS__)
|
||||||
fn ui_signal_t ui__label_button(ui_code_loc_t loc, char *str, ...) {
|
fn ui_signal_t ui__label_button(ui_code_loc_t loc, char *str, ...) {
|
||||||
S8_FMT(tcx.temp, str, string);
|
S8_FMT(tcx.temp, str, string);
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_text = true }, string);
|
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_text = true, .keyboard_nav = true }, string);
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
@@ -427,7 +458,7 @@ fn ui_box_t *ui__label(ui_code_loc_t loc, char *str, ...) {
|
|||||||
#define ui_begin_expander(...) ui__begin_expander(UILOC, __VA_ARGS__)
|
#define ui_begin_expander(...) ui__begin_expander(UILOC, __VA_ARGS__)
|
||||||
fn ui_signal_t ui__begin_expander(ui_code_loc_t loc, char *str, ...) {
|
fn ui_signal_t ui__begin_expander(ui_code_loc_t loc, char *str, ...) {
|
||||||
S8_FMT(tcx.temp, str, string);
|
S8_FMT(tcx.temp, str, string);
|
||||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_text = true }, string);
|
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_text = true, .keyboard_nav = true }, string);
|
||||||
if (box->created_new) box->expanded = true;
|
if (box->created_new) box->expanded = true;
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
if (signal.clicked) box->expanded = !box->expanded;
|
if (signal.clicked) box->expanded = !box->expanded;
|
||||||
@@ -466,9 +497,83 @@ fn void ui_begin_build(ui_code_loc_t loc, app_event_t *ev, r2f32_t window_rect)
|
|||||||
ui->root.loc = loc;
|
ui->root.loc = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void ui_end_build(void) {
|
fn ui_box_t *ui_get_prev_box(ui_box_t *box, b32 (*match)(ui_box_t *)) {
|
||||||
assert(ui->top == &ui->root);
|
for (ui_box_t *it = box; it;) {
|
||||||
|
if (it->last) {
|
||||||
|
it = it->last;
|
||||||
|
if (match(it)) return it;
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
if (it->prev) {
|
||||||
|
it = it->prev;
|
||||||
|
if (match(it)) return it;
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = it->parent;
|
||||||
|
if (it) it = it->prev;
|
||||||
|
}
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ui_box_t *ui_get_next_box(ui_box_t *box, b32 (*match)(ui_box_t *)) {
|
||||||
|
for (ui_box_t *it = box; it;) {
|
||||||
|
if (it->first) {
|
||||||
|
it = it->first;
|
||||||
|
if (match(it)) return it;
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
if (it->next) {
|
||||||
|
it = it->next;
|
||||||
|
if (match(it)) return it;
|
||||||
|
else continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = it->parent;
|
||||||
|
if (it) it = it->next;
|
||||||
|
}
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b32 ui_match_axis(ui_box_t *box, ui_axis2_t axis) {
|
||||||
|
ui_axis2_t box_axis = ui_axis_from_lop(box->lop);
|
||||||
|
b32 result = box_axis == axis;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b32 ui_match_keynav(ui_box_t *box) {
|
||||||
|
b32 result = box->flags.keyboard_nav;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b32 ui_match_keynav_xaxis(ui_box_t *box) {
|
||||||
|
b32 result = box->flags.keyboard_nav && ui_match_axis(box, ui_axis2_x);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ui_box_t *ui_get_right_box(ui_box_t *box) { return ui_get_next_box(box, ui_match_keynav_xaxis); }
|
||||||
|
fn ui_box_t *ui_get_left_box(ui_box_t *box) { return ui_get_prev_box(box, ui_match_keynav_xaxis); }
|
||||||
|
|
||||||
|
fn void ui_end_build(void) {
|
||||||
|
{
|
||||||
|
app_event_t *ev = ui->event;
|
||||||
|
ui_box_t *focus_box = ui_find_box(ui->focus);
|
||||||
|
if (focus_box == NULL) {
|
||||||
|
ui->focus = ui_get_next_box(&ui->root, ui_match_keynav)->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->kind == app_event_kind_key_down && ev->key == app_key_up) {
|
||||||
|
ui->focus = ui_get_prev_box(focus_box, ui_match_keynav)->id;
|
||||||
|
} else if (ev->kind == app_event_kind_key_down && ev->key == app_key_down) {
|
||||||
|
ui->focus = ui_get_next_box(focus_box, ui_match_keynav)->id;
|
||||||
|
} else if (ev->kind == app_event_kind_key_down && ev->key == app_key_right) {
|
||||||
|
// ui->focus = ui_get_right_box(focus_box)->id;
|
||||||
|
} else if (ev->kind == app_event_kind_key_down && ev->key == app_key_left) {
|
||||||
|
// ui->focus = ui_get_left_box(focus_box)->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ui->top == &ui->root);
|
||||||
ui_pop_init_values();
|
ui_pop_init_values();
|
||||||
ui_assert_stacks_are_null();
|
ui_assert_stacks_are_null();
|
||||||
|
|
||||||
@@ -497,7 +602,14 @@ fn v2f32_t ui_aligned_text_pos(ui_text_align_t text_align, r2f32_t rect, s8_t st
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn void ui_default_draw_box(ui_box_t *box) {
|
fn void ui_default_draw_box(ui_box_t *box) {
|
||||||
r2f32_t rect = box->final_rect;
|
r2f32_t rect = box->full_rect;
|
||||||
|
f32 appear_t = f32_ease_out_n(f32_clamp01(box->appear_t*8), 10);
|
||||||
|
|
||||||
|
if (!ui_id_is_null(box->id)) {
|
||||||
|
v2f32_t size = v2f32_divs(r2f32_get_size(rect), 2);
|
||||||
|
r2f32_t smaller_rect = r2f32_shrink(rect, size);
|
||||||
|
rect = r2f32_lerp(smaller_rect, rect, appear_t);
|
||||||
|
}
|
||||||
|
|
||||||
v4f32_t background_color = box->background_color;
|
v4f32_t background_color = box->background_color;
|
||||||
v4f32_t text_color = box->text_color;
|
v4f32_t text_color = box->text_color;
|
||||||
@@ -566,6 +678,7 @@ fn void ui_begin_frame(app_frame_t *frame) {
|
|||||||
fn void ui_end_frame(void) {
|
fn void ui_end_frame(void) {
|
||||||
for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) {
|
for (ui_box_t *box = ui->hash_first, *next = NULL; box; box = next) {
|
||||||
next = box->hash_next;
|
next = box->hash_next;
|
||||||
|
box->appear_t += (f32)ui->frame->delta;
|
||||||
if (ui_is_hot_box(box)) {
|
if (ui_is_hot_box(box)) {
|
||||||
box->hot_t += (f32)ui->frame->delta;
|
box->hot_t += (f32)ui->frame->delta;
|
||||||
} else {
|
} else {
|
||||||
@@ -591,141 +704,145 @@ fn void ui_serial_subtype(void *p, type_t *type, s8_t name) {
|
|||||||
switch(type->kind) {
|
switch(type->kind) {
|
||||||
case type_kind_i8: {
|
case type_kind_i8: {
|
||||||
i8 *n = (i8 *)p;
|
i8 *n = (i8 *)p;
|
||||||
if (ui_label_button("%S: %d##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %d##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (i8)delta;
|
n[0] += (i8)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_i16: {
|
case type_kind_i16: {
|
||||||
i16 *n = (i16 *)p;
|
i16 *n = (i16 *)p;
|
||||||
if (ui_label_button("%S: %d##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %d##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (i16)delta;
|
n[0] += (i16)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_i32: {
|
case type_kind_i32: {
|
||||||
i32 *n = (i32 *)p;
|
i32 *n = (i32 *)p;
|
||||||
if (ui_label_button("%S: %d##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %d##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (i32)delta;
|
n[0] += (i32)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_i64: {
|
case type_kind_i64: {
|
||||||
i64 *n = (i64 *)p;
|
i64 *n = (i64 *)p;
|
||||||
if (ui_label_button("%S: %lld##slider%S", name, (long long)*n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %lld##slider%S", name, (long long)*n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (i64)delta;
|
n[0] += (i64)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_u8: {
|
case type_kind_u8: {
|
||||||
u8 *n = (u8 *)p;
|
u8 *n = (u8 *)p;
|
||||||
if (ui_label_button("%S: %u##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %u##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (u8)delta;
|
n[0] += (u8)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_u16: {
|
case type_kind_u16: {
|
||||||
u16 *n = (u16 *)p;
|
u16 *n = (u16 *)p;
|
||||||
if (ui_label_button("%S: %u##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %u##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (u16)delta;
|
n[0] += (u16)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_u32: {
|
case type_kind_u32: {
|
||||||
u32 *n = (u32 *)p;
|
u32 *n = (u32 *)p;
|
||||||
if (ui_label_button("%S: %u##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %u##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (u32)delta;
|
n[0] += (u32)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_u64: {
|
case type_kind_u64: {
|
||||||
u64 *n = (u64 *)p;
|
u64 *n = (u64 *)p;
|
||||||
if (ui_label_button("%S: %llu##slider%S", name, (unsigned long long)*n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %llu##slider%S", name, (unsigned long long)*n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (u64)delta;
|
n[0] += (u64)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_b8: {
|
case type_kind_b8: {
|
||||||
b8 *n = (b8 *)p;
|
b8 *n = (b8 *)p;
|
||||||
if (ui_label_button("%S: %s", name, *n ? "true" : "false").clicked) {
|
ui_signal_t sig = ui_label_button("%S: %s##button%S", name, *n ? "true" : "false", name);
|
||||||
|
if (sig.clicked) {
|
||||||
*n = !*n;
|
*n = !*n;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_b16: {
|
case type_kind_b16: {
|
||||||
b16 *n = (b16 *)p;
|
b16 *n = (b16 *)p;
|
||||||
if (ui_label_button("%S: %s", name, *n ? "true" : "false").clicked) {
|
ui_signal_t sig = ui_label_button("%S: %s##button%S", name, *n ? "true" : "false");
|
||||||
|
if (sig.clicked) {
|
||||||
*n = !*n;
|
*n = !*n;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_b32: {
|
case type_kind_b32: {
|
||||||
b32 *n = (b32 *)p;
|
b32 *n = (b32 *)p;
|
||||||
if (ui_label_button("%S: %s", name, *n ? "true" : "false").clicked) {
|
ui_signal_t sig = ui_label_button("%S: %s##button%S", name, *n ? "true" : "false");
|
||||||
|
if (sig.clicked) {
|
||||||
*n = !*n;
|
*n = !*n;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_b64: {
|
case type_kind_b64: {
|
||||||
b64 *n = (b64 *)p;
|
b64 *n = (b64 *)p;
|
||||||
if (ui_label_button("%S: %s", name, *n ? "true" : "false").clicked) {
|
ui_signal_t sig = ui_label_button("%S: %s##button%S", name, *n ? "true" : "false");
|
||||||
|
if (sig.clicked) {
|
||||||
*n = !*n;
|
*n = !*n;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_f32: {
|
case type_kind_f32: {
|
||||||
f32 *n = (f32 *)p;
|
f32 *n = (f32 *)p;
|
||||||
if (ui_label_button("%S: %f##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %f##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += delta;
|
n[0] += sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_f64: {
|
case type_kind_f64: {
|
||||||
f64 *n = (f64 *)p;
|
f64 *n = (f64 *)p;
|
||||||
if (ui_label_button("%S: %f##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %f##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += delta;
|
n[0] += sig.drag.x;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_isize: {
|
case type_kind_isize: {
|
||||||
isize *n = (isize *)p;
|
isize *n = (isize *)p;
|
||||||
if (ui_label_button("%S: %lld##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %lld##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (isize)delta;
|
n[0] += (isize)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;;
|
return;;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_usize: {
|
case type_kind_usize: {
|
||||||
usize *n = (usize *)p;
|
usize *n = (usize *)p;
|
||||||
if (ui_label_button("%S: %llu##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %llu##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (usize)delta;
|
n[0] += (usize)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;;
|
return;;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_int: {
|
case type_kind_int: {
|
||||||
int *n = (int *)p;
|
int *n = (int *)p;
|
||||||
if (ui_label_button("%S: %d##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %d##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (int)delta;
|
n[0] += (int)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;;
|
return;;
|
||||||
} break;
|
} break;
|
||||||
case type_kind_char: {
|
case type_kind_char: {
|
||||||
char *n = (char *)p;
|
char *n = (char *)p;
|
||||||
if (ui_label_button("%S: %c##slider%S", name, *n, name).dragging) {
|
ui_signal_t sig = ui_label_button("%S: %c##slider%S", name, *n, name);
|
||||||
f32 delta = ui->event->mouse_delta.x;
|
if (sig.dragging) {
|
||||||
n[0] += (char)delta;
|
n[0] += (char)sig.drag.x;
|
||||||
}
|
}
|
||||||
return;;
|
return;;
|
||||||
} break;
|
} break;
|
||||||
@@ -739,7 +856,8 @@ fn void ui_serial_subtype(void *p, type_t *type, s8_t name) {
|
|||||||
if (type->kind == type_kind_enum) {
|
if (type->kind == type_kind_enum) {
|
||||||
i64 value = ti_enum_read_value(p, type);
|
i64 value = ti_enum_read_value(p, type);
|
||||||
s8_t string_value = ti_enum_value_to_name(value, type);
|
s8_t string_value = ti_enum_value_to_name(value, type);
|
||||||
if (ui_label_button("%S: %S = %S", name, type->name, string_value).clicked) {
|
ui_signal_t sig = ui_label_button("%S: %S = %S##button%S", name, type->name, string_value, name);
|
||||||
|
if (sig.clicked) {
|
||||||
i64 new_value = ti_enum_next_value(p, value, type);
|
i64 new_value = ti_enum_next_value(p, value, type);
|
||||||
ti_enum_write_value(p, new_value, type);
|
ti_enum_write_value(p, new_value, type);
|
||||||
}
|
}
|
||||||
@@ -791,7 +909,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co
|
|||||||
ui_begin_build(UILOC, ev, window_rect_from_frame(frame));
|
ui_begin_build(UILOC, ev, window_rect_from_frame(frame));
|
||||||
|
|
||||||
ui_box_t *top_box = ui_box0((ui_box_flags_t){.draw_rect = true, .clip_rect = true});
|
ui_box_t *top_box = ui_box0((ui_box_flags_t){.draw_rect = true, .clip_rect = true});
|
||||||
ui_set_rect(top_box, r2f32_cut_top(&ui->top->rect, ui_em(1.5f)));
|
ui_set_rect(top_box, r2f32_cut_top(&ui->top->rect, ui_em(1.5f)), ui_lop_cut_top);
|
||||||
|
|
||||||
ui_set_padding(ui_em(3))
|
ui_set_padding(ui_em(3))
|
||||||
ui_set_text_align(ui_text_align_center)
|
ui_set_text_align(ui_text_align_center)
|
||||||
@@ -805,18 +923,23 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co
|
|||||||
|
|
||||||
|
|
||||||
if (ui_g_panel == 1) {
|
if (ui_g_panel == 1) {
|
||||||
ui_box_t *scroller_box = ui_box0((ui_box_flags_t){.draw_rect = true, .clip_rect = true});
|
ui_box_t *scroller_box = ui_boxf((ui_box_flags_t){.draw_rect = true, .clip_rect = true}, "scrollbar");
|
||||||
ui_set_rect(scroller_box, r2f32_cut_right(&ui->top->rect, ui_em(0.5f)));
|
ui_set_rect(scroller_box, r2f32_cut_right(&ui->top->rect, ui_em(0.5f)), ui_lop_cut_right);
|
||||||
|
|
||||||
ui_box_t *item_box = ui_box0((ui_box_flags_t){.draw_rect = true, .clip_rect = true});
|
ui_box_t *item_box = ui_boxf((ui_box_flags_t){.draw_rect = true, .clip_rect = true}, "item_box");
|
||||||
ui_set_rect(item_box, r2f32_cut_left(&ui->top->rect, ui_max));
|
ui_set_rect(item_box, r2f32_cut_left(&ui->top->rect, ui_max), ui_lop_cut_left);
|
||||||
item_box->rect = r2f32_shrinks(item_box->rect, ui_em(1));
|
item_box->rect = r2f32_shrinks(item_box->rect, ui_em(1));
|
||||||
|
|
||||||
|
|
||||||
ui_set_text_align(ui_text_align_left)
|
ui_set_text_align(ui_text_align_left)
|
||||||
ui_set_top(item_box) {
|
ui_set_top(item_box) {
|
||||||
static char buff[128];
|
locl char buff[128];
|
||||||
ui_text_input(UILOC, buff, sizeof(buff));
|
locl ui_text_input_t text_input;
|
||||||
|
if (text_input.str == NULL) {
|
||||||
|
text_input.str = buff;
|
||||||
|
text_input.cap = lengthof(buff);
|
||||||
|
}
|
||||||
|
ui_text_input(UILOC, &text_input);
|
||||||
|
|
||||||
for (i32 i = 0; i < tweak_count; i += 1) {
|
for (i32 i = 0; i < tweak_count; i += 1) {
|
||||||
mt_tweak_t *tweak = tweak_table + i;
|
mt_tweak_t *tweak = tweak_table + i;
|
||||||
@@ -835,7 +958,7 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co
|
|||||||
if (signal.dragging) {
|
if (signal.dragging) {
|
||||||
f32 size = tweak->max - tweak->min;
|
f32 size = tweak->max - tweak->min;
|
||||||
v2f32_t string_size = rn_measure_string(rn_state.main_font, signal.box->string);
|
v2f32_t string_size = rn_measure_string(rn_state.main_font, signal.box->string);
|
||||||
f32 delta = (ui->event->mouse_delta.x / string_size.x) * size;
|
f32 delta = (signal.drag.x / string_size.x) * size;
|
||||||
*n = CLAMP(*n + delta, tweak->min, tweak->max);
|
*n = CLAMP(*n + delta, tweak->min, tweak->max);
|
||||||
}
|
}
|
||||||
} else_is_invalid;
|
} else_is_invalid;
|
||||||
@@ -858,10 +981,10 @@ fn void ui_demo_update(app_frame_t *frame, mt_tweak_t *tweak_table, i32 tweak_co
|
|||||||
|
|
||||||
r2f32_cut_top(&ui->top->rect, scroller_percent * scroller_box_size);
|
r2f32_cut_top(&ui->top->rect, scroller_percent * scroller_box_size);
|
||||||
ui_box_t *box = ui_build_box_from_id(UILOC, (ui_box_flags_t){.draw_border = true, .draw_rect = true}, ui_idf("slider"));
|
ui_box_t *box = ui_build_box_from_id(UILOC, (ui_box_flags_t){.draw_border = true, .draw_rect = true}, ui_idf("slider"));
|
||||||
ui_set_rect(box, r2f32_cut_top(&ui->top->rect, scroller_size * scroller_box_size));
|
ui_set_rect(box, r2f32_cut_top(&ui->top->rect, scroller_size * scroller_box_size), ui_lop_cut_top);
|
||||||
ui_signal_t signal = ui_signal_from_box(box);
|
ui_signal_t signal = ui_signal_from_box(box);
|
||||||
if (signal.dragging) {
|
if (signal.dragging) {
|
||||||
scroller_value += (ev->mouse_delta.y / item_box_size * 2) * (all_items_size);
|
scroller_value += (signal.drag.y / item_box_size * 2) * (all_items_size);
|
||||||
scroller_value = CLAMP(scroller_value, 0, all_items_size);
|
scroller_value = CLAMP(scroller_value, 0, all_items_size);
|
||||||
}
|
}
|
||||||
if (ev->kind == app_event_kind_mouse_wheel) {
|
if (ev->kind == app_event_kind_mouse_wheel) {
|
||||||
|
|||||||
21
src/ui/ui.h
21
src/ui/ui.h
@@ -1,5 +1,3 @@
|
|||||||
typedef void ui_custom_draw_t(struct ui_box_t *box);
|
|
||||||
|
|
||||||
typedef struct ui_code_loc_t ui_code_loc_t;
|
typedef struct ui_code_loc_t ui_code_loc_t;
|
||||||
struct ui_code_loc_t {
|
struct ui_code_loc_t {
|
||||||
char *file;
|
char *file;
|
||||||
@@ -17,8 +15,10 @@ struct ui_box_flags_t {
|
|||||||
b8 draw_rect: 1;
|
b8 draw_rect: 1;
|
||||||
b8 draw_border: 1;
|
b8 draw_border: 1;
|
||||||
b8 draw_text: 1;
|
b8 draw_text: 1;
|
||||||
|
b8 clip_rect: 1;
|
||||||
|
|
||||||
b8 clip_rect : 1;
|
b8 dont_compute_rect: 1;
|
||||||
|
b8 keyboard_nav: 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -64,6 +64,8 @@ struct ui_text_input_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ui_box_t ui_box_t;
|
typedef struct ui_box_t ui_box_t;
|
||||||
|
typedef void ui_custom_draw_t(ui_box_t *);
|
||||||
|
|
||||||
struct ui_box_t {
|
struct ui_box_t {
|
||||||
ui_box_t *next;
|
ui_box_t *next;
|
||||||
ui_box_t *prev;
|
ui_box_t *prev;
|
||||||
@@ -75,9 +77,10 @@ struct ui_box_t {
|
|||||||
ui_code_loc_t loc;
|
ui_code_loc_t loc;
|
||||||
s8_t string;
|
s8_t string;
|
||||||
|
|
||||||
ui_box_flags_t flags;
|
ui_box_flags_t flags;
|
||||||
b8 created_new;
|
b8 created_new;
|
||||||
ui_custom_draw_t *custom_draw;
|
ui_custom_draw_t *custom_draw;
|
||||||
|
ui_lop_t lop;
|
||||||
UI_DECL_BOX_MEMBERS
|
UI_DECL_BOX_MEMBERS
|
||||||
|
|
||||||
r2f32_t full_rect;
|
r2f32_t full_rect;
|
||||||
@@ -89,13 +92,14 @@ struct ui_box_t {
|
|||||||
ui_box_t *hash_prev;
|
ui_box_t *hash_prev;
|
||||||
u64 last_touched_event_id;
|
u64 last_touched_event_id;
|
||||||
|
|
||||||
|
f32 appear_t;
|
||||||
f32 hot_t;
|
f32 hot_t;
|
||||||
f32 active_t;
|
f32 active_t;
|
||||||
|
|
||||||
r2f32_t final_rect;
|
r2f32_t final_rect;
|
||||||
b32 expanded;
|
b32 expanded;
|
||||||
|
|
||||||
ui_text_input_t text_input;
|
ui_text_input_t *text_input;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ui_signal_t ui_signal_t;
|
typedef struct ui_signal_t ui_signal_t;
|
||||||
@@ -103,6 +107,7 @@ struct ui_signal_t {
|
|||||||
ui_box_t *box;
|
ui_box_t *box;
|
||||||
b8 clicked;
|
b8 clicked;
|
||||||
b8 dragging;
|
b8 dragging;
|
||||||
|
v2f32_t drag;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ui_t ui_t;
|
typedef struct ui_t ui_t;
|
||||||
@@ -132,7 +137,7 @@ struct ui_t {
|
|||||||
r2f32_t clip_rect;
|
r2f32_t clip_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
ui_t *ui;
|
gb ui_t *ui;
|
||||||
|
|
||||||
gb_read_only ui_id_t ui_null_id;
|
gb_read_only ui_id_t ui_null_id;
|
||||||
gb_read_only ui_box_t ui_null_box;
|
gb_read_only ui_box_t ui_null_box;
|
||||||
@@ -148,7 +153,7 @@ fn b32 ui_is_focused_box(ui_box_t *box) { return !ui_is_null_box(box) && box->id
|
|||||||
#define ev_left_up(ev) ((ev)->kind == app_event_kind_mouse_up && ev_left(ev))
|
#define ev_left_up(ev) ((ev)->kind == app_event_kind_mouse_up && ev_left(ev))
|
||||||
#define ev_left_down(ev) ((ev)->kind == app_event_kind_mouse_down && ev_left(ev))
|
#define ev_left_down(ev) ((ev)->kind == app_event_kind_mouse_down && ev_left(ev))
|
||||||
|
|
||||||
fn void ui_set_rect(ui_box_t *box, r2f32_t rect) { box->rect = box->full_rect = rect; }
|
fn void ui_set_rect(ui_box_t *box, r2f32_t rect, ui_lop_t lop) { box->rect = box->full_rect = rect; box->lop = lop; }
|
||||||
|
|
||||||
#define UILOC (ui_code_loc_t){.file = __FILE__, .line = __LINE__, .counter = __COUNTER__}
|
#define UILOC (ui_code_loc_t){.file = __FILE__, .line = __LINE__, .counter = __COUNTER__}
|
||||||
#define ui_em(x) ((x) * rn_state.main_font->size)
|
#define ui_em(x) ((x) * rn_state.main_font->size)
|
||||||
|
|||||||
6
todo.txt
6
todo.txt
@@ -22,17 +22,19 @@
|
|||||||
[ ] maybe copy package stuff to build?
|
[ ] maybe copy package stuff to build?
|
||||||
|
|
||||||
[ ] ui
|
[ ] ui
|
||||||
|
[ ] fix elements getting offset when font large and they are on the edge
|
||||||
[ ] text input
|
[ ] text input
|
||||||
|
[x] basic working
|
||||||
|
[ ] ctrl backspace, ctrl delete
|
||||||
|
[ ] set mouse cursor on hover
|
||||||
[ ] everything lister (with edits etc.)
|
[ ] everything lister (with edits etc.)
|
||||||
[ ] push pop flag
|
[ ] push pop flag
|
||||||
[ ] how to do colors?
|
[ ] how to do colors?
|
||||||
- css like based on ids and pre built palettes
|
- css like based on ids and pre built palettes
|
||||||
- fat box with stacks (now)
|
- fat box with stacks (now)
|
||||||
-
|
|
||||||
[ ] demo style, with different buttons and controls, headings
|
[ ] demo style, with different buttons and controls, headings
|
||||||
[x] palette idea, also push pop palette
|
[x] palette idea, also push pop palette
|
||||||
[x] replace padding with something more 'real'
|
[x] replace padding with something more 'real'
|
||||||
|
|
||||||
[ ] color picker
|
[ ] color picker
|
||||||
[ ] slider
|
[ ] slider
|
||||||
[ ] draw image in box ui
|
[ ] draw image in box ui
|
||||||
|
|||||||
Reference in New Issue
Block a user