don't hardcode stuff with rendering (sorta), actually use ui flags
							parent
							
								
									e941db978c
								
							
						
					
					
						commit
						2ffbc3a65e
					
				| 
						 | 
				
			
			@ -126,7 +126,7 @@ fragment float4 ui_rect_fs(UiRectFragment in [[stage_in]])
 | 
			
		|||
 | 
			
		||||
    float distance = rect_sdf(pixel_pos, in.position, in.size, in.border_size.x);
 | 
			
		||||
    if (distance <= 0.0) {
 | 
			
		||||
        return float4(1,1,1,0.5);
 | 
			
		||||
        return float4(0.2,0.2,0.2,1.0);
 | 
			
		||||
    } else {
 | 
			
		||||
        return float4(0);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								src/gfx.h
								
								
								
								
							
							
						
						
									
										33
									
								
								src/gfx.h
								
								
								
								
							| 
						 | 
				
			
			@ -58,6 +58,9 @@ typedef struct {
 | 
			
		|||
    uint32_t frame_width;
 | 
			
		||||
    uint32_t frame_height;
 | 
			
		||||
    _gfx_frame_func frame_func;
 | 
			
		||||
 | 
			
		||||
    size_t num_glyphs;
 | 
			
		||||
    size_t num_ui_rects;
 | 
			
		||||
} gfx_context_t;
 | 
			
		||||
static gfx_context_t _gfx_context;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,15 +91,13 @@ static void _metal_gfx_send_events(_metal_gfx_context *cx);
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
- (void)windowDidResize:(NSNotification *)notification {
 | 
			
		||||
    NSLog(@"did resize\n");
 | 
			
		||||
 | 
			
		||||
    _gfx_context.frame_width = _gfx_context.backend.window.contentView.frame.size.width;
 | 
			
		||||
    _gfx_context.frame_height = _gfx_context.backend.window.contentView.frame.size.height;
 | 
			
		||||
    
 | 
			
		||||
    CGFloat scale = _gfx_context.backend.metal_layer.contentsScale;
 | 
			
		||||
    [_gfx_context.backend.metal_layer setDrawableSize:CGSizeMake(_gfx_context.frame_width * scale, _gfx_context.frame_height * scale)];
 | 
			
		||||
 | 
			
		||||
    _metal_gfx_present(&_gfx_context.backend);
 | 
			
		||||
    _gfx_context.backend.view.needsDisplay = true;
 | 
			
		||||
}
 | 
			
		||||
@end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -276,6 +277,18 @@ void _metal_gfx_present(_metal_gfx_context *cx) {
 | 
			
		|||
 | 
			
		||||
    id<MTLRenderCommandEncoder> encoder = [command_buffer renderCommandEncoderWithDescriptor:render_pass_desc];
 | 
			
		||||
 | 
			
		||||
    if (_gfx_context.num_ui_rects > 0) {
 | 
			
		||||
        // UI Rects
 | 
			
		||||
        [encoder setRenderPipelineState:cx->pipelines.data[1]];
 | 
			
		||||
        // FIXME: allow these to be described by the user instead of hardcoded
 | 
			
		||||
        [encoder setVertexBuffer:cx->buffers.data[0] offset:0 atIndex:0]; // vertices
 | 
			
		||||
        [encoder setVertexBuffer:cx->buffers.data[4] offset:0 atIndex:1]; // ui rects
 | 
			
		||||
        [encoder setVertexBuffer:cx->buffers.data[3] offset:0 atIndex:2]; // uniforms
 | 
			
		||||
        // TODO: get instance count properly
 | 
			
		||||
        [encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:cx->buffers.data[1] indexBufferOffset:0 instanceCount:_gfx_context.num_ui_rects];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (_gfx_context.num_glyphs > 0) {
 | 
			
		||||
        // UI Text
 | 
			
		||||
        [encoder setRenderPipelineState:cx->pipelines.data[0]];
 | 
			
		||||
        // FIXME: allow these to be described by the user instead of hardcoded
 | 
			
		||||
| 
						 | 
				
			
			@ -284,16 +297,8 @@ void _metal_gfx_present(_metal_gfx_context *cx) {
 | 
			
		|||
        [encoder setVertexBuffer:cx->buffers.data[3] offset:0 atIndex:2]; // uniforms
 | 
			
		||||
        [encoder setFragmentTexture:cx->textures.data[0] atIndex:0];
 | 
			
		||||
        // TODO: get instance count properly
 | 
			
		||||
    [encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:cx->buffers.data[1] indexBufferOffset:0 instanceCount:36];
 | 
			
		||||
 | 
			
		||||
    // UI Rects
 | 
			
		||||
    [encoder setRenderPipelineState:cx->pipelines.data[1]];
 | 
			
		||||
    // FIXME: allow these to be described by the user instead of hardcoded
 | 
			
		||||
    [encoder setVertexBuffer:cx->buffers.data[0] offset:0 atIndex:0]; // vertices
 | 
			
		||||
    [encoder setVertexBuffer:cx->buffers.data[4] offset:0 atIndex:1]; // ui rects
 | 
			
		||||
    [encoder setVertexBuffer:cx->buffers.data[3] offset:0 atIndex:2]; // uniforms
 | 
			
		||||
    // TODO: get instance count properly
 | 
			
		||||
    [encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:cx->buffers.data[1] indexBufferOffset:0 instanceCount:3];
 | 
			
		||||
        [encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:cx->buffers.data[1] indexBufferOffset:0 instanceCount:_gfx_context.num_glyphs];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [encoder endEncoding];
 | 
			
		||||
    [command_buffer presentDrawable:drawable];
 | 
			
		||||
| 
						 | 
				
			
			@ -355,6 +360,8 @@ void * gfx_init_context(_gfx_frame_func frame_func, uint32_t width, uint32_t hei
 | 
			
		|||
    _gfx_context.frame_func = frame_func;
 | 
			
		||||
    _gfx_context.frame_width = width;
 | 
			
		||||
    _gfx_context.frame_height = height;
 | 
			
		||||
    _gfx_context.num_glyphs = 0;
 | 
			
		||||
    _gfx_context.num_ui_rects = 0;
 | 
			
		||||
 | 
			
		||||
    return &_gfx_context;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										42
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -66,18 +66,18 @@ void queue_text(string text, float position[2]) {
 | 
			
		|||
 | 
			
		||||
            glyph.position[0] = x+position[0];
 | 
			
		||||
            glyph.position[1] = position[1];
 | 
			
		||||
            x += glyph.size[0]/2;
 | 
			
		||||
            x += glyph.size[0]/2+4;
 | 
			
		||||
 | 
			
		||||
            pushArray(GpuGlyph, &state.gpu_glyphs, glyph);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void queue_ui_rect(uint32_t position[2], uint32_t size[2], uint32_t border_size) {
 | 
			
		||||
void queue_ui_rect(float position[2], float size[2], float border_size) {
 | 
			
		||||
    GpuUiRect rect = (GpuUiRect) {
 | 
			
		||||
        .position = { (float)position[0], (float)position[1] },
 | 
			
		||||
        .size = { (float)size[0], (float)size[1] },
 | 
			
		||||
        .border_size = { (float)border_size, (float)border_size },
 | 
			
		||||
        .position = { position[0], position[1] },
 | 
			
		||||
        .size = { size[0], size[1] },
 | 
			
		||||
        .border_size = { border_size, border_size },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    pushArray(GpuUiRect, &state.gpu_ui_rects, rect);
 | 
			
		||||
| 
						 | 
				
			
			@ -178,36 +178,42 @@ void ed_init(_gfx_frame_func frame_func) {
 | 
			
		|||
    gfx_push_texture_buffer(state.gfx_cx, font_bitmap_size, font_bitmap_size, font_bitmap, font_bitmap_size*font_bitmap_size * sizeof(uint8_t));
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void render_ui_text(string text, float position[2]) {
 | 
			
		||||
    queue_text(text, position);
 | 
			
		||||
}
 | 
			
		||||
void render_ui_rect(float position[2], float size[2]) {
 | 
			
		||||
    queue_ui_rect(position, size, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ed_frame() {
 | 
			
		||||
    state.ui_cx.frame_elements.data[0].size.computed_size[0] = state.gfx_cx->frame_width;
 | 
			
		||||
    state.ui_cx.frame_elements.data[0].size.computed_size[1] = state.gfx_cx->frame_height;
 | 
			
		||||
 | 
			
		||||
    ui_element(&state.ui_cx, _String("Number 1"));
 | 
			
		||||
    ui_element(&state.ui_cx, _String("ui element 2"));
 | 
			
		||||
    ui_element(&state.ui_cx, _String("ui element 3"));
 | 
			
		||||
    ui_element(&state.ui_cx, _String("Number 1"), UI_AXIS_VERTICAL, ui_make_size(ui_fill, ui_fill), 0);
 | 
			
		||||
    ui_push_parent(&state.ui_cx);
 | 
			
		||||
    {
 | 
			
		||||
        ui_element(&state.ui_cx, _String("ui element 2"), UI_AXIS_HORIZONTAL, ui_make_size(ui_fit_text, ui_fill), UI_FLAG_DRAW_BACKGROUND|UI_FLAG_DRAW_TEXT);
 | 
			
		||||
        ui_element(&state.ui_cx, _String("ui element 2"), UI_AXIS_HORIZONTAL, ui_make_size(ui_fit_text, ui_fit_text), UI_FLAG_DRAW_BACKGROUND|UI_FLAG_DRAW_TEXT);
 | 
			
		||||
    }
 | 
			
		||||
    ui_pop_parent(&state.ui_cx);
 | 
			
		||||
    ui_element(&state.ui_cx, _String("Look I don't have to hardcode any values"), UI_AXIS_VERTICAL, ui_make_size(ui_fit_text, ui_fit_text), UI_FLAG_DRAW_BACKGROUND|UI_FLAG_DRAW_TEXT);
 | 
			
		||||
 | 
			
		||||
    ui_compute_layout(&state.ui_cx, 0);
 | 
			
		||||
 | 
			
		||||
    state.gpu_glyphs.size = 0;
 | 
			
		||||
    state.gpu_ui_rects.size = 0;
 | 
			
		||||
    for (size_t i = 1; i < state.ui_cx.frame_elements.size; ++i) {
 | 
			
		||||
        string text = state.ui_cx.frame_elements.data[i].key;
 | 
			
		||||
        ui_element_frame_data *elm = &state.ui_cx.frame_elements.data[i];
 | 
			
		||||
 | 
			
		||||
        queue_text(text, (float[]){ (float)elm->size.computed_pos[0], (float)elm->size.computed_pos[1] });
 | 
			
		||||
 | 
			
		||||
        fprintf(stderr, "size[0]: %d, size[1]: %d\n", elm->size.computed_size[0], elm->size.computed_size[1]);
 | 
			
		||||
        queue_ui_rect(elm->size.computed_pos, elm->size.computed_size, 16);
 | 
			
		||||
    }
 | 
			
		||||
    ui_render(&state.ui_cx, render_ui_text, render_ui_rect);
 | 
			
		||||
 | 
			
		||||
    ui_update_cache(&state.ui_cx, 0);
 | 
			
		||||
    ui_prune(&state.ui_cx);
 | 
			
		||||
 | 
			
		||||
    state.gfx_cx->num_glyphs = state.gpu_glyphs.size;
 | 
			
		||||
    if (state.gpu_glyphs.size > 0) {
 | 
			
		||||
        gfx_update_buffer(state.gfx_cx, 2, state.gpu_glyphs.data, state.gpu_glyphs.size * sizeof(GpuGlyph));
 | 
			
		||||
        fprintf(stderr, "updated glyph buffer: %zu\n", state.gpu_glyphs.size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    state.gfx_cx->num_ui_rects = state.gpu_ui_rects.size;
 | 
			
		||||
    if (state.gpu_ui_rects.size > 0) {
 | 
			
		||||
        gfx_update_buffer(state.gfx_cx, 4, state.gpu_ui_rects.data, state.gpu_ui_rects.size * sizeof(GpuUiRect));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								src/ui.h
								
								
								
								
							
							
						
						
									
										59
									
								
								src/ui.h
								
								
								
								
							| 
						 | 
				
			
			@ -52,6 +52,13 @@ typedef struct {
 | 
			
		|||
    };
 | 
			
		||||
} ui_semantic_size;
 | 
			
		||||
 | 
			
		||||
#define ui_make_size(horizontal, vertical) ((ui_semantic_size[2]) { horizontal, vertical })
 | 
			
		||||
 | 
			
		||||
#define ui_fit_text ((ui_semantic_size) { .type = UI_SEMANTIC_SIZE_FIT_TEXT })
 | 
			
		||||
#define ui_fill ((ui_semantic_size) { .type = UI_SEMANTIC_SIZE_FILL })
 | 
			
		||||
#define ui_children_sum ((ui_semantic_size) { .type = UI_SEMANTIC_SIZE_CHILDREN_SUM })
 | 
			
		||||
#define ui_exact(value) ((ui_semantic_size) { .type = UI_SEMANTIC_SIZE_EXACT, .integer = value })
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    ui_axis axis;
 | 
			
		||||
    ui_semantic_size semantic_size[2];
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +149,19 @@ ui_context ui_init_context() {
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ui_element(ui_context *cx, string label) {
 | 
			
		||||
void ui_push_parent(ui_context *cx) {
 | 
			
		||||
    if (cx->frame_elements.size > 0) {
 | 
			
		||||
        cx->current_parent = cx->frame_elements.size-1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ui_pop_parent(ui_context *cx) {
 | 
			
		||||
    if (_parent(cx->current_parent) < SIZE_MAX) {
 | 
			
		||||
        cx->current_parent = _parent(cx->current_parent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ui_element(ui_context *cx, string label, ui_axis axis, ui_semantic_size size[2], ui_flags flags) {
 | 
			
		||||
    ui_element_frame_data frame_data = (ui_element_frame_data) {
 | 
			
		||||
        .index = cx->frame_elements.size,
 | 
			
		||||
        // TODO: don't just set this to label, because then elements
 | 
			
		||||
| 
						 | 
				
			
			@ -154,8 +173,10 @@ size_t ui_element(ui_context *cx, string label) {
 | 
			
		|||
        .next = -1,
 | 
			
		||||
        .prev = cx->frame_elements.data[cx->current_parent].last,
 | 
			
		||||
        .parent = cx->current_parent,
 | 
			
		||||
        .size.semantic_size[0].type = UI_SEMANTIC_SIZE_FILL,
 | 
			
		||||
        .size.semantic_size[1].type = UI_SEMANTIC_SIZE_FIT_TEXT,
 | 
			
		||||
        .size.axis = axis,
 | 
			
		||||
        .size.semantic_size[0] = size[0],
 | 
			
		||||
        .size.semantic_size[1] = size[1],
 | 
			
		||||
        .flags = flags,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Get cached element data
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +184,11 @@ size_t ui_element(ui_context *cx, string label) {
 | 
			
		|||
    if (cache_data) {
 | 
			
		||||
        cache_data->last_instantiated_index = cx->frame_index;
 | 
			
		||||
 | 
			
		||||
        frame_data.size = cache_data->size;
 | 
			
		||||
        frame_data.size.computed_pos[0] = cache_data->size.computed_pos[0];
 | 
			
		||||
        frame_data.size.computed_pos[1] = cache_data->size.computed_pos[1];
 | 
			
		||||
 | 
			
		||||
        frame_data.size.computed_size[0] = cache_data->size.computed_size[0];
 | 
			
		||||
        frame_data.size.computed_size[1] = cache_data->size.computed_size[1];
 | 
			
		||||
    } else {
 | 
			
		||||
        assert("couldn't insert into ui element cache" && ht_set(&cx->cached_elements, label, &(ui_element_cache_data) {
 | 
			
		||||
            .label = label,
 | 
			
		||||
| 
						 | 
				
			
			@ -386,6 +411,32 @@ void ui_update_cache(ui_context *cx, size_t element_index) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef void (*_ui_render_text_func)(string text, float position[2]);
 | 
			
		||||
typedef void (*_ui_render_rect_func)(float position[2], float size[2]);
 | 
			
		||||
void ui_render(ui_context *cx, _ui_render_text_func text_func, _ui_render_rect_func rect_func) {
 | 
			
		||||
    for (size_t i = 1; i < cx->frame_elements.size; ++i) {
 | 
			
		||||
        string text = cx->frame_elements.data[i].key;
 | 
			
		||||
        ui_element_frame_data *elm = &cx->frame_elements.data[i];
 | 
			
		||||
 | 
			
		||||
        if (_flags(i, UI_FLAG_DRAW_TEXT)) {
 | 
			
		||||
            text_func(text, (float[]){ (float)elm->size.computed_pos[0], (float)elm->size.computed_pos[1] });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_flags(i, UI_FLAG_DRAW_BACKGROUND)) {
 | 
			
		||||
            rect_func(
 | 
			
		||||
                (float[]){
 | 
			
		||||
                    (float)elm->size.computed_pos[0],
 | 
			
		||||
                    (float)elm->size.computed_pos[1]
 | 
			
		||||
                },
 | 
			
		||||
                (float[]){
 | 
			
		||||
                    (float)elm->size.computed_size[0],
 | 
			
		||||
                    (float)elm->size.computed_size[1]
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ui_prune(ui_context *cx) {
 | 
			
		||||
    for (size_t i = 0; i < cx->cached_elements.capacity; ++i) {
 | 
			
		||||
        if (cx->cached_elements.key_slots[i].key.data != NULL) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue