diff --git a/draw/draw.odin b/draw/draw.odin index 0d834a9..841ea5c 100644 --- a/draw/draw.odin +++ b/draw/draw.odin @@ -1346,6 +1346,7 @@ Draw :: struct solid_circles : SolidCircle, solid_capsules : SolidCapsules, polygons : SolidPolygon, + textures : Texture, drawCounters : bool, //regular_font : im.Font, frame_buffer : u32, @@ -1435,11 +1436,33 @@ draw_flush :: proc(draw : ^Draw) { lines_flush(&draw.lines, &draw.cam) points_flush(&draw.points, &draw.cam) circle_flush(&draw.circles, &draw.cam) + textures_flush(draw) text_flush(draw) check_opengl() } +Rect :: struct { + x, y, w, h : f32, +} + +TextureData :: struct +{ + texture_id : u32, //opengl texture id + width, height : i32, + src_rect : Rect, // in pixel format + dst_rect : Rect, // in pixel format +} + +//Contains multiple textures +Texture :: struct +{ + textures : [dynamic]TextureData, + vao, vbo, ebo: u32, + uniforms : gl.Uniforms, + program_id : u32, +} + /* Create texture and render texture @@ -1449,7 +1472,51 @@ draw_flush :: proc(draw : ^Draw) { render_texture :: gets a texture_id and rect and displays the texture (generic but convinent for micorui) */ -create_texutre :: proc(data: []u8, width, height: i32) -> u32 +textures_create :: proc(texture: ^Texture) +{ + + texture.program_id, _ = gl.load_shaders_source(#load("shaders/texture.vs"), #load("shaders/texture.fs")) + + gl.UseProgram(texture.program_id) + gl.Enable(gl.BLEND) + gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + + texture.uniforms = gl.get_uniforms_from_program(texture.program_id) + + vertices : []f32 = { + 0.0, 1.0, 0.0, 1.0, + 0.0, 0.0, 0.0, 0.0, + 1.0, 0.0, 1.0, 0.0, + 1.0, 1.0, 1.0, 1.0, + } + + indices := []u32 { + 0, 1, 2, + 0, 2, 3, + } + + gl.GenVertexArrays(1, &texture.vao) + gl.GenBuffers(1, &texture.vbo) + gl.GenBuffers(1, &texture.ebo) + + gl.BindVertexArray(texture.vao) + gl.BindBuffer(gl.ARRAY_BUFFER, texture.vbo) + gl.BufferData(gl.ARRAY_BUFFER, len(vertices) * size_of(f32), raw_data(vertices), gl.DYNAMIC_DRAW) + gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, texture.ebo) + gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indices) * size_of(u32), raw_data(indices), gl.DYNAMIC_DRAW) + gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 4 * size_of(f32), 0) + gl.EnableVertexAttribArray(0) + gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 4 * size_of(f32), 2 * size_of(f32)) + gl.EnableVertexAttribArray(1) + + //gl.BindBuffer(gl.ARRAY_BUFFER, 0) + //gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0) + + gl.UseProgram(0) +} + + +create_texture :: proc(data: []u8, width, height: i32) -> u32 { texture : u32 @@ -1457,16 +1524,55 @@ create_texutre :: proc(data: []u8, width, height: i32) -> u32 gl.BindTexture(gl.TEXTURE_2D, texture) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, raw_data(data)) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - - gl.BindTexture(gl.TEXTURE_2D, 0) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.BindTexture( gl.TEXTURE_2D, 0) return texture } +textures_flush :: proc(d: ^Draw) +{ + + texture := &d.textures + + gl.UseProgram(texture.program_id) + gl.Uniform2f(texture.uniforms["u_resolution"].location, f32(d.cam.width), f32(d.cam.height)) + + gl.Enable(gl.BLEND) + gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + gl.ActiveTexture(gl.TEXTURE0) + + for &t in &texture.textures + { + vertices := []f32{ + 0.0, 1.0, t.src_rect.x , (t.src_rect.y+ f32(t.src_rect.h)), + 0.0, 0.0, t.src_rect.x , (t.src_rect.y ), + 1.0, 0.0, (t.src_rect.x + f32(t.src_rect.w)), (t.src_rect.y ), + 1.0, 1.0, (t.src_rect.x + f32(t.src_rect.w)), (t.src_rect.y+ f32(t.src_rect.h)) + } + + gl.BindBuffer(gl.ARRAY_BUFFER, texture.vbo) + gl.BufferData(gl.ARRAY_BUFFER, len(vertices) * size_of(f32), raw_data(vertices), gl.DYNAMIC_DRAW) + + gl.Uniform2f(texture.uniforms["u_position"].location, t.dst_rect.x, t.dst_rect.y) + gl.Uniform2f(texture.uniforms["u_size"].location, t.dst_rect.w, t.dst_rect.h) + + gl.BindTexture(gl.TEXTURE_2D, t.texture_id) + gl.Uniform1i(texture.uniforms["ourTexture"].location, 0) + gl.BindVertexArray(texture.vao) + + gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil) + + + } + gl.Disable(gl.BLEND) + gl.UseProgram(0) + check_opengl() + + clear(&texture.textures) +} + @@ -1481,6 +1587,7 @@ draw_create :: proc(draw : ^Draw, camera : ^Camera, font_path : string = "") circle_create(&draw.circles) solid_circle_create(&draw.solid_circles) solid_polygon_create(&draw.polygons) + textures_create(&draw.textures) { draw.glyph.atlas_width = draw.cam.width diff --git a/draw/shaders/texture.vs b/draw/shaders/texture.vs index b55312b..e8f08ad 100644 --- a/draw/shaders/texture.vs +++ b/draw/shaders/texture.vs @@ -18,7 +18,7 @@ void main(){ vec2 ndc; ndc.x = (screen_pos.x / u_resolution.x) * 2.0 - 1.0; - ndc.y = 1.0 - (screen_pos.y / u_resolution.x) * 2.0; + ndc.y = 1.0 - (screen_pos.y / u_resolution.y) * 2.0; gl_Position = vec4(ndc, 0.0, 1.0); TexCoord = aTexCoord; diff --git a/edit2d.odin b/edit2d.odin index 8306d9e..599d11f 100644 --- a/edit2d.odin +++ b/edit2d.odin @@ -36,6 +36,7 @@ engine_state :: struct input : input_state, mu_ctx : mu.Context, + mu_tex : u32, } MAX_KEYS :: 512 @@ -177,14 +178,43 @@ engine_init :: proc($GameType : typeid, state: ^engine_state, font_path : strin //Glyph and microui { + //Create index mu.init(&state.mu_ctx) state.mu_ctx.style.font = cast(mu.Font)&state.draw.glyph state.mu_ctx.text_width = mui_text_width state.mu_ctx.text_height = mui_text_height + texture_data := make([]u8, mu.DEFAULT_ATLAS_WIDTH* mu.DEFAULT_ATLAS_HEIGHT * 4) + idx :i32 = 0 + for y in 0.. e2_draw.Rect +{ + points : e2_draw.Rect + + points.x = f32(rect.x) / f32(size) + points.y = f32(rect.y) / f32(size) + points.w = f32(rect.w) / f32(size) + points.h = f32(rect.h) / f32(size) + return points +} + update_frame :: proc(state: ^engine_state) { @@ -264,7 +294,7 @@ end_frame :: proc(state: ^engine_state) for &p, i in &points do points[i] = e2_draw.camera_convert_screen_to_world(&draw.cam, p) color := c.color //hex_color := e2_draw.make_hex_color({color.r, color.g, color.b, color.a}) - e2_draw.solid_polygon_add(&draw.polygons, {q = e2_draw.Rot{c = 1}}, &points[0], 4, 0, transmute([4]u8)color) + e2_draw.solid_polygon_add(&draw.polygons, {q = e2_draw.Rot{c = 1}}, &points[0], 4, 0.01, transmute([4]u8)color) } case ^mu.Command_Clip: { @@ -272,19 +302,13 @@ end_frame :: proc(state: ^engine_state) gl.Scissor(rect.x, state.height - (rect.y + rect.h), rect.w, rect.h) } case ^mu.Command_Icon:{ + rect := mu.default_atlas[c.id] - if c.id == .CHECK - { - pos :[2]f32= {f32(c.rect.x), f32(c.rect.y)} - - pos.x += f32(c.rect.w)/2.0 - pos.y += f32(c.rect.h)/2.0 - pos = e2_draw.camera_convert_screen_to_world(&draw.cam, pos) - - e2_draw.solid_circle_add(&draw.solid_circles,{p = pos, q = e2_draw.Rot{c = 1}} , 0.1,{255, 255, 255, 255}) - }else{ - fmt.println(c.id) - } + append(&draw.textures.textures, e2_draw.TextureData{ + texture_id = state.mu_tex, + src_rect = normalize_rect(rect, mu.DEFAULT_ATLAS_WIDTH), + dst_rect = e2_draw.Rect{f32(c.rect.x), f32(c.rect.y), f32(rect.w), f32(rect.h)}, + }) } } @@ -346,8 +370,3 @@ draw_flush :: proc(d: ^e2_draw.Draw) e2_draw.draw_flush(d) } - - - - - diff --git a/interface.odin b/interface.odin index 0e9ce80..820b018 100644 --- a/interface.odin +++ b/interface.odin @@ -103,6 +103,7 @@ interface_get_default :: proc(interface: ^interface_state) interface.chain_index^ = 0 } +/* interface_draw_options :: proc(state: ^engine_state) { debug_draw := &state.debug_draw @@ -123,10 +124,11 @@ interface_draw_options :: proc(state: ^engine_state) im.Checkbox("Islands ", &debug_draw.drawIslands) im.SliderFloat("Rotation", &state.draw.cam.rotation, 0, 360) } +*/ mu_interface_game_mode :: proc(state: ^engine_state, interface: ^interface_state) { - if mu.begin_window(&state.mu_ctx, "Edit Mode", {1700, 0, 250, 170}) + if mu.begin_window(&state.mu_ctx, "Edit Mode", {1630, 0, 250, 170}) { for type in EditMode { @@ -187,12 +189,11 @@ interface_all :: proc(interface: ^interface_state) -> bool if im.BeginTabBar("Tabs") { - if mu.begin_window(&state.mu_ctx, "B2d Interface", {1700, 150, 250, 250}) + if mu.begin_window(&state.mu_ctx, "B2d Interface", {1630, 170, 250, 450}) { if .ACTIVE in mu.header(&state.mu_ctx, "Entity", {.AUTO_SIZE}) { if interface_entity(interface) do ret = true - } mu.end_window(&state.mu_ctx) } diff --git a/interface_entity.odin b/interface_entity.odin index 0d8d53d..4c132b3 100644 --- a/interface_entity.odin +++ b/interface_entity.odin @@ -27,6 +27,7 @@ import "core:fmt" By doing comparasion on def */ +/* interface_body_def_editor :: proc(def: ^engine_entity_def) { if im.BeginCombo("Body Type", fmt.ctprint(def.body_def.type)) @@ -59,14 +60,58 @@ interface_body_def_editor :: proc(def: ^engine_entity_def) def.body_def.name = cstring(&def.name_buf[0]) } } +*/ + +mu_interface_body_def_editor :: proc(interface: ^interface_state, def : ^engine_entity_def) +{ + + ctx := &interface.state.mu_ctx + if .ACTIVE in mu.begin_treenode(ctx, "Body Type") + { + for type in b2.BodyType + { + state := def.body_def.type == type + if .CHANGE in mu.checkbox(ctx, fmt.tprint(type), &state) + { + def.body_def.type = type + } + } + mu.end_treenode(ctx) + } + + mu.label(ctx, "Position") + mu.slider(ctx, &def.body_def.position[0], -50, 50) + mu.slider(ctx, &def.body_def.position[1], -50, 50) + + angle := draw.RAD2DEG * b2.Rot_GetAngle(def.body_def.rotation) + + mu.label(ctx, "Rotation") + if .CHANGE in mu.slider(ctx, &angle, 0, 359) + { + def.body_def.rotation = b2.MakeRot(draw.DEG2RAD * angle) + } + + + mu.label(ctx, "Linear Velocity") + mu.slider(ctx, &def.body_def.linearVelocity[0], 0, 500) + mu.slider(ctx, &def.body_def.linearVelocity[1], 0, 500) + mu.label(ctx, "Angular Velocity") + mu.slider(ctx, &def.body_def.angularVelocity, 0, 500) + mu.label(ctx, "Linear Damping") + mu.slider(ctx, &def.body_def.linearDamping, 0, 500) + mu.label(ctx, "Angular Damping") + mu.slider(ctx, &def.body_def.angularDamping, 0, 500) + mu.label(ctx, "Gravity Scale") + mu.slider(ctx, &def.body_def.gravityScale, 0, 100) + mu.checkbox(ctx, "Fixed rotation", &def.body_def.fixedRotation) + +} interface_edit_static_index :: proc(interface:^interface_state, def: ^engine_entity_def) -> bool { - curr_index := &interface.curr_static_index - entity := interface.entities[interface.selected_entity] - - level := interface.world + entity := interface.entities[interface.selected_entity] + level := interface.world if level.relations[entity.index] == nil @@ -123,6 +168,26 @@ interface_edit_static_index :: proc(interface:^interface_state, def: ^engine_ent return false } +mu_interface_edit_static_index :: proc(interface: ^interface_state, def : ^engine_entity_def) -> bool +{ + curr_index := &interface.curr_static_index + entity := interface.entities[interface.selected_entity] + level := interface.world + ctx := &interface.state.mu_ctx + + + if level.relations[entity.index] == nil + { + level.relations[entity.index] = {} + } + + indexes := &level.relations[entity.index] + + //if mu.slider() + + +} + mu_interface_shape_def_editor :: proc( state : ^engine_state, def : ^engine_entity_def) -> bool @@ -210,6 +275,7 @@ mu_interface_shape_def_editor :: proc( } +/* interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool { shape_def := &def.shape_def @@ -300,6 +366,7 @@ interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool } return false } +*/ interface_entity :: proc(interface: ^interface_state) -> bool { @@ -322,20 +389,23 @@ interface_entity :: proc(interface: ^interface_state) -> bool im.Separator() - if im.CollapsingHeader("Shape Edit") + + if .ACTIVE in mu.begin_treenode(&interface.state.mu_ctx, "Body Def") { - //interface_shape_def_editor(def) + mu_interface_body_def_editor(interface, def) + mu.end_treenode(&interface.state.mu_ctx) + } + + if .ACTIVE in mu.begin_treenode(&interface.state.mu_ctx, "Shape Def") + { + mu_interface_shape_def_editor(interface.state, def) + mu.end_treenode(&interface.state.mu_ctx) } - mu_interface_shape_def_editor(interface.state, def) im.Separator() - if im.CollapsingHeader("Body Edit") - { - interface_body_def_editor(def) - } - - if im.CollapsingHeader("Static Index") + + if .ACTIVE in mu.begin_treenode(&interface.state.mu_ctx, "Static Index") { ret |= interface_edit_static_index(interface, def) }