fix: quick port to c3 0.8.2
This commit is contained in:
parent
f68327b027
commit
1584b04fd3
43
src/atlas.c3
43
src/atlas.c3
@ -4,9 +4,9 @@ import std::io;
|
|||||||
|
|
||||||
faultdef CANNOT_PLACE, INVALID_TYPE;
|
faultdef CANNOT_PLACE, INVALID_TYPE;
|
||||||
|
|
||||||
enum AtlasType {
|
enum AtlasType : (sz bpp, typeid underlying) {
|
||||||
ATLAS_GRAYSCALE,
|
ATLAS_GRAYSCALE {1, char},
|
||||||
ATLAS_R8G8B8A8,
|
ATLAS_R8G8B8A8 {4, uint},
|
||||||
}
|
}
|
||||||
|
|
||||||
// black and white atlas
|
// black and white atlas
|
||||||
@ -21,23 +21,6 @@ struct Atlas {
|
|||||||
ushort row_h;
|
ushort row_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bytes per pixel
|
|
||||||
macro usz AtlasType.bpp(type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ATLAS_GRAYSCALE: return 1;
|
|
||||||
case ATLAS_R8G8B8A8: return 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro typeid AtlasType.underlying(type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ATLAS_GRAYSCALE: return char;
|
|
||||||
case ATLAS_R8G8B8A8: return uint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// FIXME: in and out types are not always known at compile time
|
// FIXME: in and out types are not always known at compile time
|
||||||
macro @pixel_convert(p, AtlasType $in, AtlasType $out)
|
macro @pixel_convert(p, AtlasType $in, AtlasType $out)
|
||||||
@ -52,10 +35,10 @@ macro @pixel_convert(p, AtlasType $in, AtlasType $out)
|
|||||||
var b = ((p >> 16) & 0xff);
|
var b = ((p >> 16) & 0xff);
|
||||||
var a = ((p >> 24) & 0xff);
|
var a = ((p >> 24) & 0xff);
|
||||||
if (a == 0) return (char)0;
|
if (a == 0) return (char)0;
|
||||||
return (ATLAS_GRAYSCALE.underlying())(((float)r+g+b) / 3.0f);
|
return (ATLAS_GRAYSCALE.underlying)(((float)r+g+b) / 3.0f);
|
||||||
$case $in == ATLAS_GRAYSCALE && $out == ATLAS_R8G8B8A8:
|
$case $in == ATLAS_GRAYSCALE && $out == ATLAS_R8G8B8A8:
|
||||||
var x = (char)(p/3.0);
|
var x = (char)(p/3.0);
|
||||||
return (ATLAS_R8G8B8A8.underlying())(x|(x<<8)|(x<<16)|(255<<24));
|
return (ATLAS_R8G8B8A8.underlying)(x|(x<<8)|(x<<16)|(255<<24));
|
||||||
$default: $error "Unimplemented pixel format conversion";
|
$default: $error "Unimplemented pixel format conversion";
|
||||||
$endswitch
|
$endswitch
|
||||||
$endif
|
$endif
|
||||||
@ -69,7 +52,7 @@ fn void? Atlas.new(&atlas, Id id, AtlasType type, ushort width, ushort height)
|
|||||||
atlas.width = width;
|
atlas.width = width;
|
||||||
atlas.height = height;
|
atlas.height = height;
|
||||||
|
|
||||||
atlas.buffer = mem::new_array(char, (usz)atlas.width*atlas.height*type.bpp());
|
atlas.buffer = mem::new_array(char, (sz)atlas.width*atlas.height*type.bpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void Atlas.free(&atlas)
|
fn void Atlas.free(&atlas)
|
||||||
@ -103,7 +86,7 @@ fn Point? Atlas.place(&atlas, char[] pixels, ushort w, ushort h, ushort stride)
|
|||||||
p = atlas.row;
|
p = atlas.row;
|
||||||
} else {
|
} else {
|
||||||
atlas.row.x = 0;
|
atlas.row.x = 0;
|
||||||
atlas.row.y = atlas.row.y + atlas.row_h;
|
atlas.row.y = (short)atlas.row.y + (short)atlas.row_h;
|
||||||
atlas.row_h = 0;
|
atlas.row_h = 0;
|
||||||
if (atlas.row.x + w <= atlas.width && atlas.row.y + h <= atlas.height) {
|
if (atlas.row.x + w <= atlas.width && atlas.row.y + h <= atlas.height) {
|
||||||
p = atlas.row;
|
p = atlas.row;
|
||||||
@ -112,17 +95,17 @@ fn Point? Atlas.place(&atlas, char[] pixels, ushort w, ushort h, ushort stride)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usz bpp = atlas.type.bpp();
|
sz bpp = atlas.type.bpp;
|
||||||
for (usz y = 0; y < h; y++) {
|
for (sz y = 0; y < h; y++) {
|
||||||
for (usz x = 0; x < w; x++) {
|
for (sz x = 0; x < w; x++) {
|
||||||
char[] buf = atlas.buffer[(usz)(p.y+y)*atlas.width*bpp + (p.x+x)*bpp ..];
|
char[] buf = atlas.buffer[(sz)(p.y+y)*atlas.width*bpp + (p.x+x)*bpp ..];
|
||||||
char[] pix = pixels[(usz)y*stride*bpp + x*bpp ..];
|
char[] pix = pixels[(sz)y*stride*bpp + x*bpp ..];
|
||||||
|
|
||||||
buf[0..bpp-1] = pix[0..bpp-1];
|
buf[0..bpp-1] = pix[0..bpp-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atlas.row.x += w;
|
atlas.row.x += (short)w;
|
||||||
if (h > atlas.row_h) {
|
if (h > atlas.row_h) {
|
||||||
atlas.row_h = h;
|
atlas.row_h = h;
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/cache.c3
20
src/cache.c3
@ -10,13 +10,13 @@ module cache<Key, Value, SIZE>;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import std::core::mem;
|
import std::core::mem;
|
||||||
import std::core::mem::allocator;
|
import std::core::mem::alloc;
|
||||||
import std::collections::bitset;
|
import std::collections::bitset;
|
||||||
import std::collections::map;
|
import std::collections::map;
|
||||||
|
|
||||||
alias BitArr = bitset::BitSet{SIZE};
|
alias BitArr = bitset::BitSet{SIZE};
|
||||||
alias IdTable = map::HashMap{Key, usz};
|
alias IdTable = map::HashMap{Key, sz};
|
||||||
alias IdTableEntry = map::Entry{Key, usz};
|
alias IdTableEntry = map::Entry{Key, sz};
|
||||||
|
|
||||||
const usz CACHE_NCYCLES = (usz)(SIZE * 2.0/3.0);
|
const usz CACHE_NCYCLES = (usz)(SIZE * 2.0/3.0);
|
||||||
|
|
||||||
@ -47,13 +47,13 @@ fn void? Cache.init(&cache, Allocator allocator)
|
|||||||
// FIXME: this shit is SLOW
|
// FIXME: this shit is SLOW
|
||||||
foreach (idx, bit : cache.used) { cache.used[idx] = false; }
|
foreach (idx, bit : cache.used) { cache.used[idx] = false; }
|
||||||
foreach (idx, bit : cache.present) { cache.present[idx] = false; }
|
foreach (idx, bit : cache.present) { cache.present[idx] = false; }
|
||||||
cache.pool = allocator::new_array(allocator, Value, SIZE);
|
cache.pool = alloc::new_array(allocator, Value, SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void Cache.free(&cache)
|
fn void Cache.free(&cache)
|
||||||
{
|
{
|
||||||
(void)cache.table.free();
|
(void)cache.table.free();
|
||||||
(void)allocator::free(cache.allocator, cache.pool);
|
(void)alloc::free(cache.allocator, cache.pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Value*? Cache.search(&cache, Key id)
|
fn Value*? Cache.search(&cache, Key id)
|
||||||
@ -94,12 +94,12 @@ fn void Cache.remove(&cache, Key id)
|
|||||||
|
|
||||||
/* Look for a free spot in the present bitmap and return its index */
|
/* Look for a free spot in the present bitmap and return its index */
|
||||||
/* If there is no free space left then just return the first position */
|
/* If there is no free space left then just return the first position */
|
||||||
fn usz Cache.get_free_spot(&cache)
|
fn sz Cache.get_free_spot(&cache)
|
||||||
{
|
{
|
||||||
const BITS = @bitsizeof(cache.present.data[0]);
|
const BITS = @bitsizeof(cache.present.data[0]);
|
||||||
foreach (idx, d: cache.present.data) {
|
foreach (idx, d: cache.present.data) {
|
||||||
if (d != $typeof(d).max) {
|
if (d != $Typeof(d)::max) {
|
||||||
usz spot = idx*BITS + BITS-d.clz();
|
sz spot = idx*BITS + BITS-d.clz();
|
||||||
if (cache.used[spot]) unreachable("free spot is not actually free: %d", spot);
|
if (cache.used[spot]) unreachable("free spot is not actually free: %d", spot);
|
||||||
return spot;
|
return spot;
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ fn usz Cache.get_free_spot(&cache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
<* @require g != null *>
|
<* @require g != null *>
|
||||||
fn Value*? Cache.insert_at(&cache, Value* g, Key id, usz index)
|
fn Value*? Cache.insert_at(&cache, Value* g, Key id, sz index)
|
||||||
{
|
{
|
||||||
Value* spot;
|
Value* spot;
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ fn Value*? Cache.insert_at(&cache, Value* g, Key id, usz index)
|
|||||||
<* @require g != null *>
|
<* @require g != null *>
|
||||||
fn Value*? Cache.insert_new(&cache, Value* g, Key id)
|
fn Value*? Cache.insert_new(&cache, Value* g, Key id)
|
||||||
{
|
{
|
||||||
usz index = cache.get_free_spot();
|
sz index = cache.get_free_spot();
|
||||||
return cache.insert_at(g, id, index);
|
return cache.insert_at(g, id, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
src/cmd.c3
24
src/cmd.c3
@ -70,9 +70,9 @@ fn int Cmd.compare_to(Cmd a, Cmd b)
|
|||||||
fn void? CmdQueue.sort(&queue)
|
fn void? CmdQueue.sort(&queue)
|
||||||
{
|
{
|
||||||
CmdQueue stack;
|
CmdQueue stack;
|
||||||
stack.init(allocator::tmem);
|
stack.init(tmem);
|
||||||
|
|
||||||
for (isz i = queue.len()-1; i > 0; i--) {
|
for (sz i = queue.len()-1; i > 0; i--) {
|
||||||
Cmd cur = (*queue)[i];
|
Cmd cur = (*queue)[i];
|
||||||
Cmd next = (*queue)[i - 1];
|
Cmd next = (*queue)[i - 1];
|
||||||
// cur < next
|
// cur < next
|
||||||
@ -82,17 +82,17 @@ fn void? CmdQueue.sort(&queue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usz l = stack.len();
|
sz l = stack.len();
|
||||||
for (usz i; i < l; i++) {
|
for (sz i; i < l; i++) {
|
||||||
queue.push(stack.pop())!;
|
queue.push(stack.pop())!;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// implement the Printable interface
|
// implement the Printable interface
|
||||||
fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
fn sz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
||||||
{
|
{
|
||||||
usz ret;
|
sz ret;
|
||||||
|
|
||||||
ret += f.printf("Cmd{ type: %s, z_index: %d, ", cmd.type, cmd.z_index)!;
|
ret += f.printf("Cmd{ type: %s, z_index: %d, ", cmd.type, cmd.z_index)!;
|
||||||
switch (cmd.type) {
|
switch (cmd.type) {
|
||||||
@ -116,7 +116,7 @@ fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro bool cull_rect(Rect rect, Rect clip = {0,0,short.max,short.max})
|
macro bool cull_rect(Rect rect, Rect clip = {0,0,short::max,short::max})
|
||||||
{
|
{
|
||||||
bool no_area = rect.w <= 0 || rect.h <= 0;
|
bool no_area = rect.w <= 0 || rect.h <= 0;
|
||||||
return no_area || !rect.collides(clip);
|
return no_area || !rect.collides(clip);
|
||||||
@ -164,7 +164,7 @@ fn void? Ctx.push_rect(&ctx, Rect rect, int z_index, Style* style)
|
|||||||
.type = CMD_RECT,
|
.type = CMD_RECT,
|
||||||
.rect.rect = rect,
|
.rect.rect = rect,
|
||||||
.rect.color = border_color,
|
.rect.color = border_color,
|
||||||
.rect.radius = radius + border.x,
|
.rect.radius = radius + (ushort)border.x,
|
||||||
};
|
};
|
||||||
ctx.push_cmd(cmd, z_index);
|
ctx.push_cmd(cmd, z_index);
|
||||||
}
|
}
|
||||||
@ -204,13 +204,13 @@ fn void? Ctx.push_update_atlas(&ctx, Atlas* atlas)
|
|||||||
.update_atlas = {
|
.update_atlas = {
|
||||||
.id = atlas.id,
|
.id = atlas.id,
|
||||||
.raw_buffer = atlas.buffer,
|
.raw_buffer = atlas.buffer,
|
||||||
.width = atlas.width,
|
.width = (short)atlas.width,
|
||||||
.height = atlas.height,
|
.height = (short)atlas.height,
|
||||||
.bpp = (ushort)atlas.type.bpp(),
|
.bpp = (short)atlas.type.bpp,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// update the atlases before everything else
|
// update the atlases before everything else
|
||||||
ctx.push_cmd(up, -1);
|
ctx.push_cmd(up, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro Ctx.dbg_rect(&ctx, Rect r, uint c = 0xff000042u) => ctx.push_rect(r, int.max, &&(Style){.bg=c.to_rgba()})!!;
|
macro Ctx.dbg_rect(&ctx, Rect r, uint c = 0xff000042u) => ctx.push_rect(r, int::max, &&(Style){.bg=c.to_rgba()})!!;
|
||||||
|
|||||||
18
src/core.c3
18
src/core.c3
@ -105,7 +105,7 @@ struct InputData {
|
|||||||
}
|
}
|
||||||
struct keyboard {
|
struct keyboard {
|
||||||
char[TEXT_MAX] text;
|
char[TEXT_MAX] text;
|
||||||
usz text_len;
|
sz text_len;
|
||||||
ModKeys modkeys;
|
ModKeys modkeys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ fn Elem*? Ctx.get_parent(&ctx)
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro @bits(#a) => $typeof(#a).sizeof*8;
|
macro @bits(#a) => $Typeof(#a)::size*8;
|
||||||
macro Id.rotate_left(id, uint $n) => (id << $n) | (id >> (@bits(id) - $n));
|
macro Id.rotate_left(id, uint $n) => (id << $n) | (id >> (@bits(id) - $n));
|
||||||
const uint GOLDEN_RATIO = 0x9E3779B9;
|
const uint GOLDEN_RATIO = 0x9E3779B9;
|
||||||
|
|
||||||
@ -161,8 +161,8 @@ fn Id? Ctx.gen_id(&ctx, Id id2)
|
|||||||
macro Id @compute_id(...)
|
macro Id @compute_id(...)
|
||||||
{
|
{
|
||||||
Id id = (Id)$$LINE.hash() ^ (Id)@str_hash($$FILE);
|
Id id = (Id)$$LINE.hash() ^ (Id)@str_hash($$FILE);
|
||||||
$for var $i = 0; $i < $vacount; $i++:
|
$for var $i = 0; $i < $vaarg.len; $i++:
|
||||||
id ^= (Id)$vaexpr[$i].hash();
|
id ^= (Id)$vaarg[$i].hash();
|
||||||
$endfor
|
$endfor
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ fn void? Ctx.init(&ctx, Allocator allocator)
|
|||||||
ctx.cache.init(allocator)!;
|
ctx.cache.init(allocator)!;
|
||||||
defer catch { (void)ctx.cache.free(); }
|
defer catch { (void)ctx.cache.free(); }
|
||||||
|
|
||||||
ctx.cmd_queue.init(allocator::mem, MAX_COMMANDS);
|
ctx.cmd_queue.init(mem, MAX_COMMANDS);
|
||||||
defer catch { (void)ctx.cmd_queue.free(); }
|
defer catch { (void)ctx.cmd_queue.free(); }
|
||||||
|
|
||||||
ctx.styles.init(allocator);
|
ctx.styles.init(allocator);
|
||||||
@ -254,14 +254,14 @@ fn void? Ctx.frame_begin(&ctx)
|
|||||||
// other stuff
|
// other stuff
|
||||||
//elem.flags.has_focus = ctx.has_focus;
|
//elem.flags.has_focus = ctx.has_focus;
|
||||||
|
|
||||||
elem.bounds = {0, 0, ctx.width, ctx.height};
|
elem.bounds = {0, 0, (short)ctx.width, (short)ctx.height};
|
||||||
elem.z_index = 0;
|
elem.z_index = 0;
|
||||||
elem.div.scroll_x.enabled = false;
|
elem.div.scroll_x.enabled = false;
|
||||||
elem.div.scroll_y.enabled = false;
|
elem.div.scroll_y.enabled = false;
|
||||||
elem.layout.dir = ROW;
|
elem.layout.dir = ROW;
|
||||||
elem.layout.anchor = TOP_LEFT;
|
elem.layout.anchor = TOP_LEFT;
|
||||||
elem.layout.w = @exact(ctx.width);
|
elem.layout.w = @exact((short)ctx.width);
|
||||||
elem.layout.h = @exact(ctx.height);
|
elem.layout.h = @exact((short)ctx.height);
|
||||||
|
|
||||||
ctx.div_scissor = elem.bounds;
|
ctx.div_scissor = elem.bounds;
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ $if $feature(DEBUG_POINTER):
|
|||||||
// draw mouse position
|
// draw mouse position
|
||||||
Cmd cmd = {
|
Cmd cmd = {
|
||||||
.type = CMD_RECT,
|
.type = CMD_RECT,
|
||||||
.z_index = int.max-1, // hopefully over everything else
|
.z_index = int::max-1, // hopefully over everything else
|
||||||
.rect.rect = {
|
.rect.rect = {
|
||||||
.x = ctx.input.mouse.pos.x - 2,
|
.x = ctx.input.mouse.pos.x - 2,
|
||||||
.y = ctx.input.mouse.pos.y - 2,
|
.y = ctx.input.mouse.pos.y - 2,
|
||||||
|
|||||||
12
src/font.c3
12
src/font.c3
@ -5,7 +5,7 @@ import std::collections::map;
|
|||||||
import std::core::mem;
|
import std::core::mem;
|
||||||
import std::core::mem::allocator;
|
import std::core::mem::allocator;
|
||||||
import std::io;
|
import std::io;
|
||||||
import std::ascii;
|
import std::core::ascii;
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------- //
|
// ---------------------------------------------------------------------------------- //
|
||||||
@ -65,8 +65,8 @@ struct Font {
|
|||||||
bool should_update; // should send update_atlas command, resets at frame_end()
|
bool should_update; // should send update_atlas command, resets at frame_end()
|
||||||
}
|
}
|
||||||
|
|
||||||
macro Rect Glyph.bounds(&g) => {.x = g.ox, .y = g.oy, .w = g.w, .h = g.h};
|
macro Rect Glyph.bounds(&g) => {.x = (short)g.ox, .y = (short)g.oy, .w = (short)g.w, .h = (short)g.h};
|
||||||
macro Rect Glyph.uv(&g) => {.x = g.u, .y = g.v, .w = g.w, .h = g.h};
|
macro Rect Glyph.uv(&g) => {.x = (short)g.u, .y = (short)g.v, .w = (short)g.w, .h = (short)g.h};
|
||||||
|
|
||||||
<*
|
<*
|
||||||
@param [&inout] font
|
@param [&inout] font
|
||||||
@ -145,7 +145,7 @@ fn Glyph*? Font.get_glyph(&font, Codepoint code)
|
|||||||
.width = gmtx.minWidth,
|
.width = gmtx.minWidth,
|
||||||
.height = gmtx.minHeight,
|
.height = gmtx.minHeight,
|
||||||
};
|
};
|
||||||
char[] pixels = mem::new_array(char, (usz)img.width * img.height);
|
char[] pixels = mem::new_array(char, (usz)img.width * (usz)img.height);
|
||||||
img.pixels = pixels;
|
img.pixels = pixels;
|
||||||
if (schrift::render(&font.sft, gid, img) < 0) {
|
if (schrift::render(&font.sft, gid, img) < 0) {
|
||||||
return RENDER_ERROR~;
|
return RENDER_ERROR~;
|
||||||
@ -161,8 +161,8 @@ fn Glyph*? Font.get_glyph(&font, Codepoint code)
|
|||||||
// glyph.code, glyph.w, glyph.h, glyph.ox, glyph.oy, glyph.adv);
|
// glyph.code, glyph.w, glyph.h, glyph.ox, glyph.oy, glyph.adv);
|
||||||
|
|
||||||
Point uv = font.atlas.place(pixels, glyph.w, glyph.h, (ushort)img.width)!;
|
Point uv = font.atlas.place(pixels, glyph.w, glyph.h, (ushort)img.width)!;
|
||||||
glyph.u = uv.x;
|
glyph.u = (ushort)uv.x;
|
||||||
glyph.v = uv.y;
|
glyph.v = (ushort)uv.y;
|
||||||
|
|
||||||
mem::free(pixels);
|
mem::free(pixels);
|
||||||
|
|
||||||
|
|||||||
31
src/input.c3
31
src/input.c3
@ -59,17 +59,20 @@ const ModKeys KMOD_ALT = {.lalt = true, .ralt = true};
|
|||||||
const ModKeys KMOD_GUI = {.lgui = true, .rgui = true};
|
const ModKeys KMOD_GUI = {.lgui = true, .rgui = true};
|
||||||
const ModKeys KMOD_TXT = {.bkspc = true, .del = true}; // modkeys that act like text input
|
const ModKeys KMOD_TXT = {.bkspc = true, .del = true}; // modkeys that act like text input
|
||||||
const ModKeys KMOD_NONE = {};
|
const ModKeys KMOD_NONE = {};
|
||||||
const ModKeys KMOD_ANY = (ModKeys)(ModKeys.inner.max);
|
const ModKeys KMOD_ANY = (ModKeys)(uint::max);
|
||||||
|
//const ModKeys KMOD_ANY = (ModKeys)(ModKeys::inner::max);
|
||||||
|
|
||||||
const MouseButtons BTN_NONE = {};
|
const MouseButtons BTN_NONE = {};
|
||||||
const MouseButtons BTN_ANY = (MouseButtons)(MouseButtons.inner.max);
|
const MouseButtons BTN_ANY = (MouseButtons)(uint::max);
|
||||||
|
//const MouseButtons BTN_ANY = (MouseButtons)(MouseButtons::max);
|
||||||
const MouseButtons BTN_LEFT = {.btn_left = true};
|
const MouseButtons BTN_LEFT = {.btn_left = true};
|
||||||
const MouseButtons BTN_MIDDLE = {.btn_middle = true};
|
const MouseButtons BTN_MIDDLE = {.btn_middle = true};
|
||||||
const MouseButtons BTN_RIGHT = {.btn_right = true};
|
const MouseButtons BTN_RIGHT = {.btn_right = true};
|
||||||
const MouseButtons BTN_4 = {.btn_4 = true};
|
const MouseButtons BTN_4 = {.btn_4 = true};
|
||||||
const MouseButtons BTN_5 = {.btn_5 = true};
|
const MouseButtons BTN_5 = {.btn_5 = true};
|
||||||
|
|
||||||
const ModKeys KEY_ANY = (ModKeys)(ModKeys.inner.max);
|
const ModKeys KEY_ANY = (ModKeys)(uint::max);
|
||||||
|
//const ModKeys KEY_ANY = (ModKeys)(ModKeys::max);
|
||||||
|
|
||||||
<* @param [&inout] ctx *>
|
<* @param [&inout] ctx *>
|
||||||
fn bool Ctx.check_key_combo(&ctx, ModKeys mod, String ...keys)
|
fn bool Ctx.check_key_combo(&ctx, ModKeys mod, String ...keys)
|
||||||
@ -90,9 +93,9 @@ fn void? Ctx.input_window_size(&ctx, short width, short height)
|
|||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
return INVALID_SIZE~;
|
return INVALID_SIZE~;
|
||||||
}
|
}
|
||||||
ctx.current_input.events.resize = ctx.width != width || ctx.height != height;
|
ctx.current_input.events.resize = ctx.width != (ushort)width || ctx.height != (ushort)height;
|
||||||
ctx.width = width;
|
ctx.width = (ushort)width;
|
||||||
ctx.height = height;
|
ctx.height = (ushort)height;
|
||||||
if (ctx.current_input.events.resize) ctx.skip_frame = true;
|
if (ctx.current_input.events.resize) ctx.skip_frame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +130,8 @@ fn void Ctx.input_mouse_button(&ctx, MouseButtons buttons)
|
|||||||
<* @param [&inout] ctx *>
|
<* @param [&inout] ctx *>
|
||||||
fn void Ctx.input_mouse_abs(&ctx, short x, short y)
|
fn void Ctx.input_mouse_abs(&ctx, short x, short y)
|
||||||
{
|
{
|
||||||
ctx.current_input.mouse.pos.x = math::clamp(x, (short)0, ctx.width);
|
ctx.current_input.mouse.pos.x = math::clamp(x, (short)0, (short)ctx.width);
|
||||||
ctx.current_input.mouse.pos.y = math::clamp(y, (short)0, ctx.height);
|
ctx.current_input.mouse.pos.y = math::clamp(y, (short)0, (short)ctx.height);
|
||||||
|
|
||||||
short dx, dy;
|
short dx, dy;
|
||||||
dx = x - ctx.current_input.mouse.pos.x;
|
dx = x - ctx.current_input.mouse.pos.x;
|
||||||
@ -151,8 +154,8 @@ fn void Ctx.input_mouse_delta(&ctx, short dx, short dy)
|
|||||||
mx = ctx.current_input.mouse.pos.x + dx;
|
mx = ctx.current_input.mouse.pos.x + dx;
|
||||||
my = ctx.current_input.mouse.pos.y + dy;
|
my = ctx.current_input.mouse.pos.y + dy;
|
||||||
|
|
||||||
ctx.current_input.mouse.pos.x = math::clamp(mx, (short)0, ctx.width);
|
ctx.current_input.mouse.pos.x = math::clamp(mx, (short)0, (short)ctx.width);
|
||||||
ctx.current_input.mouse.pos.y = math::clamp(my, (short)0, ctx.height);
|
ctx.current_input.mouse.pos.y = math::clamp(my, (short)0, (short)ctx.height);
|
||||||
|
|
||||||
ctx.current_input.events.mouse_move = dx != 0 || dy != 0;
|
ctx.current_input.events.mouse_move = dx != 0 || dy != 0;
|
||||||
}
|
}
|
||||||
@ -189,8 +192,8 @@ fn void Ctx.input_text_utf8(&ctx, char[] text)
|
|||||||
{
|
{
|
||||||
if (text == "") return;
|
if (text == "") return;
|
||||||
|
|
||||||
usz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
sz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
||||||
usz len = text.len > remaining ? remaining : text.len;
|
sz len = text.len > remaining ? remaining : text.len;
|
||||||
char[] s = ctx.current_input.keyboard.text[ctx.current_input.keyboard.text_len ..];
|
char[] s = ctx.current_input.keyboard.text[ctx.current_input.keyboard.text_len ..];
|
||||||
s[..len-1] = text[..len-1];
|
s[..len-1] = text[..len-1];
|
||||||
ctx.current_input.keyboard.text_len += len;
|
ctx.current_input.keyboard.text_len += len;
|
||||||
@ -205,10 +208,10 @@ fn void? Ctx.input_text_unicode(&ctx, uint[] text)
|
|||||||
{
|
{
|
||||||
if (text.len == 0) return;
|
if (text.len == 0) return;
|
||||||
|
|
||||||
usz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
sz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
||||||
char[] s = ctx.current_input.keyboard.text[ctx.current_input.keyboard.text_len ..];
|
char[] s = ctx.current_input.keyboard.text[ctx.current_input.keyboard.text_len ..];
|
||||||
|
|
||||||
usz off = conv::utf32to8(text, s)!;
|
sz off = conv::utf32to8(text, s)!;
|
||||||
ctx.current_input.keyboard.text_len += off;
|
ctx.current_input.keyboard.text_len += off;
|
||||||
|
|
||||||
ctx.current_input.events.text_input = true;
|
ctx.current_input.events.text_input = true;
|
||||||
|
|||||||
22
src/mtree.c3
22
src/mtree.c3
@ -60,14 +60,14 @@ module mtree<Type>;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import std::core::mem;
|
import std::core::mem;
|
||||||
import std::core::mem::allocator;
|
import std::core::mem::alloc;
|
||||||
import std::io;
|
import std::io;
|
||||||
import std::bits;
|
import std::bits;
|
||||||
import std::collections::list;
|
import std::collections::list;
|
||||||
|
|
||||||
|
|
||||||
alias Bitmap = ulong;
|
alias Bitmap = ulong;
|
||||||
const BITS = Bitmap.sizeof*8;
|
const BITS = Bitmap::size*8;
|
||||||
|
|
||||||
alias IdxList = List{int};
|
alias IdxList = List{int};
|
||||||
|
|
||||||
@ -96,10 +96,10 @@ fn void MTree.init(&tree, usz size, Allocator allocator = mem)
|
|||||||
|
|
||||||
tree.elements = 0;
|
tree.elements = 0;
|
||||||
tree.allocator = allocator;
|
tree.allocator = allocator;
|
||||||
tree.queue.init(tree.allocator, size);
|
tree.queue.init(tree.allocator, (sz)size);
|
||||||
tree.used = allocator::new_array(tree.allocator, Bitmap, size/BITS);
|
tree.used = alloc::new_array(tree.allocator, Bitmap, (sz)size/BITS);
|
||||||
tree.elem_vec = allocator::new_array(tree.allocator, Type, size);
|
tree.elem_vec = alloc::new_array(tree.allocator, Type, (sz)size);
|
||||||
tree.refs_vec = allocator::new_array(tree.allocator, RefNode, size);
|
tree.refs_vec = alloc::new_array(tree.allocator, RefNode, (sz)size);
|
||||||
|
|
||||||
foreach (&r: tree.refs_vec) {
|
foreach (&r: tree.refs_vec) {
|
||||||
r.next = -1;
|
r.next = -1;
|
||||||
@ -112,9 +112,9 @@ fn void MTree.free(&tree)
|
|||||||
{
|
{
|
||||||
tree.elements = 0;
|
tree.elements = 0;
|
||||||
tree.queue.free();
|
tree.queue.free();
|
||||||
(void)allocator::free(tree.allocator, tree.used);
|
(void)alloc::free(tree.allocator, tree.used);
|
||||||
(void)allocator::free(tree.allocator, tree.elem_vec);
|
(void)alloc::free(tree.allocator, tree.elem_vec);
|
||||||
(void)allocator::free(tree.allocator, tree.refs_vec);
|
(void)alloc::free(tree.allocator, tree.refs_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ fn void MTree.free(&tree)
|
|||||||
fn int? MTree.get_free_spot(&tree)
|
fn int? MTree.get_free_spot(&tree)
|
||||||
{
|
{
|
||||||
foreach (idx, d: tree.used) {
|
foreach (idx, d: tree.used) {
|
||||||
if (d != $typeof(d).max) {
|
if (d != $Typeof(d)::max) {
|
||||||
int spot = (int)idx*BITS + BITS-(int)d.clz();
|
int spot = (int)idx*BITS + BITS-(int)d.clz();
|
||||||
return spot;
|
return spot;
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ fn Type? MTree.get(&tree, int ref) @operator([])
|
|||||||
}
|
}
|
||||||
|
|
||||||
<* @param [&in] tree *>
|
<* @param [&in] tree *>
|
||||||
fn Type? MTree.parentof(&tree, int ref)
|
fn int? MTree.parentof(&tree, int ref)
|
||||||
{
|
{
|
||||||
if (!tree.is_used(ref)) return NOT_FOUND~;
|
if (!tree.is_used(ref)) return NOT_FOUND~;
|
||||||
return tree.refs_vec[ref].parent;
|
return tree.refs_vec[ref].parent;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ struct Rect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find another name
|
// TODO: find another name
|
||||||
const Rect RECT_MAX = {0, 0, short.max, short.max};
|
const Rect RECT_MAX = {0, 0, short::max, short::max};
|
||||||
|
|
||||||
// return true if rect a contains b
|
// return true if rect a contains b
|
||||||
macro bool Rect.contains(Rect a, Rect b)
|
macro bool Rect.contains(Rect a, Rect b)
|
||||||
@ -250,7 +250,7 @@ struct Size {
|
|||||||
|
|
||||||
macro Size @grow() => {.min = 0, .max = 0};
|
macro Size @grow() => {.min = 0, .max = 0};
|
||||||
macro Size @exact(short s) => {.min = s, .max = s};
|
macro Size @exact(short s) => {.min = s, .max = s};
|
||||||
macro Size @fit(short min = 0, short max = short.max) => {.min = min, .max = max};
|
macro Size @fit(short min = 0, short max = short::max) => {.min = min, .max = max};
|
||||||
|
|
||||||
macro bool Size.@is_grow(s) => (s.min == 0 && s.max == 0);
|
macro bool Size.@is_grow(s) => (s.min == 0 && s.max == 0);
|
||||||
macro bool Size.@is_exact(s) => (s.min == s.max && s.min != 0);
|
macro bool Size.@is_exact(s) => (s.min == s.max && s.min != 0);
|
||||||
|
|||||||
@ -40,7 +40,7 @@ fn void? SpriteAtlas.init(&this, String name, AtlasType type, ushort width, usho
|
|||||||
|
|
||||||
this.id = name.hash();
|
this.id = name.hash();
|
||||||
this.atlas.new(this.id, AtlasType.ATLAS_R8G8B8A8, width, height)!;
|
this.atlas.new(this.id, AtlasType.ATLAS_R8G8B8A8, width, height)!;
|
||||||
this.sprites.init(allocator::mem, capacity: SRITES_PER_ATLAS);
|
this.sprites.init(mem, capacity: SRITES_PER_ATLAS);
|
||||||
this.should_update = false;
|
this.should_update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +60,8 @@ fn Sprite*? SpriteAtlas.insert(&this, String name, SpriteType type, char[] pixel
|
|||||||
Point uv = this.atlas.place(pixels, w, h, stride)!;
|
Point uv = this.atlas.place(pixels, w, h, stride)!;
|
||||||
s.w = w;
|
s.w = w;
|
||||||
s.h = h;
|
s.h = h;
|
||||||
s.u = uv.x;
|
s.u = (ushort)uv.x;
|
||||||
s.v = uv.y;
|
s.v = (ushort)uv.y;
|
||||||
this.sprites.set(s.id, s);
|
this.sprites.set(s.id, s);
|
||||||
this.should_update = true;
|
this.should_update = true;
|
||||||
return this.sprites.get_ref(s.id);
|
return this.sprites.get_ref(s.id);
|
||||||
@ -78,8 +78,8 @@ fn Sprite*? SpriteAtlas.get_by_id(&this, Id id)
|
|||||||
return this.sprites.get_ref(id);
|
return this.sprites.get_ref(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro Rect Sprite.rect(s) => {0,0,s.w,s.h};
|
macro Rect Sprite.rect(s) => {0, 0, (short)s.w, (short)s.h};
|
||||||
macro Rect Sprite.uv(s) => {s.u,s.v,s.w,s.h};
|
macro Rect Sprite.uv(s) => {(short)s.u, (short)s.v, (short)s.w, (short)s.h};
|
||||||
|
|
||||||
fn void? Ctx.sprite_atlas_create(&ctx, String name, AtlasType type, ushort w, ushort h)
|
fn void? Ctx.sprite_atlas_create(&ctx, String name, AtlasType type, ushort w, ushort h)
|
||||||
{
|
{
|
||||||
@ -100,7 +100,7 @@ fn void? Ctx.import_sprite_file_qoi(&ctx, String name, String path, SpriteType t
|
|||||||
{
|
{
|
||||||
QOIDesc desc;
|
QOIDesc desc;
|
||||||
|
|
||||||
char[] pixels = qoi::read(allocator::mem, path, &desc, QOIChannels.RGBA)!;
|
char[] pixels = qoi::read(mem, path, &desc, QOIChannels.RGBA)!;
|
||||||
defer mem::free(pixels);
|
defer mem::free(pixels);
|
||||||
|
|
||||||
ctx.sprite_atlas.insert(name, type, pixels, (ushort)desc.width, (ushort)desc.height, (ushort)desc.width)!;
|
ctx.sprite_atlas.insert(name, type, pixels, (ushort)desc.width, (ushort)desc.height, (ushort)desc.width)!;
|
||||||
|
|||||||
@ -4,12 +4,12 @@ import std::collections::list;
|
|||||||
import std::core::string;
|
import std::core::string;
|
||||||
|
|
||||||
struct LineInfo @local {
|
struct LineInfo @local {
|
||||||
usz start, end;
|
sz start, end;
|
||||||
short width, height;
|
short width, height;
|
||||||
short first_off; // first character offset
|
short first_off; // first character offset
|
||||||
}
|
}
|
||||||
|
|
||||||
macro usz LineInfo.len(li) => li.end-li.start;
|
macro sz LineInfo.len(li) => li.end-li.start;
|
||||||
|
|
||||||
alias LineStack @local = list::List{LineInfo};
|
alias LineStack @local = list::List{LineInfo};
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ struct GlyphIterator {
|
|||||||
Font* font;
|
Font* font;
|
||||||
|
|
||||||
LineStack lines;
|
LineStack lines;
|
||||||
usz line_off, line_idx;
|
sz line_off, line_idx;
|
||||||
String text;
|
String text;
|
||||||
|
|
||||||
Codepoint cp;
|
Codepoint cp;
|
||||||
@ -123,15 +123,15 @@ fn void? GlyphIterator.init(&self, Allocator allocator, String text, Rect bounds
|
|||||||
|
|
||||||
fn void? GlyphIterator.populate_lines_stack(&self)
|
fn void? GlyphIterator.populate_lines_stack(&self)
|
||||||
{
|
{
|
||||||
usz line_start;
|
sz line_start;
|
||||||
LineInfo li;
|
LineInfo li;
|
||||||
Point o = self.o;
|
Point o = self.o;
|
||||||
StringIterator ti = self.text.iterator();
|
StringIterator ti = self.text.iterator();
|
||||||
|
|
||||||
usz prev_off;
|
sz prev_off;
|
||||||
for (Codepoint cp; ti.has_next();) {
|
for (Codepoint cp; ti.has_next();) {
|
||||||
cp = ti.next()!;
|
cp = ti.next()!;
|
||||||
usz off = ti.current;
|
sz off = ti.current;
|
||||||
bool push = false;
|
bool push = false;
|
||||||
|
|
||||||
li.height = self.line_height;
|
li.height = self.line_height;
|
||||||
@ -233,7 +233,7 @@ fn Rect? GlyphIterator.next(&self)
|
|||||||
t = self.text[self.line_off..];
|
t = self.text[self.line_off..];
|
||||||
}
|
}
|
||||||
|
|
||||||
usz read = t.len < 4 ? t.len : 4;
|
sz read = t.len < 4 ? t.len : 4;
|
||||||
self.cp = conv::utf8_to_char32(&t[0], &read)!;
|
self.cp = conv::utf8_to_char32(&t[0], &read)!;
|
||||||
self.line_off += read;
|
self.line_off += read;
|
||||||
self.gp = self.font.get_glyph(self.cp)!;
|
self.gp = self.font.get_glyph(self.cp)!;
|
||||||
@ -292,7 +292,7 @@ fn bool GlyphIterator.has_next(&self)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usz GlyphIterator.current_offset(&self)
|
fn sz GlyphIterator.current_offset(&self)
|
||||||
{
|
{
|
||||||
if (self.anchor == TOP_LEFT) return self.line_off;
|
if (self.anchor == TOP_LEFT) return self.line_off;
|
||||||
return self.lines[self.line_idx].start + self.line_off;
|
return self.lines[self.line_idx].start + self.line_off;
|
||||||
@ -327,7 +327,7 @@ fn void? Ctx.layout_string(&ctx, String text, Rect bounds, Anchor anchor, int z_
|
|||||||
// ---------------------------------------------------------------------------------- //
|
// ---------------------------------------------------------------------------------- //
|
||||||
|
|
||||||
|
|
||||||
fn Rect? Ctx.get_cursor_position(&ctx, String text, Rect bounds, Anchor anchor, usz cursor, bool reflow = false)
|
fn Rect? Ctx.get_cursor_position(&ctx, String text, Rect bounds, Anchor anchor, sz cursor, bool reflow = false)
|
||||||
{
|
{
|
||||||
if (bounds.w <= 0 || bounds.h <= 0) return {};
|
if (bounds.w <= 0 || bounds.h <= 0) return {};
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ fn Rect? Ctx.get_cursor_position(&ctx, String text, Rect bounds, Anchor anchor,
|
|||||||
@param [&in] ctx
|
@param [&in] ctx
|
||||||
@param [in] text
|
@param [in] text
|
||||||
*>
|
*>
|
||||||
fn usz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point p, bool reflow = false)
|
fn sz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point p, bool reflow = false)
|
||||||
{
|
{
|
||||||
if (text == "") return 0;
|
if (text == "") return 0;
|
||||||
if (bounds.w <= 0 || bounds.h <= 0) return 0;
|
if (bounds.w <= 0 || bounds.h <= 0) return 0;
|
||||||
@ -382,12 +382,12 @@ fn usz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point
|
|||||||
GlyphIterator gi;
|
GlyphIterator gi;
|
||||||
gi.init(tmem, text, bounds, font, anchor, reflow, TAB_SIZE)!;
|
gi.init(tmem, text, bounds, font, anchor, reflow, TAB_SIZE)!;
|
||||||
|
|
||||||
usz prev_offset = 0;
|
sz prev_offset = 0;
|
||||||
Point prev_o = gi.o;
|
Point prev_o = gi.o;
|
||||||
|
|
||||||
while (gi.has_next()) {
|
while (gi.has_next()) {
|
||||||
Point o_before = gi.o;
|
Point o_before = gi.o;
|
||||||
usz offset_before = gi.current_offset();
|
sz offset_before = gi.current_offset();
|
||||||
Rect b = gi.next()!;
|
Rect b = gi.next()!;
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -443,7 +443,7 @@ fn usz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement a function `layout_string_with_selection` to avoid iterating over the string twice
|
// TODO: implement a function `layout_string_with_selection` to avoid iterating over the string twice
|
||||||
fn void? Ctx.draw_string_selection(&ctx, String text, Rect bounds, Anchor anchor, usz start, usz end, int z_index, Color hue, bool reflow = false)
|
fn void? Ctx.draw_string_selection(&ctx, String text, Rect bounds, Anchor anchor, sz start, sz end, int z_index, Color hue, bool reflow = false)
|
||||||
{
|
{
|
||||||
if (text == "") return;
|
if (text == "") return;
|
||||||
if (bounds.w <= 0 || bounds.h <= 0) return;
|
if (bounds.w <= 0 || bounds.h <= 0) return;
|
||||||
@ -452,7 +452,7 @@ fn void? Ctx.draw_string_selection(&ctx, String text, Rect bounds, Anchor anchor
|
|||||||
|
|
||||||
// Ensure start < end
|
// Ensure start < end
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
usz temp = start;
|
sz temp = start;
|
||||||
start = end;
|
start = end;
|
||||||
end = temp;
|
end = temp;
|
||||||
}
|
}
|
||||||
@ -465,11 +465,11 @@ fn void? Ctx.draw_string_selection(&ctx, String text, Rect bounds, Anchor anchor
|
|||||||
gi.init(tmem, text, bounds, font, anchor, reflow, TAB_SIZE)!;
|
gi.init(tmem, text, bounds, font, anchor, reflow, TAB_SIZE)!;
|
||||||
|
|
||||||
Rect sel_rect = { .h = gi.line_height }; // selection rect
|
Rect sel_rect = { .h = gi.line_height }; // selection rect
|
||||||
isz sel_line = -1; // selection line
|
sz sel_line = -1; // selection line
|
||||||
while (gi.has_next()) {
|
while (gi.has_next()) {
|
||||||
Rect b = gi.next()!;
|
Rect b = gi.next()!;
|
||||||
usz off = gi.current_offset()-1;
|
sz off = gi.current_offset()-1;
|
||||||
isz line = gi.line_idx;
|
sz line = gi.line_idx;
|
||||||
bool in_selection = start <= off && off <= end;
|
bool in_selection = start <= off && off <= end;
|
||||||
|
|
||||||
if (in_selection && line != sel_line) {
|
if (in_selection && line != sel_line) {
|
||||||
@ -522,9 +522,9 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
|||||||
short line_height = (short)font.line_height();
|
short line_height = (short)font.line_height();
|
||||||
short line_gap = (short)font.linegap;
|
short line_gap = (short)font.linegap;
|
||||||
short space_width = font.get_glyph(' ').adv!;
|
short space_width = font.get_glyph(' ').adv!;
|
||||||
short tab_width = space_width * TAB_SIZE;
|
short tab_width = (usz)space_width * TAB_SIZE;
|
||||||
|
|
||||||
isz off;
|
sz off;
|
||||||
usz x;
|
usz x;
|
||||||
|
|
||||||
TextSize ts;
|
TextSize ts;
|
||||||
@ -566,7 +566,7 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
|||||||
if (off < text.len) {
|
if (off < text.len) {
|
||||||
word_width += gp.adv;
|
word_width += gp.adv;
|
||||||
} else {
|
} else {
|
||||||
word_width += gp.w + gp.ox;
|
word_width += (short)gp.w + (short)gp.ox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/style.c3
18
src/style.c3
@ -75,7 +75,7 @@ fn int Ctx.import_style_from_string(&ctx, String text) => ctx.styles.import_styl
|
|||||||
fn int Ctx.import_style_from_file(&ctx, String path)
|
fn int Ctx.import_style_from_file(&ctx, String path)
|
||||||
{
|
{
|
||||||
char[] text;
|
char[] text;
|
||||||
usz size = file::get_size(path)!!;
|
sz size = file::get_size(path)!!;
|
||||||
text = mem::new_array(char, size);
|
text = mem::new_array(char, size);
|
||||||
file::load_buffer(path, text)!!;
|
file::load_buffer(path, text)!!;
|
||||||
defer mem::free(text);
|
defer mem::free(text);
|
||||||
@ -109,7 +109,7 @@ fn int Ctx.import_style_from_file(&ctx, String path)
|
|||||||
|
|
||||||
module ugui::css;
|
module ugui::css;
|
||||||
|
|
||||||
import std::ascii;
|
import std::core::ascii;
|
||||||
import std::io;
|
import std::io;
|
||||||
|
|
||||||
// CSS parser module
|
// CSS parser module
|
||||||
@ -194,14 +194,14 @@ fn Token Lexer.next_token(&lex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// skip whitespace
|
// skip whitespace
|
||||||
while (ascii::is_space_m(lex.peep())) {
|
while (ascii::is_space(lex.peep())) {
|
||||||
if (lex.advance() == 0) return {.type = EOF};
|
if (lex.advance() == 0) return {.type = EOF};
|
||||||
if (lex.off >= lex.text.len) return {.type = EOF};
|
if (lex.off >= lex.text.len) return {.type = EOF};
|
||||||
}
|
}
|
||||||
t.off = lex.off;
|
t.off = lex.off;
|
||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case ascii::is_punct_m(lex.peep()) && lex.peep() != '#': // punctuation
|
case ascii::is_punct(lex.peep()) && lex.peep() != '#': // punctuation
|
||||||
t.text = lex.text[lex.off:1];
|
t.text = lex.text[lex.off:1];
|
||||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||||
switch (t.text[0]) {
|
switch (t.text[0]) {
|
||||||
@ -216,7 +216,7 @@ fn Token Lexer.next_token(&lex)
|
|||||||
t.type = COLOR;
|
t.type = COLOR;
|
||||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||||
usz hex_start = t.off+1;
|
usz hex_start = t.off+1;
|
||||||
while (ascii::is_alnum_m(lex.peep())) {
|
while (ascii::is_alnum(lex.peep())) {
|
||||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||||
}
|
}
|
||||||
usz h_len = lex.off - hex_start;
|
usz h_len = lex.off - hex_start;
|
||||||
@ -236,19 +236,19 @@ fn Token Lexer.next_token(&lex)
|
|||||||
}
|
}
|
||||||
t.color = color_hex.to_rgba();
|
t.color = color_hex.to_rgba();
|
||||||
|
|
||||||
case ascii::is_alpha_m(lex.peep()): // identifier
|
case ascii::is_alpha(lex.peep()): // identifier
|
||||||
t.type = IDENTIFIER;
|
t.type = IDENTIFIER;
|
||||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '-' || lex.peep() == '_') {
|
while (ascii::is_alnum(lex.peep()) || lex.peep() == '-' || lex.peep() == '_') {
|
||||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||||
}
|
}
|
||||||
t.text = lex.text[t.off..lex.off-1];
|
t.text = lex.text[t.off..lex.off-1];
|
||||||
|
|
||||||
case ascii::is_digit_m(lex.peep()): // number
|
case ascii::is_digit(lex.peep()): // number
|
||||||
t.type = NUMBER;
|
t.type = NUMBER;
|
||||||
t.unit = PIXELS;
|
t.unit = PIXELS;
|
||||||
// find the end of the number
|
// find the end of the number
|
||||||
usz end;
|
usz end;
|
||||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '+' || lex.peep() == '-' || lex.peep() == '.') {
|
while (ascii::is_alnum(lex.peep()) || lex.peep() == '+' || lex.peep() == '-' || lex.peep() == '.') {
|
||||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||||
}
|
}
|
||||||
end = lex.off;
|
end = lex.off;
|
||||||
|
|||||||
@ -4,16 +4,16 @@ import ugui::textedit::te;
|
|||||||
|
|
||||||
struct TextEdit {
|
struct TextEdit {
|
||||||
char[] buffer;
|
char[] buffer;
|
||||||
usz chars;
|
sz chars;
|
||||||
usz cursor;
|
sz cursor;
|
||||||
isz sel_len;
|
sz sel_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn String TextEdit.to_string(&te) => (String)te.buffer[:te.chars];
|
fn String TextEdit.to_string(&te) => (String)te.buffer[:te.chars];
|
||||||
fn String TextEdit.until_cursor(&te) => (String)te.buffer[..te.cursor];
|
fn String TextEdit.until_cursor(&te) => (String)te.buffer[..te.cursor];
|
||||||
fn String TextEdit.from_cursor(&te) => (String)te.buffer[te.cursor..te.chars];
|
fn String TextEdit.from_cursor(&te) => (String)te.buffer[te.cursor..te.chars];
|
||||||
fn String TextEdit.until(&te, usz off) => (String)te.buffer[..min(te.chars, off)];
|
fn String TextEdit.until(&te, sz off) => (String)te.buffer[..min(te.chars, off)];
|
||||||
fn String TextEdit.from(&te, usz off) => (String)te.buffer[off..te.chars];
|
fn String TextEdit.from(&te, sz off) => (String)te.buffer[off..te.chars];
|
||||||
|
|
||||||
// implement text editing operations on the buffer
|
// implement text editing operations on the buffer
|
||||||
// returns true if the buffer is full
|
// returns true if the buffer is full
|
||||||
@ -75,26 +75,26 @@ fn bool Ctx.text_edit(&ctx, TextEdit* te)
|
|||||||
module ugui::textedit::te;
|
module ugui::textedit::te;
|
||||||
|
|
||||||
import std::core::string;
|
import std::core::string;
|
||||||
import std::ascii;
|
import std::core::ascii;
|
||||||
import std::collections::pair;
|
import std::collections::pair;
|
||||||
|
|
||||||
alias OffPair = pair::Pair{usz, usz};
|
alias OffPair = pair::Pair{sz, sz};
|
||||||
|
|
||||||
// returns the offset of the next codepoint in the buffer from the cursor
|
// returns the offset of the next codepoint in the buffer from the cursor
|
||||||
fn usz TextEdit.next_char_off(&te)
|
fn sz TextEdit.next_char_off(&te)
|
||||||
{
|
{
|
||||||
usz len = min(te.chars - te.cursor, 4);
|
sz len = min(te.chars - te.cursor, 4);
|
||||||
if (len == 0) return len;
|
if (len == 0) return len;
|
||||||
conv::utf8_to_char32(&te.buffer[te.cursor], &len)!!;
|
conv::utf8_to_char32(&te.buffer[te.cursor], &len)!!;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the offset of the previous codepoint in the buffer from the cursor
|
// returns the offset of the previous codepoint in the buffer from the cursor
|
||||||
fn usz TextEdit.prev_char_off(&te)
|
fn sz TextEdit.prev_char_off(&te)
|
||||||
{
|
{
|
||||||
if (te.cursor == 0) return 0;
|
if (te.cursor == 0) return 0;
|
||||||
String b = (String)te.buffer[..te.cursor];
|
String b = (String)te.buffer[..te.cursor];
|
||||||
usz len;
|
sz len;
|
||||||
foreach_r (off, c: b) {
|
foreach_r (off, c: b) {
|
||||||
if (c & 0xC0 == 0x80) continue;
|
if (c & 0xC0 == 0x80) continue;
|
||||||
len = b.len - off;
|
len = b.len - off;
|
||||||
@ -123,7 +123,7 @@ fn void TextEdit.move_cursor(&te, bool forward, bool select)
|
|||||||
te.sel_len = 0;
|
te.sel_len = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
isz off = forward ? te.next_char_off() : -te.prev_char_off();
|
sz off = forward ? te.next_char_off() : -te.prev_char_off();
|
||||||
if (te.cursor + off < 0 || te.cursor + off > te.chars) return;
|
if (te.cursor + off < 0 || te.cursor + off > te.chars) return;
|
||||||
te.cursor += off;
|
te.cursor += off;
|
||||||
// if trying to select increment selection width
|
// if trying to select increment selection width
|
||||||
@ -135,12 +135,12 @@ fn void TextEdit.move_cursor(&te, bool forward, bool select)
|
|||||||
|
|
||||||
// set the cursor to the exact offset provided, the selection flags controls wether the selection has
|
// set the cursor to the exact offset provided, the selection flags controls wether the selection has
|
||||||
// expanded or rese
|
// expanded or rese
|
||||||
fn void TextEdit.set_cursor(&te, usz cur, bool select)
|
fn void TextEdit.set_cursor(&te, sz cur, bool select)
|
||||||
{
|
{
|
||||||
if (!select) te.sel_len = 0;
|
if (!select) te.sel_len = 0;
|
||||||
if (cur == te.cursor) return;
|
if (cur == te.cursor) return;
|
||||||
|
|
||||||
usz prev_cur = te.cursor;
|
sz prev_cur = te.cursor;
|
||||||
te.cursor = cur;
|
te.cursor = cur;
|
||||||
if (select) {
|
if (select) {
|
||||||
te.sel_len += prev_cur - cur;
|
te.sel_len += prev_cur - cur;
|
||||||
@ -155,7 +155,7 @@ fn void TextEdit.move_cursor_word(&te, bool forward, bool select)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usz prev_cur = te.cursor;
|
sz prev_cur = te.cursor;
|
||||||
while (te.cursor <= te.chars) {
|
while (te.cursor <= te.chars) {
|
||||||
char c;
|
char c;
|
||||||
if (forward) {
|
if (forward) {
|
||||||
@ -203,9 +203,9 @@ fn void TextEdit.delete_selection(&te)
|
|||||||
{
|
{
|
||||||
if (te.sel_len == 0) return;
|
if (te.sel_len == 0) return;
|
||||||
|
|
||||||
usz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
sz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
||||||
usz end = te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor;
|
sz end = te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor;
|
||||||
usz len = te.chars - end;
|
sz len = te.chars - end;
|
||||||
|
|
||||||
te.buffer[start:len] = te.buffer[end:len];
|
te.buffer[start:len] = te.buffer[end:len];
|
||||||
te.cursor -= te.sel_len < 0 ? -te.sel_len : 0;
|
te.cursor -= te.sel_len < 0 ? -te.sel_len : 0;
|
||||||
@ -224,15 +224,15 @@ fn void TextEdit.remove_character(&te, bool forward)
|
|||||||
|
|
||||||
if (te.chars == 0) return;
|
if (te.chars == 0) return;
|
||||||
if (forward) {
|
if (forward) {
|
||||||
usz rem = te.chars - te.cursor;
|
sz rem = te.chars - te.cursor;
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
usz len = te.next_char_off();
|
sz len = te.next_char_off();
|
||||||
te.buffer[te.cursor:rem-len] = te.buffer[te.cursor+len:rem-len];
|
te.buffer[te.cursor:rem-len] = te.buffer[te.cursor+len:rem-len];
|
||||||
te.chars -= len;
|
te.chars -= len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (te.cursor > 0) {
|
if (te.cursor > 0) {
|
||||||
usz len = te.prev_char_off();
|
sz len = te.prev_char_off();
|
||||||
te.buffer[te.cursor-len:te.chars-te.cursor] = te.buffer[te.cursor:te.chars-te.cursor];
|
te.buffer[te.cursor-len:te.chars-te.cursor] = te.buffer[te.cursor:te.chars-te.cursor];
|
||||||
te.chars -= len;
|
te.chars -= len;
|
||||||
te.cursor -= len;
|
te.cursor -= len;
|
||||||
@ -249,7 +249,7 @@ fn void TextEdit.remove_word(&te, bool forward)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usz prev_cur = te.cursor;
|
sz prev_cur = te.cursor;
|
||||||
while (te.chars > 0) {
|
while (te.chars > 0) {
|
||||||
char c;
|
char c;
|
||||||
if (forward) {
|
if (forward) {
|
||||||
@ -271,7 +271,7 @@ fn void TextEdit.remove_word(&te, bool forward)
|
|||||||
fn void TextEdit.insert_character(&te, uint cp)
|
fn void TextEdit.insert_character(&te, uint cp)
|
||||||
{
|
{
|
||||||
char[4] b;
|
char[4] b;
|
||||||
usz len = conv::char32_to_utf8(cp, b[..])!!;
|
sz len = conv::char32_to_utf8(cp, b[..])!!;
|
||||||
te.insert_utf8((String)b[:len]);
|
te.insert_utf8((String)b[:len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,4 +285,4 @@ fn void TextEdit.insert_utf8(&te, String s)
|
|||||||
te.buffer[te.cursor : s.len] = s[..];
|
te.buffer[te.cursor : s.len] = s[..];
|
||||||
te.chars += s.len;
|
te.chars += s.len;
|
||||||
te.cursor += s.len;
|
te.cursor += s.len;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ struct ElemButton {
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.button(&ctx, String label = "", String icon = "", ...)
|
macro Ctx.button(&ctx, String label = "", String icon = "", ...)
|
||||||
=> ctx.button_id(@compute_id($vasplat), label, icon);
|
=> ctx.button_id(@compute_id(...$vaarg), label, icon);
|
||||||
fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -20,9 +20,9 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
Sprite* sprite = icon != "" ? ctx.sprite_atlas.get(icon)! : &&(Sprite){};
|
Sprite* sprite = icon != "" ? ctx.sprite_atlas.get(icon)! : &&(Sprite){};
|
||||||
Rect icon_size = sprite.rect();
|
Rect icon_size = sprite.rect();
|
||||||
|
|
||||||
ushort min_size = style.size;
|
short min_size = style.size;
|
||||||
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
short half_lh = (short)(ctx.font.line_height() / 2);
|
||||||
ushort inner_pad = label != "" && icon != "" ? half_lh : 0;
|
short inner_pad = label != "" && icon != "" ? half_lh : 0;
|
||||||
/*
|
/*
|
||||||
* +--------------------------------------+
|
* +--------------------------------------+
|
||||||
* | +--------+ |
|
* | +--------+ |
|
||||||
@ -85,7 +85,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.checkbox(&ctx, String desc, bool* active, String tick_sprite = "", ...)
|
macro Ctx.checkbox(&ctx, String desc, bool* active, String tick_sprite = "", ...)
|
||||||
=> ctx.checkbox_id(@compute_id($vasplat), desc, active, tick_sprite);
|
=> ctx.checkbox_id(@compute_id(...$vaarg), desc, active, tick_sprite);
|
||||||
fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String tick_sprite)
|
fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String tick_sprite)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -158,7 +158,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro Ctx.toggle(&ctx, String desc, bool* active)
|
macro Ctx.toggle(&ctx, String desc, bool* active)
|
||||||
=> ctx.toggle_id(@compute_id($vasplat), desc, active);
|
=> ctx.toggle_id(@compute_id(...$vaarg), desc, active);
|
||||||
fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
|
|||||||
@ -55,7 +55,7 @@ macro Ctx.@div(&ctx,
|
|||||||
@body()
|
@body()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize, $vasplat)!;
|
ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize, ...$vaarg)!;
|
||||||
@body();
|
@body();
|
||||||
return ctx.div_end()!;
|
return ctx.div_end()!;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ macro Ctx.div_begin(&ctx,
|
|||||||
...
|
...
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize);
|
return ctx.div_begin_id(@compute_id(...$vaarg), width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void? Ctx.div_begin_id(&ctx,
|
fn void? Ctx.div_begin_id(&ctx,
|
||||||
@ -269,7 +269,7 @@ macro bool? Ctx.popup_begin(&ctx, Point pos,
|
|||||||
bool scroll_x = false, bool scroll_y = false,
|
bool scroll_x = false, bool scroll_y = false,
|
||||||
...
|
...
|
||||||
)
|
)
|
||||||
=> ctx.popup_begin_id(@compute_id($vasplat), pos, width, height, dir, anchor, scroll_x, scroll_y);
|
=> ctx.popup_begin_id(@compute_id(...$vaarg), pos, width, height, dir, anchor, scroll_x, scroll_y);
|
||||||
fn bool? Ctx.popup_begin_id(&ctx,
|
fn bool? Ctx.popup_begin_id(&ctx,
|
||||||
Id id,
|
Id id,
|
||||||
Point pos,
|
Point pos,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ module ugui;
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.separator(&ctx, Size width, Size height, ...)
|
macro Ctx.separator(&ctx, Size width, Size height, ...)
|
||||||
=> ctx.separator_id(@compute_id($vasplat), width, height);
|
=> ctx.separator_id(@compute_id(...$vaarg), width, height);
|
||||||
fn void? Ctx.separator_id(&ctx, Id id, Size width, Size height)
|
fn void? Ctx.separator_id(&ctx, Id id, Size width, Size height)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -17,7 +17,7 @@ fn void? Ctx.separator_id(&ctx, Id id, Size width, Size height)
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.hor_line(&ctx, ...)
|
macro Ctx.hor_line(&ctx, ...)
|
||||||
=> ctx.hor_line_id(@compute_id($vasplat));
|
=> ctx.hor_line_id(@compute_id(...$vaarg));
|
||||||
fn void? Ctx.hor_line_id(&ctx, Id id)
|
fn void? Ctx.hor_line_id(&ctx, Id id)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -37,7 +37,7 @@ fn void? Ctx.hor_line_id(&ctx, Id id)
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.ver_line(&ctx, ...)
|
macro Ctx.ver_line(&ctx, ...)
|
||||||
=> ctx.ver_line_id(@compute_id($vasplat));
|
=> ctx.ver_line_id(@compute_id(...$vaarg));
|
||||||
fn void? Ctx.ver_line_id(&ctx, Id id)
|
fn void? Ctx.ver_line_id(&ctx, Id id)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -53,4 +53,4 @@ fn void? Ctx.ver_line_id(&ctx, Id id)
|
|||||||
|
|
||||||
Rect r = elem.bounds.pad(elem.layout.content_offset);
|
Rect r = elem.bounds.pad(elem.layout.content_offset);
|
||||||
ctx.push_rect(r, elem.z_index, style)!;
|
ctx.push_rect(r, elem.z_index, style)!;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct ElemSlider {
|
|||||||
* +----+-----+---------------------+
|
* +----+-----+---------------------+
|
||||||
*/
|
*/
|
||||||
macro Ctx.slider_hor(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
|
macro Ctx.slider_hor(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
|
||||||
=> ctx.slider_hor_id(@compute_id($vasplat), w, h, value, hpercent);
|
=> ctx.slider_hor_id(@compute_id(...$vaarg), w, h, value, hpercent);
|
||||||
<*
|
<*
|
||||||
@require value != null
|
@require value != null
|
||||||
*>
|
*>
|
||||||
@ -80,7 +80,7 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Size w, Size h, float* value, floa
|
|||||||
* +--+
|
* +--+
|
||||||
*/
|
*/
|
||||||
macro Ctx.slider_ver(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
|
macro Ctx.slider_ver(&ctx, Size w, Size h, float* value, float hpercent = 0.25, ...)
|
||||||
=> ctx.slider_ver_id(@compute_id($vasplat), w, h, value, hpercent);
|
=> ctx.slider_ver_id(@compute_id(...$vaarg), w, h, value, hpercent);
|
||||||
fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, float hpercent = 0.25)
|
fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, float hpercent = 0.25)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ struct ElemSprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro Ctx.sprite(&ctx, String name, short size = 0, ...)
|
macro Ctx.sprite(&ctx, String name, short size = 0, ...)
|
||||||
=> ctx.sprite_id(@compute_id($vasplat), name, size);
|
=> ctx.sprite_id(@compute_id(...$vaarg), name, size);
|
||||||
fn void? Ctx.sprite_id(&ctx, Id id, String name, short size = 0)
|
fn void? Ctx.sprite_id(&ctx, Id id, String name, short size = 0)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -17,8 +17,8 @@ fn void? Ctx.sprite_id(&ctx, Id id, String name, short size = 0)
|
|||||||
elem.sprite.id = ctx.get_sprite_atlas_id(name);
|
elem.sprite.id = ctx.get_sprite_atlas_id(name);
|
||||||
|
|
||||||
// scale the sprite so that the biggest dimension becomes "size"
|
// scale the sprite so that the biggest dimension becomes "size"
|
||||||
short width = sprite.w;
|
short width = (short)sprite.w;
|
||||||
short height = sprite.h;
|
short height = (short)sprite.h;
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
if (sprite.w >= sprite.h) {
|
if (sprite.w >= sprite.h) {
|
||||||
height = (short)(size * (float)height/width);
|
height = (short)(size * (float)height/width);
|
||||||
|
|||||||
@ -13,7 +13,7 @@ struct ElemText {
|
|||||||
* not a problem but it is in the situation where the text changes almost all frames.
|
* not a problem but it is in the situation where the text changes almost all frames.
|
||||||
*/
|
*/
|
||||||
macro Ctx.text(&ctx, String text, ...)
|
macro Ctx.text(&ctx, String text, ...)
|
||||||
=> ctx.text_id(@compute_id($vasplat), text);
|
=> ctx.text_id(@compute_id(...$vaarg), text);
|
||||||
fn void? Ctx.text_id(&ctx, Id id, String text)
|
fn void? Ctx.text_id(&ctx, Id id, String text)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -40,7 +40,7 @@ fn void? Ctx.text_id(&ctx, Id id, String text)
|
|||||||
|
|
||||||
|
|
||||||
macro Ctx.text_box(&ctx, Size w, Size h, TextEdit* te, Anchor text_alignment = TOP_LEFT, bool reflow = true, ...)
|
macro Ctx.text_box(&ctx, Size w, Size h, TextEdit* te, Anchor text_alignment = TOP_LEFT, bool reflow = true, ...)
|
||||||
=> ctx.text_box_id(@compute_id($vasplat), w, h, te, text_alignment, reflow);
|
=> ctx.text_box_id(@compute_id(...$vaarg), w, h, te, text_alignment, reflow);
|
||||||
fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor text_alignment, bool reflow)
|
fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor text_alignment, bool reflow)
|
||||||
{
|
{
|
||||||
id = ctx.gen_id(id)!;
|
id = ctx.gen_id(id)!;
|
||||||
@ -76,8 +76,8 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor
|
|||||||
ctx.push_rect(bg_bounds, parent.z_index, style)!;
|
ctx.push_rect(bg_bounds, parent.z_index, style)!;
|
||||||
String s = elem.text.te.to_string();
|
String s = elem.text.te.to_string();
|
||||||
if (te.sel_len) {
|
if (te.sel_len) {
|
||||||
usz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
sz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
||||||
usz end = (te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor) - 1;
|
sz end = (te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor) - 1;
|
||||||
ctx.draw_string_selection(s, text_bounds, text_alignment, start, end, parent.z_index, style.accent, reflow)!;
|
ctx.draw_string_selection(s, text_bounds, text_alignment, start, end, parent.z_index, style.accent, reflow)!;
|
||||||
}
|
}
|
||||||
ctx.layout_string(s, text_bounds, text_alignment, parent.z_index, style.fg, reflow)!;
|
ctx.layout_string(s, text_bounds, text_alignment, parent.z_index, style.fg, reflow)!;
|
||||||
@ -85,7 +85,7 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor
|
|||||||
// draw the cursor if the element has focus
|
// draw the cursor if the element has focus
|
||||||
if (elem.events.has_focus) {
|
if (elem.events.has_focus) {
|
||||||
if (elem.events.mouse_press || elem.events.mouse_hold) {
|
if (elem.events.mouse_press || elem.events.mouse_hold) {
|
||||||
usz cur = ctx.hit_test_string(s, text_bounds, text_alignment, ctx.input.mouse.pos, reflow)!;
|
sz cur = ctx.hit_test_string(s, text_bounds, text_alignment, ctx.input.mouse.pos, reflow)!;
|
||||||
bool select = (elem.events.mouse_hold && !elem.events.mouse_press) || (ctx.get_mod() & KMOD_SHIFT);
|
bool select = (elem.events.mouse_hold && !elem.events.mouse_press) || (ctx.get_mod() & KMOD_SHIFT);
|
||||||
te.set_cursor(cur, select);
|
te.set_cursor(cur, select);
|
||||||
}
|
}
|
||||||
@ -94,4 +94,4 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor
|
|||||||
ctx.push_rect(cur, parent.z_index, &&(Style){.bg = style.fg})!;
|
ctx.push_rect(cur, parent.z_index, &&(Style){.bg = style.fg})!;
|
||||||
}
|
}
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user