Compare commits
No commits in common. "1584b04fd31490967fd53c95af57b516e5e99cdc" and "14e0a6ad0a6103d2235d010ee110f001460f301c" have entirely different histories.
1584b04fd3
...
14e0a6ad0a
43
src/atlas.c3
43
src/atlas.c3
@ -4,9 +4,9 @@ import std::io;
|
||||
|
||||
faultdef CANNOT_PLACE, INVALID_TYPE;
|
||||
|
||||
enum AtlasType : (sz bpp, typeid underlying) {
|
||||
ATLAS_GRAYSCALE {1, char},
|
||||
ATLAS_R8G8B8A8 {4, uint},
|
||||
enum AtlasType {
|
||||
ATLAS_GRAYSCALE,
|
||||
ATLAS_R8G8B8A8,
|
||||
}
|
||||
|
||||
// black and white atlas
|
||||
@ -21,6 +21,23 @@ struct Atlas {
|
||||
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
|
||||
macro @pixel_convert(p, AtlasType $in, AtlasType $out)
|
||||
@ -35,10 +52,10 @@ macro @pixel_convert(p, AtlasType $in, AtlasType $out)
|
||||
var b = ((p >> 16) & 0xff);
|
||||
var a = ((p >> 24) & 0xff);
|
||||
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:
|
||||
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";
|
||||
$endswitch
|
||||
$endif
|
||||
@ -52,7 +69,7 @@ fn void? Atlas.new(&atlas, Id id, AtlasType type, ushort width, ushort height)
|
||||
atlas.width = width;
|
||||
atlas.height = height;
|
||||
|
||||
atlas.buffer = mem::new_array(char, (sz)atlas.width*atlas.height*type.bpp);
|
||||
atlas.buffer = mem::new_array(char, (usz)atlas.width*atlas.height*type.bpp());
|
||||
}
|
||||
|
||||
fn void Atlas.free(&atlas)
|
||||
@ -86,7 +103,7 @@ fn Point? Atlas.place(&atlas, char[] pixels, ushort w, ushort h, ushort stride)
|
||||
p = atlas.row;
|
||||
} else {
|
||||
atlas.row.x = 0;
|
||||
atlas.row.y = (short)atlas.row.y + (short)atlas.row_h;
|
||||
atlas.row.y = atlas.row.y + atlas.row_h;
|
||||
atlas.row_h = 0;
|
||||
if (atlas.row.x + w <= atlas.width && atlas.row.y + h <= atlas.height) {
|
||||
p = atlas.row;
|
||||
@ -95,17 +112,17 @@ fn Point? Atlas.place(&atlas, char[] pixels, ushort w, ushort h, ushort stride)
|
||||
}
|
||||
}
|
||||
|
||||
sz bpp = atlas.type.bpp;
|
||||
for (sz y = 0; y < h; y++) {
|
||||
for (sz x = 0; x < w; x++) {
|
||||
char[] buf = atlas.buffer[(sz)(p.y+y)*atlas.width*bpp + (p.x+x)*bpp ..];
|
||||
char[] pix = pixels[(sz)y*stride*bpp + x*bpp ..];
|
||||
usz bpp = atlas.type.bpp();
|
||||
for (usz y = 0; y < h; y++) {
|
||||
for (usz x = 0; x < w; x++) {
|
||||
char[] buf = atlas.buffer[(usz)(p.y+y)*atlas.width*bpp + (p.x+x)*bpp ..];
|
||||
char[] pix = pixels[(usz)y*stride*bpp + x*bpp ..];
|
||||
|
||||
buf[0..bpp-1] = pix[0..bpp-1];
|
||||
}
|
||||
}
|
||||
|
||||
atlas.row.x += (short)w;
|
||||
atlas.row.x += w;
|
||||
if (h > atlas.row_h) {
|
||||
atlas.row_h = h;
|
||||
}
|
||||
|
||||
24
src/cache.c3
24
src/cache.c3
@ -10,13 +10,13 @@ module cache<Key, Value, SIZE>;
|
||||
*/
|
||||
|
||||
import std::core::mem;
|
||||
import std::core::mem::alloc;
|
||||
import std::core::mem::allocator;
|
||||
import std::collections::bitset;
|
||||
import std::collections::map;
|
||||
|
||||
alias BitArr = bitset::BitSet{SIZE};
|
||||
alias IdTable = map::HashMap{Key, sz};
|
||||
alias IdTableEntry = map::Entry{Key, sz};
|
||||
alias IdTable = map::HashMap{Key, usz};
|
||||
alias IdTableEntry = map::Entry{Key, usz};
|
||||
|
||||
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
|
||||
foreach (idx, bit : cache.used) { cache.used[idx] = false; }
|
||||
foreach (idx, bit : cache.present) { cache.present[idx] = false; }
|
||||
cache.pool = alloc::new_array(allocator, Value, SIZE);
|
||||
cache.pool = allocator::new_array(allocator, Value, SIZE);
|
||||
}
|
||||
|
||||
fn void Cache.free(&cache)
|
||||
{
|
||||
(void)cache.table.free();
|
||||
(void)alloc::free(cache.allocator, cache.pool);
|
||||
(void)allocator::free(cache.allocator, cache.pool);
|
||||
}
|
||||
|
||||
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 */
|
||||
/* If there is no free space left then just return the first position */
|
||||
fn sz Cache.get_free_spot(&cache)
|
||||
fn usz Cache.get_free_spot(&cache)
|
||||
{
|
||||
const BITS = @bitsizeof(cache.present.data[0]);
|
||||
foreach (idx, d: cache.present.data) {
|
||||
if (d != $Typeof(d)::max) {
|
||||
sz spot = idx*BITS + BITS-d.clz();
|
||||
if (d != $typeof(d).max) {
|
||||
usz spot = idx*BITS + BITS-d.clz();
|
||||
if (cache.used[spot]) unreachable("free spot is not actually free: %d", spot);
|
||||
return spot;
|
||||
}
|
||||
@ -107,9 +107,9 @@ fn sz Cache.get_free_spot(&cache)
|
||||
return 0;
|
||||
}
|
||||
|
||||
<* @require g != null *>
|
||||
fn Value*? Cache.insert_at(&cache, Value* g, Key id, sz index)
|
||||
fn Value*? Cache.insert_at(&cache, Value* g, Key id, usz index)
|
||||
{
|
||||
// TODO: verify index, g and id
|
||||
Value* spot;
|
||||
|
||||
/* Set used and present */
|
||||
@ -124,14 +124,12 @@ fn Value*? Cache.insert_at(&cache, Value* g, Key id, sz index)
|
||||
}
|
||||
|
||||
// Insert an element in the cache, returns the index
|
||||
<* @require g != null *>
|
||||
fn Value*? Cache.insert_new(&cache, Value* g, Key id)
|
||||
{
|
||||
sz index = cache.get_free_spot();
|
||||
usz index = cache.get_free_spot();
|
||||
return cache.insert_at(g, id, index);
|
||||
}
|
||||
|
||||
<* @require g != null *>
|
||||
fn Value*? Cache.get_or_insert(&cache, Value* g, Key id, bool *is_new = null)
|
||||
{
|
||||
Value*? c = cache.search(id);
|
||||
|
||||
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)
|
||||
{
|
||||
CmdQueue stack;
|
||||
stack.init(tmem);
|
||||
stack.init(allocator::tmem);
|
||||
|
||||
for (sz i = queue.len()-1; i > 0; i--) {
|
||||
for (isz i = queue.len()-1; i > 0; i--) {
|
||||
Cmd cur = (*queue)[i];
|
||||
Cmd next = (*queue)[i - 1];
|
||||
// cur < next
|
||||
@ -82,17 +82,17 @@ fn void? CmdQueue.sort(&queue)
|
||||
}
|
||||
}
|
||||
|
||||
sz l = stack.len();
|
||||
for (sz i; i < l; i++) {
|
||||
usz l = stack.len();
|
||||
for (usz i; i < l; i++) {
|
||||
queue.push(stack.pop())!;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// implement the Printable interface
|
||||
fn sz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
||||
fn usz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
||||
{
|
||||
sz ret;
|
||||
usz ret;
|
||||
|
||||
ret += f.printf("Cmd{ type: %s, z_index: %d, ", cmd.type, cmd.z_index)!;
|
||||
switch (cmd.type) {
|
||||
@ -116,7 +116,7 @@ fn sz? Cmd.to_format(Cmd* cmd, Formatter *f) @dynamic
|
||||
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;
|
||||
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,
|
||||
.rect.rect = rect,
|
||||
.rect.color = border_color,
|
||||
.rect.radius = radius + (ushort)border.x,
|
||||
.rect.radius = radius + border.x,
|
||||
};
|
||||
ctx.push_cmd(cmd, z_index);
|
||||
}
|
||||
@ -204,13 +204,13 @@ fn void? Ctx.push_update_atlas(&ctx, Atlas* atlas)
|
||||
.update_atlas = {
|
||||
.id = atlas.id,
|
||||
.raw_buffer = atlas.buffer,
|
||||
.width = (short)atlas.width,
|
||||
.height = (short)atlas.height,
|
||||
.bpp = (short)atlas.type.bpp,
|
||||
.width = atlas.width,
|
||||
.height = atlas.height,
|
||||
.bpp = (ushort)atlas.type.bpp(),
|
||||
},
|
||||
};
|
||||
// update the atlases before everything else
|
||||
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 {
|
||||
char[TEXT_MAX] text;
|
||||
sz text_len;
|
||||
usz text_len;
|
||||
ModKeys modkeys;
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ fn Elem*? Ctx.get_parent(&ctx)
|
||||
return parent;
|
||||
}
|
||||
|
||||
macro @bits(#a) => $Typeof(#a)::size*8;
|
||||
macro @bits(#a) => $typeof(#a).sizeof*8;
|
||||
macro Id.rotate_left(id, uint $n) => (id << $n) | (id >> (@bits(id) - $n));
|
||||
const uint GOLDEN_RATIO = 0x9E3779B9;
|
||||
|
||||
@ -161,8 +161,8 @@ fn Id? Ctx.gen_id(&ctx, Id id2)
|
||||
macro Id @compute_id(...)
|
||||
{
|
||||
Id id = (Id)$$LINE.hash() ^ (Id)@str_hash($$FILE);
|
||||
$for var $i = 0; $i < $vaarg.len; $i++:
|
||||
id ^= (Id)$vaarg[$i].hash();
|
||||
$for var $i = 0; $i < $vacount; $i++:
|
||||
id ^= (Id)$vaexpr[$i].hash();
|
||||
$endfor
|
||||
return id;
|
||||
}
|
||||
@ -218,7 +218,7 @@ fn void? Ctx.init(&ctx, Allocator allocator)
|
||||
ctx.cache.init(allocator)!;
|
||||
defer catch { (void)ctx.cache.free(); }
|
||||
|
||||
ctx.cmd_queue.init(mem, MAX_COMMANDS);
|
||||
ctx.cmd_queue.init(allocator::mem, MAX_COMMANDS);
|
||||
defer catch { (void)ctx.cmd_queue.free(); }
|
||||
|
||||
ctx.styles.init(allocator);
|
||||
@ -254,14 +254,14 @@ fn void? Ctx.frame_begin(&ctx)
|
||||
// other stuff
|
||||
//elem.flags.has_focus = ctx.has_focus;
|
||||
|
||||
elem.bounds = {0, 0, (short)ctx.width, (short)ctx.height};
|
||||
elem.bounds = {0, 0, ctx.width, ctx.height};
|
||||
elem.z_index = 0;
|
||||
elem.div.scroll_x.enabled = false;
|
||||
elem.div.scroll_y.enabled = false;
|
||||
elem.layout.dir = ROW;
|
||||
elem.layout.anchor = TOP_LEFT;
|
||||
elem.layout.w = @exact((short)ctx.width);
|
||||
elem.layout.h = @exact((short)ctx.height);
|
||||
elem.layout.w = @exact(ctx.width);
|
||||
elem.layout.h = @exact(ctx.height);
|
||||
|
||||
ctx.div_scissor = elem.bounds;
|
||||
|
||||
@ -331,7 +331,7 @@ $if $feature(DEBUG_POINTER):
|
||||
// draw mouse position
|
||||
Cmd cmd = {
|
||||
.type = CMD_RECT,
|
||||
.z_index = int::max-1, // hopefully over everything else
|
||||
.z_index = int.max-1, // hopefully over everything else
|
||||
.rect.rect = {
|
||||
.x = ctx.input.mouse.pos.x - 2,
|
||||
.y = ctx.input.mouse.pos.y - 2,
|
||||
|
||||
18
src/font.c3
18
src/font.c3
@ -5,7 +5,7 @@ import std::collections::map;
|
||||
import std::core::mem;
|
||||
import std::core::mem::allocator;
|
||||
import std::io;
|
||||
import std::core::ascii;
|
||||
import std::ascii;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------- //
|
||||
@ -65,8 +65,8 @@ struct Font {
|
||||
bool should_update; // should send update_atlas command, resets at frame_end()
|
||||
}
|
||||
|
||||
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 = (short)g.u, .y = (short)g.v, .w = (short)g.w, .h = (short)g.h};
|
||||
macro Rect Glyph.bounds(&g) => {.x = g.ox, .y = g.oy, .w = g.w, .h = g.h};
|
||||
macro Rect Glyph.uv(&g) => {.x = g.u, .y = g.v, .w = g.w, .h = g.h};
|
||||
|
||||
<*
|
||||
@param [&inout] font
|
||||
@ -100,6 +100,8 @@ fn void? Font.load(&font, Allocator allocator, String name, ZString path, uint h
|
||||
font.linegap = (float)lmetrics.lineGap;
|
||||
//io::printfn("ascender:%d, descender:%d, linegap:%d", font.ascender, font.descender, font.linegap);
|
||||
|
||||
// TODO: allocate buffer based on FONT_CACHED and the size of a sample letter
|
||||
// like the letter 'A'
|
||||
ushort size = (ushort)font.size*(ushort)($$sqrt((float)FONT_CACHED));
|
||||
font.atlas.new(font.id, ATLAS_GRAYSCALE, size, size)!;
|
||||
|
||||
@ -145,7 +147,7 @@ fn Glyph*? Font.get_glyph(&font, Codepoint code)
|
||||
.width = gmtx.minWidth,
|
||||
.height = gmtx.minHeight,
|
||||
};
|
||||
char[] pixels = mem::new_array(char, (usz)img.width * (usz)img.height);
|
||||
char[] pixels = mem::new_array(char, (usz)img.width * img.height);
|
||||
img.pixels = pixels;
|
||||
if (schrift::render(&font.sft, gid, img) < 0) {
|
||||
return RENDER_ERROR~;
|
||||
@ -161,8 +163,8 @@ fn Glyph*? Font.get_glyph(&font, Codepoint code)
|
||||
// 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)!;
|
||||
glyph.u = (ushort)uv.x;
|
||||
glyph.v = (ushort)uv.y;
|
||||
glyph.u = uv.x;
|
||||
glyph.v = uv.y;
|
||||
|
||||
mem::free(pixels);
|
||||
|
||||
@ -203,10 +205,9 @@ fn void? Ctx.load_font(&ctx, Allocator allocator, String name, ZString path, uin
|
||||
<*
|
||||
@param [&in] ctx
|
||||
@param [in] label
|
||||
@require ctx.font.id != 0 : "font not loaded"
|
||||
*>
|
||||
// TODO: check if the font is present in the context
|
||||
fn Id Ctx.get_font_id(&ctx, String label) => (Id)ctx.font.id;
|
||||
fn Id Ctx.get_font_id(&ctx, String label) => (Id)label.hash();
|
||||
|
||||
<*
|
||||
@param [&in] ctx
|
||||
@ -214,6 +215,7 @@ fn Id Ctx.get_font_id(&ctx, String label) => (Id)ctx.font.id;
|
||||
*>
|
||||
fn Atlas*? Ctx.get_font_atlas(&ctx, String name)
|
||||
{
|
||||
// TODO: use the font name, for now there is only one font
|
||||
if (name.hash() != ctx.font.id) {
|
||||
return WRONG_ID~;
|
||||
}
|
||||
|
||||
31
src/input.c3
31
src/input.c3
@ -59,20 +59,17 @@ const ModKeys KMOD_ALT = {.lalt = true, .ralt = 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_NONE = {};
|
||||
const ModKeys KMOD_ANY = (ModKeys)(uint::max);
|
||||
//const ModKeys KMOD_ANY = (ModKeys)(ModKeys::inner::max);
|
||||
const ModKeys KMOD_ANY = (ModKeys)(ModKeys.inner.max);
|
||||
|
||||
const MouseButtons BTN_NONE = {};
|
||||
const MouseButtons BTN_ANY = (MouseButtons)(uint::max);
|
||||
//const MouseButtons BTN_ANY = (MouseButtons)(MouseButtons::max);
|
||||
const MouseButtons BTN_ANY = (MouseButtons)(MouseButtons.inner.max);
|
||||
const MouseButtons BTN_LEFT = {.btn_left = true};
|
||||
const MouseButtons BTN_MIDDLE = {.btn_middle = true};
|
||||
const MouseButtons BTN_RIGHT = {.btn_right = true};
|
||||
const MouseButtons BTN_4 = {.btn_4 = true};
|
||||
const MouseButtons BTN_5 = {.btn_5 = true};
|
||||
|
||||
const ModKeys KEY_ANY = (ModKeys)(uint::max);
|
||||
//const ModKeys KEY_ANY = (ModKeys)(ModKeys::max);
|
||||
const ModKeys KEY_ANY = (ModKeys)(ModKeys.inner.max);
|
||||
|
||||
<* @param [&inout] ctx *>
|
||||
fn bool Ctx.check_key_combo(&ctx, ModKeys mod, String ...keys)
|
||||
@ -93,9 +90,9 @@ fn void? Ctx.input_window_size(&ctx, short width, short height)
|
||||
if (width <= 0 || height <= 0) {
|
||||
return INVALID_SIZE~;
|
||||
}
|
||||
ctx.current_input.events.resize = ctx.width != (ushort)width || ctx.height != (ushort)height;
|
||||
ctx.width = (ushort)width;
|
||||
ctx.height = (ushort)height;
|
||||
ctx.current_input.events.resize = ctx.width != width || ctx.height != height;
|
||||
ctx.width = width;
|
||||
ctx.height = height;
|
||||
if (ctx.current_input.events.resize) ctx.skip_frame = true;
|
||||
}
|
||||
|
||||
@ -130,8 +127,8 @@ fn void Ctx.input_mouse_button(&ctx, MouseButtons buttons)
|
||||
<* @param [&inout] ctx *>
|
||||
fn void Ctx.input_mouse_abs(&ctx, short x, short y)
|
||||
{
|
||||
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, (short)ctx.height);
|
||||
ctx.current_input.mouse.pos.x = math::clamp(x, (short)0, ctx.width);
|
||||
ctx.current_input.mouse.pos.y = math::clamp(y, (short)0, ctx.height);
|
||||
|
||||
short dx, dy;
|
||||
dx = x - ctx.current_input.mouse.pos.x;
|
||||
@ -154,8 +151,8 @@ fn void Ctx.input_mouse_delta(&ctx, short dx, short dy)
|
||||
mx = ctx.current_input.mouse.pos.x + dx;
|
||||
my = ctx.current_input.mouse.pos.y + dy;
|
||||
|
||||
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, (short)ctx.height);
|
||||
ctx.current_input.mouse.pos.x = math::clamp(mx, (short)0, ctx.width);
|
||||
ctx.current_input.mouse.pos.y = math::clamp(my, (short)0, ctx.height);
|
||||
|
||||
ctx.current_input.events.mouse_move = dx != 0 || dy != 0;
|
||||
}
|
||||
@ -192,8 +189,8 @@ fn void Ctx.input_text_utf8(&ctx, char[] text)
|
||||
{
|
||||
if (text == "") return;
|
||||
|
||||
sz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
||||
sz len = text.len > remaining ? remaining : text.len;
|
||||
usz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
||||
usz len = text.len > remaining ? remaining : text.len;
|
||||
char[] s = ctx.current_input.keyboard.text[ctx.current_input.keyboard.text_len ..];
|
||||
s[..len-1] = text[..len-1];
|
||||
ctx.current_input.keyboard.text_len += len;
|
||||
@ -208,10 +205,10 @@ fn void? Ctx.input_text_unicode(&ctx, uint[] text)
|
||||
{
|
||||
if (text.len == 0) return;
|
||||
|
||||
sz remaining = ctx.current_input.keyboard.text.len - ctx.current_input.keyboard.text_len;
|
||||
usz 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 ..];
|
||||
|
||||
sz off = conv::utf32to8(text, s)!;
|
||||
usz off = conv::utf32to8(text, s)!;
|
||||
ctx.current_input.keyboard.text_len += off;
|
||||
|
||||
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::alloc;
|
||||
import std::core::mem::allocator;
|
||||
import std::io;
|
||||
import std::bits;
|
||||
import std::collections::list;
|
||||
|
||||
|
||||
alias Bitmap = ulong;
|
||||
const BITS = Bitmap::size*8;
|
||||
const BITS = Bitmap.sizeof*8;
|
||||
|
||||
alias IdxList = List{int};
|
||||
|
||||
@ -96,10 +96,10 @@ fn void MTree.init(&tree, usz size, Allocator allocator = mem)
|
||||
|
||||
tree.elements = 0;
|
||||
tree.allocator = allocator;
|
||||
tree.queue.init(tree.allocator, (sz)size);
|
||||
tree.used = alloc::new_array(tree.allocator, Bitmap, (sz)size/BITS);
|
||||
tree.elem_vec = alloc::new_array(tree.allocator, Type, (sz)size);
|
||||
tree.refs_vec = alloc::new_array(tree.allocator, RefNode, (sz)size);
|
||||
tree.queue.init(tree.allocator, size);
|
||||
tree.used = allocator::new_array(tree.allocator, Bitmap, size/BITS);
|
||||
tree.elem_vec = allocator::new_array(tree.allocator, Type, size);
|
||||
tree.refs_vec = allocator::new_array(tree.allocator, RefNode, size);
|
||||
|
||||
foreach (&r: tree.refs_vec) {
|
||||
r.next = -1;
|
||||
@ -112,9 +112,9 @@ fn void MTree.free(&tree)
|
||||
{
|
||||
tree.elements = 0;
|
||||
tree.queue.free();
|
||||
(void)alloc::free(tree.allocator, tree.used);
|
||||
(void)alloc::free(tree.allocator, tree.elem_vec);
|
||||
(void)alloc::free(tree.allocator, tree.refs_vec);
|
||||
(void)allocator::free(tree.allocator, tree.used);
|
||||
(void)allocator::free(tree.allocator, tree.elem_vec);
|
||||
(void)allocator::free(tree.allocator, tree.refs_vec);
|
||||
}
|
||||
|
||||
|
||||
@ -122,7 +122,7 @@ fn void MTree.free(&tree)
|
||||
fn int? MTree.get_free_spot(&tree)
|
||||
{
|
||||
foreach (idx, d: tree.used) {
|
||||
if (d != $Typeof(d)::max) {
|
||||
if (d != $typeof(d).max) {
|
||||
int spot = (int)idx*BITS + BITS-(int)d.clz();
|
||||
return spot;
|
||||
}
|
||||
@ -334,7 +334,7 @@ fn Type? MTree.get(&tree, int ref) @operator([])
|
||||
}
|
||||
|
||||
<* @param [&in] tree *>
|
||||
fn int? MTree.parentof(&tree, int ref)
|
||||
fn Type? MTree.parentof(&tree, int ref)
|
||||
{
|
||||
if (!tree.is_used(ref)) return NOT_FOUND~;
|
||||
return tree.refs_vec[ref].parent;
|
||||
|
||||
@ -11,7 +11,7 @@ struct Rect {
|
||||
}
|
||||
|
||||
// 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
|
||||
macro bool Rect.contains(Rect a, Rect b)
|
||||
@ -250,7 +250,7 @@ struct Size {
|
||||
|
||||
macro Size @grow() => {.min = 0, .max = 0};
|
||||
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_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.atlas.new(this.id, AtlasType.ATLAS_R8G8B8A8, width, height)!;
|
||||
this.sprites.init(mem, capacity: SRITES_PER_ATLAS);
|
||||
this.sprites.init(allocator::mem, capacity: SRITES_PER_ATLAS);
|
||||
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)!;
|
||||
s.w = w;
|
||||
s.h = h;
|
||||
s.u = (ushort)uv.x;
|
||||
s.v = (ushort)uv.y;
|
||||
s.u = uv.x;
|
||||
s.v = uv.y;
|
||||
this.sprites.set(s.id, s);
|
||||
this.should_update = true;
|
||||
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);
|
||||
}
|
||||
|
||||
macro Rect Sprite.rect(s) => {0, 0, (short)s.w, (short)s.h};
|
||||
macro Rect Sprite.uv(s) => {(short)s.u, (short)s.v, (short)s.w, (short)s.h};
|
||||
macro Rect Sprite.rect(s) => {0,0,s.w,s.h};
|
||||
macro Rect Sprite.uv(s) => {s.u,s.v,s.w,s.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;
|
||||
|
||||
char[] pixels = qoi::read(mem, path, &desc, QOIChannels.RGBA)!;
|
||||
char[] pixels = qoi::read(allocator::mem, path, &desc, QOIChannels.RGBA)!;
|
||||
defer mem::free(pixels);
|
||||
|
||||
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;
|
||||
|
||||
struct LineInfo @local {
|
||||
sz start, end;
|
||||
usz start, end;
|
||||
short width, height;
|
||||
short first_off; // first character offset
|
||||
}
|
||||
|
||||
macro sz LineInfo.len(li) => li.end-li.start;
|
||||
macro usz LineInfo.len(li) => li.end-li.start;
|
||||
|
||||
alias LineStack @local = list::List{LineInfo};
|
||||
|
||||
@ -74,7 +74,7 @@ struct GlyphIterator {
|
||||
Font* font;
|
||||
|
||||
LineStack lines;
|
||||
sz line_off, line_idx;
|
||||
usz line_off, line_idx;
|
||||
String text;
|
||||
|
||||
Codepoint cp;
|
||||
@ -123,15 +123,15 @@ fn void? GlyphIterator.init(&self, Allocator allocator, String text, Rect bounds
|
||||
|
||||
fn void? GlyphIterator.populate_lines_stack(&self)
|
||||
{
|
||||
sz line_start;
|
||||
usz line_start;
|
||||
LineInfo li;
|
||||
Point o = self.o;
|
||||
StringIterator ti = self.text.iterator();
|
||||
|
||||
sz prev_off;
|
||||
usz prev_off;
|
||||
for (Codepoint cp; ti.has_next();) {
|
||||
cp = ti.next()!;
|
||||
sz off = ti.current;
|
||||
usz off = ti.current;
|
||||
bool push = false;
|
||||
|
||||
li.height = self.line_height;
|
||||
@ -233,7 +233,7 @@ fn Rect? GlyphIterator.next(&self)
|
||||
t = self.text[self.line_off..];
|
||||
}
|
||||
|
||||
sz read = t.len < 4 ? t.len : 4;
|
||||
usz read = t.len < 4 ? t.len : 4;
|
||||
self.cp = conv::utf8_to_char32(&t[0], &read)!;
|
||||
self.line_off += read;
|
||||
self.gp = self.font.get_glyph(self.cp)!;
|
||||
@ -292,7 +292,7 @@ fn bool GlyphIterator.has_next(&self)
|
||||
return true;
|
||||
}
|
||||
|
||||
fn sz GlyphIterator.current_offset(&self)
|
||||
fn usz GlyphIterator.current_offset(&self)
|
||||
{
|
||||
if (self.anchor == TOP_LEFT) return 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, sz cursor, bool reflow = false)
|
||||
fn Rect? Ctx.get_cursor_position(&ctx, String text, Rect bounds, Anchor anchor, usz cursor, bool reflow = false)
|
||||
{
|
||||
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] text
|
||||
*>
|
||||
fn sz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point p, bool reflow = false)
|
||||
fn usz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point p, bool reflow = false)
|
||||
{
|
||||
if (text == "") return 0;
|
||||
if (bounds.w <= 0 || bounds.h <= 0) return 0;
|
||||
@ -382,12 +382,12 @@ fn sz? Ctx.hit_test_string(&ctx, String text, Rect bounds, Anchor anchor, Point
|
||||
GlyphIterator gi;
|
||||
gi.init(tmem, text, bounds, font, anchor, reflow, TAB_SIZE)!;
|
||||
|
||||
sz prev_offset = 0;
|
||||
usz prev_offset = 0;
|
||||
Point prev_o = gi.o;
|
||||
|
||||
while (gi.has_next()) {
|
||||
Point o_before = gi.o;
|
||||
sz offset_before = gi.current_offset();
|
||||
usz offset_before = gi.current_offset();
|
||||
Rect b = gi.next()!;
|
||||
|
||||
switch {
|
||||
@ -443,7 +443,7 @@ fn sz? 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
|
||||
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)
|
||||
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)
|
||||
{
|
||||
if (text == "") 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
|
||||
if (start > end) {
|
||||
sz temp = start;
|
||||
usz temp = start;
|
||||
start = end;
|
||||
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)!;
|
||||
|
||||
Rect sel_rect = { .h = gi.line_height }; // selection rect
|
||||
sz sel_line = -1; // selection line
|
||||
isz sel_line = -1; // selection line
|
||||
while (gi.has_next()) {
|
||||
Rect b = gi.next()!;
|
||||
sz off = gi.current_offset()-1;
|
||||
sz line = gi.line_idx;
|
||||
usz off = gi.current_offset()-1;
|
||||
isz line = gi.line_idx;
|
||||
bool in_selection = start <= off && off <= end;
|
||||
|
||||
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_gap = (short)font.linegap;
|
||||
short space_width = font.get_glyph(' ').adv!;
|
||||
short tab_width = (usz)space_width * TAB_SIZE;
|
||||
short tab_width = space_width * TAB_SIZE;
|
||||
|
||||
sz off;
|
||||
isz off;
|
||||
usz x;
|
||||
|
||||
TextSize ts;
|
||||
@ -566,7 +566,7 @@ fn TextSize? Ctx.measure_string(&ctx, String text)
|
||||
if (off < text.len) {
|
||||
word_width += gp.adv;
|
||||
} else {
|
||||
word_width += (short)gp.w + (short)gp.ox;
|
||||
word_width += gp.w + 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)
|
||||
{
|
||||
char[] text;
|
||||
sz size = file::get_size(path)!!;
|
||||
usz size = file::get_size(path)!!;
|
||||
text = mem::new_array(char, size);
|
||||
file::load_buffer(path, text)!!;
|
||||
defer mem::free(text);
|
||||
@ -109,7 +109,7 @@ fn int Ctx.import_style_from_file(&ctx, String path)
|
||||
|
||||
module ugui::css;
|
||||
|
||||
import std::core::ascii;
|
||||
import std::ascii;
|
||||
import std::io;
|
||||
|
||||
// CSS parser module
|
||||
@ -194,14 +194,14 @@ fn Token Lexer.next_token(&lex)
|
||||
}
|
||||
|
||||
// skip whitespace
|
||||
while (ascii::is_space(lex.peep())) {
|
||||
while (ascii::is_space_m(lex.peep())) {
|
||||
if (lex.advance() == 0) return {.type = EOF};
|
||||
if (lex.off >= lex.text.len) return {.type = EOF};
|
||||
}
|
||||
t.off = lex.off;
|
||||
|
||||
switch (true) {
|
||||
case ascii::is_punct(lex.peep()) && lex.peep() != '#': // punctuation
|
||||
case ascii::is_punct_m(lex.peep()) && lex.peep() != '#': // punctuation
|
||||
t.text = lex.text[lex.off:1];
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
switch (t.text[0]) {
|
||||
@ -216,7 +216,7 @@ fn Token Lexer.next_token(&lex)
|
||||
t.type = COLOR;
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
usz hex_start = t.off+1;
|
||||
while (ascii::is_alnum(lex.peep())) {
|
||||
while (ascii::is_alnum_m(lex.peep())) {
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
}
|
||||
usz h_len = lex.off - hex_start;
|
||||
@ -236,19 +236,19 @@ fn Token Lexer.next_token(&lex)
|
||||
}
|
||||
t.color = color_hex.to_rgba();
|
||||
|
||||
case ascii::is_alpha(lex.peep()): // identifier
|
||||
case ascii::is_alpha_m(lex.peep()): // identifier
|
||||
t.type = IDENTIFIER;
|
||||
while (ascii::is_alnum(lex.peep()) || lex.peep() == '-' || lex.peep() == '_') {
|
||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '-' || lex.peep() == '_') {
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
}
|
||||
t.text = lex.text[t.off..lex.off-1];
|
||||
|
||||
case ascii::is_digit(lex.peep()): // number
|
||||
case ascii::is_digit_m(lex.peep()): // number
|
||||
t.type = NUMBER;
|
||||
t.unit = PIXELS;
|
||||
// find the end of the number
|
||||
usz end;
|
||||
while (ascii::is_alnum(lex.peep()) || lex.peep() == '+' || lex.peep() == '-' || lex.peep() == '.') {
|
||||
while (ascii::is_alnum_m(lex.peep()) || lex.peep() == '+' || lex.peep() == '-' || lex.peep() == '.') {
|
||||
if (lex.advance() == 0) { t.type = INVALID; break; }
|
||||
}
|
||||
end = lex.off;
|
||||
|
||||
@ -4,16 +4,16 @@ import ugui::textedit::te;
|
||||
|
||||
struct TextEdit {
|
||||
char[] buffer;
|
||||
sz chars;
|
||||
sz cursor;
|
||||
sz sel_len;
|
||||
usz chars;
|
||||
usz cursor;
|
||||
isz sel_len;
|
||||
}
|
||||
|
||||
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.from_cursor(&te) => (String)te.buffer[te.cursor..te.chars];
|
||||
fn String TextEdit.until(&te, sz off) => (String)te.buffer[..min(te.chars, off)];
|
||||
fn String TextEdit.from(&te, sz off) => (String)te.buffer[off..te.chars];
|
||||
fn String TextEdit.until(&te, usz off) => (String)te.buffer[..min(te.chars, off)];
|
||||
fn String TextEdit.from(&te, usz off) => (String)te.buffer[off..te.chars];
|
||||
|
||||
// implement text editing operations on the buffer
|
||||
// returns true if the buffer is full
|
||||
@ -75,26 +75,26 @@ fn bool Ctx.text_edit(&ctx, TextEdit* te)
|
||||
module ugui::textedit::te;
|
||||
|
||||
import std::core::string;
|
||||
import std::core::ascii;
|
||||
import std::ascii;
|
||||
import std::collections::pair;
|
||||
|
||||
alias OffPair = pair::Pair{sz, sz};
|
||||
alias OffPair = pair::Pair{usz, usz};
|
||||
|
||||
// returns the offset of the next codepoint in the buffer from the cursor
|
||||
fn sz TextEdit.next_char_off(&te)
|
||||
fn usz TextEdit.next_char_off(&te)
|
||||
{
|
||||
sz len = min(te.chars - te.cursor, 4);
|
||||
usz len = min(te.chars - te.cursor, 4);
|
||||
if (len == 0) return len;
|
||||
conv::utf8_to_char32(&te.buffer[te.cursor], &len)!!;
|
||||
return len;
|
||||
}
|
||||
|
||||
// returns the offset of the previous codepoint in the buffer from the cursor
|
||||
fn sz TextEdit.prev_char_off(&te)
|
||||
fn usz TextEdit.prev_char_off(&te)
|
||||
{
|
||||
if (te.cursor == 0) return 0;
|
||||
String b = (String)te.buffer[..te.cursor];
|
||||
sz len;
|
||||
usz len;
|
||||
foreach_r (off, c: b) {
|
||||
if (c & 0xC0 == 0x80) continue;
|
||||
len = b.len - off;
|
||||
@ -123,7 +123,7 @@ fn void TextEdit.move_cursor(&te, bool forward, bool select)
|
||||
te.sel_len = 0;
|
||||
|
||||
} else {
|
||||
sz off = forward ? te.next_char_off() : -te.prev_char_off();
|
||||
isz off = forward ? te.next_char_off() : -te.prev_char_off();
|
||||
if (te.cursor + off < 0 || te.cursor + off > te.chars) return;
|
||||
te.cursor += off;
|
||||
// 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
|
||||
// expanded or rese
|
||||
fn void TextEdit.set_cursor(&te, sz cur, bool select)
|
||||
fn void TextEdit.set_cursor(&te, usz cur, bool select)
|
||||
{
|
||||
if (!select) te.sel_len = 0;
|
||||
if (cur == te.cursor) return;
|
||||
|
||||
sz prev_cur = te.cursor;
|
||||
usz prev_cur = te.cursor;
|
||||
te.cursor = cur;
|
||||
if (select) {
|
||||
te.sel_len += prev_cur - cur;
|
||||
@ -155,7 +155,7 @@ fn void TextEdit.move_cursor_word(&te, bool forward, bool select)
|
||||
return;
|
||||
}
|
||||
|
||||
sz prev_cur = te.cursor;
|
||||
usz prev_cur = te.cursor;
|
||||
while (te.cursor <= te.chars) {
|
||||
char c;
|
||||
if (forward) {
|
||||
@ -203,9 +203,9 @@ fn void TextEdit.delete_selection(&te)
|
||||
{
|
||||
if (te.sel_len == 0) return;
|
||||
|
||||
sz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
||||
sz end = te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor;
|
||||
sz len = te.chars - end;
|
||||
usz 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;
|
||||
usz len = te.chars - end;
|
||||
|
||||
te.buffer[start:len] = te.buffer[end:len];
|
||||
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 (forward) {
|
||||
sz rem = te.chars - te.cursor;
|
||||
usz rem = te.chars - te.cursor;
|
||||
if (rem > 0) {
|
||||
sz len = te.next_char_off();
|
||||
usz len = te.next_char_off();
|
||||
te.buffer[te.cursor:rem-len] = te.buffer[te.cursor+len:rem-len];
|
||||
te.chars -= len;
|
||||
}
|
||||
} else {
|
||||
if (te.cursor > 0) {
|
||||
sz len = te.prev_char_off();
|
||||
usz len = te.prev_char_off();
|
||||
te.buffer[te.cursor-len:te.chars-te.cursor] = te.buffer[te.cursor:te.chars-te.cursor];
|
||||
te.chars -= len;
|
||||
te.cursor -= len;
|
||||
@ -249,7 +249,7 @@ fn void TextEdit.remove_word(&te, bool forward)
|
||||
return;
|
||||
}
|
||||
|
||||
sz prev_cur = te.cursor;
|
||||
usz prev_cur = te.cursor;
|
||||
while (te.chars > 0) {
|
||||
char c;
|
||||
if (forward) {
|
||||
@ -271,7 +271,7 @@ fn void TextEdit.remove_word(&te, bool forward)
|
||||
fn void TextEdit.insert_character(&te, uint cp)
|
||||
{
|
||||
char[4] b;
|
||||
sz len = conv::char32_to_utf8(cp, b[..])!!;
|
||||
usz len = conv::char32_to_utf8(cp, b[..])!!;
|
||||
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.chars += s.len;
|
||||
te.cursor += s.len;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ struct ElemButton {
|
||||
|
||||
|
||||
macro Ctx.button(&ctx, String label = "", String icon = "", ...)
|
||||
=> ctx.button_id(@compute_id(...$vaarg), label, icon);
|
||||
=> ctx.button_id(@compute_id($vasplat), label, icon);
|
||||
fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
{
|
||||
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){};
|
||||
Rect icon_size = sprite.rect();
|
||||
|
||||
short min_size = style.size;
|
||||
short half_lh = (short)(ctx.font.line_height() / 2);
|
||||
short inner_pad = label != "" && icon != "" ? half_lh : 0;
|
||||
ushort min_size = style.size;
|
||||
ushort half_lh = (ushort)(ctx.font.line_height() / 2);
|
||||
ushort 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 = "", ...)
|
||||
=> ctx.checkbox_id(@compute_id(...$vaarg), desc, active, tick_sprite);
|
||||
=> ctx.checkbox_id(@compute_id($vasplat), desc, active, tick_sprite);
|
||||
fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String tick_sprite)
|
||||
{
|
||||
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)
|
||||
=> ctx.toggle_id(@compute_id(...$vaarg), desc, active);
|
||||
=> ctx.toggle_id(@compute_id($vasplat), desc, active);
|
||||
fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
||||
{
|
||||
id = ctx.gen_id(id)!;
|
||||
|
||||
@ -55,7 +55,7 @@ macro Ctx.@div(&ctx,
|
||||
@body()
|
||||
)
|
||||
{
|
||||
ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize, ...$vaarg)!;
|
||||
ctx.div_begin(width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize, $vasplat)!;
|
||||
@body();
|
||||
return ctx.div_end()!;
|
||||
}
|
||||
@ -69,7 +69,7 @@ macro Ctx.div_begin(&ctx,
|
||||
...
|
||||
)
|
||||
{
|
||||
return ctx.div_begin_id(@compute_id(...$vaarg), width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize);
|
||||
return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, absolute, off, scroll_x, scroll_y, resize);
|
||||
}
|
||||
|
||||
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,
|
||||
...
|
||||
)
|
||||
=> ctx.popup_begin_id(@compute_id(...$vaarg), pos, width, height, dir, anchor, scroll_x, scroll_y);
|
||||
=> ctx.popup_begin_id(@compute_id($vasplat), pos, width, height, dir, anchor, scroll_x, scroll_y);
|
||||
fn bool? Ctx.popup_begin_id(&ctx,
|
||||
Id id,
|
||||
Point pos,
|
||||
|
||||
@ -2,7 +2,7 @@ module ugui;
|
||||
|
||||
|
||||
macro Ctx.separator(&ctx, Size width, Size height, ...)
|
||||
=> ctx.separator_id(@compute_id(...$vaarg), width, height);
|
||||
=> ctx.separator_id(@compute_id($vasplat), width, height);
|
||||
fn void? Ctx.separator_id(&ctx, Id id, Size width, Size height)
|
||||
{
|
||||
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, ...)
|
||||
=> ctx.hor_line_id(@compute_id(...$vaarg));
|
||||
=> ctx.hor_line_id(@compute_id($vasplat));
|
||||
fn void? Ctx.hor_line_id(&ctx, 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, ...)
|
||||
=> ctx.ver_line_id(@compute_id(...$vaarg));
|
||||
=> ctx.ver_line_id(@compute_id($vasplat));
|
||||
fn void? Ctx.ver_line_id(&ctx, 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);
|
||||
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, ...)
|
||||
=> ctx.slider_hor_id(@compute_id(...$vaarg), w, h, value, hpercent);
|
||||
=> ctx.slider_hor_id(@compute_id($vasplat), w, h, value, hpercent);
|
||||
<*
|
||||
@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, ...)
|
||||
=> ctx.slider_ver_id(@compute_id(...$vaarg), w, h, value, hpercent);
|
||||
=> ctx.slider_ver_id(@compute_id($vasplat), w, h, value, hpercent);
|
||||
fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, float hpercent = 0.25)
|
||||
{
|
||||
id = ctx.gen_id(id)!;
|
||||
|
||||
@ -5,7 +5,7 @@ struct ElemSprite {
|
||||
}
|
||||
|
||||
macro Ctx.sprite(&ctx, String name, short size = 0, ...)
|
||||
=> ctx.sprite_id(@compute_id(...$vaarg), name, size);
|
||||
=> ctx.sprite_id(@compute_id($vasplat), name, size);
|
||||
fn void? Ctx.sprite_id(&ctx, Id id, String name, short size = 0)
|
||||
{
|
||||
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);
|
||||
|
||||
// scale the sprite so that the biggest dimension becomes "size"
|
||||
short width = (short)sprite.w;
|
||||
short height = (short)sprite.h;
|
||||
short width = sprite.w;
|
||||
short height = sprite.h;
|
||||
if (size > 0) {
|
||||
if (sprite.w >= sprite.h) {
|
||||
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.
|
||||
*/
|
||||
macro Ctx.text(&ctx, String text, ...)
|
||||
=> ctx.text_id(@compute_id(...$vaarg), text);
|
||||
=> ctx.text_id(@compute_id($vasplat), text);
|
||||
fn void? Ctx.text_id(&ctx, Id id, String text)
|
||||
{
|
||||
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, ...)
|
||||
=> ctx.text_box_id(@compute_id(...$vaarg), w, h, te, text_alignment, reflow);
|
||||
=> ctx.text_box_id(@compute_id($vasplat), 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)
|
||||
{
|
||||
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)!;
|
||||
String s = elem.text.te.to_string();
|
||||
if (te.sel_len) {
|
||||
sz start = te.sel_len > 0 ? te.cursor : te.cursor + te.sel_len;
|
||||
sz end = (te.sel_len > 0 ? te.cursor + te.sel_len : te.cursor) - 1;
|
||||
usz 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;
|
||||
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)!;
|
||||
@ -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
|
||||
if (elem.events.has_focus) {
|
||||
if (elem.events.mouse_press || elem.events.mouse_hold) {
|
||||
sz cur = ctx.hit_test_string(s, text_bounds, text_alignment, ctx.input.mouse.pos, reflow)!;
|
||||
usz 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);
|
||||
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})!;
|
||||
}
|
||||
return elem.events;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user