diff --git a/resources/utiltex/water.png b/resources/utiltex/water.png deleted file mode 100644 index 9ae6671..0000000 Binary files a/resources/utiltex/water.png and /dev/null differ diff --git a/resources/utiltex/water1.png b/resources/utiltex/water1.png deleted file mode 100644 index e2ed0c9..0000000 Binary files a/resources/utiltex/water1.png and /dev/null differ diff --git a/resources/utiltex/water_small.png b/resources/utiltex/water_small.png new file mode 100644 index 0000000..65986e3 Binary files /dev/null and b/resources/utiltex/water_small.png differ diff --git a/src/editor/animation_studio.jai b/src/editor/animation_studio.jai new file mode 100644 index 0000000..282a50b --- /dev/null +++ b/src/editor/animation_studio.jai @@ -0,0 +1,75 @@ +#scope_file + +current_sheet : s32 = 0; +current_sheet_last_frame : s32 = -1; +current_sheet_ptr : *Spritesheet; + +step_offset_y : s32 = 0; +scale : float = 5; + +#scope_export + +tick_animation_studio :: () { + if input_button_states[Key_Code.ARROW_UP] & .START { + step_offset_y -= 1; + } + if input_button_states[Key_Code.ARROW_DOWN] & .START { + step_offset_y += 1; + } + + scale += mouse_delta_z; + scale = clamp(scale, 1, 10); + +} + +draw_animation_studio_ui :: (theme: *GR.Overall_Theme) { + if g_spritesheets.count < 1 then return; + + r := GR.get_rect(0, ui_h(5,0), ui_w(20, 0), ui_h(95, 0)); + ui_add_mouse_occluder(r); + draw_bg_rectangle(r, theme); + + sheets : [..]string; + sheets.allocator = temp; + + for v : g_spritesheets { + array_add(*sheets, v.name); + } + + r2 := r; + r2.h = ui_h(5,0); + r2.w = r.w; + GR.dropdown(r2, sheets, *current_sheet, *theme.dropdown_theme); + + if current_sheet != current_sheet_last_frame { + current_sheet_ptr = table_find_pointer(*g_spritesheets, sheets[current_sheet]); + } + + number_theme : GR.Number_Input_Theme; + + r2.y += r2.h * 1.1; + GR.label(r2, "Step X", *theme.label_theme); + r2.y += r2.h * 1.1; + GR.number_input(r2, tprint("%", current_sheet_ptr.step_x), *current_sheet_ptr.step_x, 0, 128, *number_theme); + r2.y += r2.h * 1.1; + GR.label(r2, "Step Y", *theme.label_theme); + r2.y += r2.h * 1.1; + GR.number_input(r2, tprint("%", current_sheet_ptr.step_y), *current_sheet_ptr.step_y, 0, 128, *number_theme); + + uiTex := New(Ui_Texture ,,temp); + uiTex.tex = current_sheet_ptr.sheet; + if uiTex.tex.id != INVALID_ID { + menu_offset := Vector2.{ui_w(20,0), ui_h(5,0)}; + zone_r := GR.get_rect(menu_offset.x, menu_offset.y, ui_w(80,0), ui_h(95,0)); + draw_rectangle(zone_r, .{1.0, 0.0, 1.0, 1.0}); + set_shader_for_images(uiTex); + + img_r := zone_r; + img_r.y -= step_offset_y * cast(s32)current_sheet_ptr.step_y * scale; + img_r.w = current_sheet_ptr.w * scale; + img_r.h = current_sheet_ptr.h * scale; + + immediate_quad(.{img_r.x, img_r.y}, .{img_r.x + img_r.w, img_r.y}, .{img_r.x + img_r.w, img_r.y + img_r.h}, .{img_r.x, img_r.y + img_r.h}); + set_shader_for_color(); + } +} diff --git a/src/editor/editor.jai b/src/editor/editor.jai index b455073..9186fad 100644 --- a/src/editor/editor.jai +++ b/src/editor/editor.jai @@ -3,6 +3,7 @@ #load "picker.jai"; #load "trile_editor.jai"; #load "level_editor.jai"; + #load "animation_studio.jai"; } #if HAS_TACOMA { #load "tacoma.jai"; } #load "console.jai"; @@ -65,6 +66,8 @@ draw_editor_ui :: (theme: *GR.Overall_Theme) { draw_trile_editor_ui(theme); case .Level_Editor; draw_level_editor_ui(theme); + case .Animation_Editor; + draw_animation_studio_ui(theme); } } draw_profiler(); @@ -103,6 +106,7 @@ tick_editor_ui :: () { case .Level_Editor; tick_level_editor(); case .Animation_Editor; + tick_animation_studio(); } } } diff --git a/src/editor/level_editor.jai b/src/editor/level_editor.jai index a811413..a7a4650 100644 --- a/src/editor/level_editor.jai +++ b/src/editor/level_editor.jai @@ -225,10 +225,8 @@ draw_tacoma_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) { Edit_Mode :: enum { TRILES; - GROUND; } -groundType : Ground_Tile; editMode : Edit_Mode; #scope_export @@ -236,49 +234,15 @@ editMode : Edit_Mode; draw_tools_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) { r := total_r; r.h = ui_h(3,0); - r.w = r.w/2.0; - if GR.button(r, "Edit triles", *t_button_selectable(theme, editMode == .TRILES)) { - editMode = .TRILES; - } - r.x += r.w; - if GR.button(r, "Edit ground", *t_button_selectable(theme, editMode == .GROUND)) { - editMode = .GROUND; - } - r.x -= r.w; - r.w *= 2.0; - r.y += r.h * 1.5; - if editMode == .GROUND { - if GR.button(r, "Grass", *t_button_selectable(theme, groundType == .GRASS)) { - groundType = .GRASS; - } - r.y += r.h; - if GR.button(r, "Water", *t_button_selectable(theme, groundType == .WATER)) { - groundType = .WATER; - } - r.y += r.h; - if GR.button(r, "Sand", *t_button_selectable(theme, groundType == .SAND)) { - groundType = .SAND; - } - } } handle_tool_click :: (x: int, y: int, z: int, delete: bool = false) { curworld := get_current_world(); - if editMode == { - case .TRILES; - if delete { - remove_trile(cast(float)x, cast(float)y, cast(float)z); - } else { - if editor_current_trile != null then add_trile(editor_current_trile.name, cast(float)x, cast(float)y, cast(float)z); - } - case .GROUND; - ray := get_mouse_ray(*get_level_editor_camera()); - hit, point := ray_plane_collision_point(ray, 0, 100); - if hit { - curworld.world.ground[floor(point.y).(int) + 500][floor(point.x).(int) + 500] = groundType; - } + if delete { + remove_trile(cast(float)x, cast(float)y, cast(float)z); + } else { + if editor_current_trile != null then add_trile(editor_current_trile.name, cast(float)x, cast(float)y, cast(float)z); } - } add_trile :: (name: string, x: float, y: float, z: float) { diff --git a/src/load.jai b/src/load.jai index 6e384c7..aed3258 100644 --- a/src/load.jai +++ b/src/load.jai @@ -1,9 +1,10 @@ +g_asset_pack : Load_Package; + #scope_file MAX_FILE_SIZE :: 2_000_000_000; buf : [MAX_FILE_SIZE]u8; -g_asset_pack : Load_Package; mandatory_loads_left : s32 = 0; @@ -48,12 +49,12 @@ add_font_from_pack :: (path: string) { state.font_default.fons_font = fonsAddFontMem(state.fons, "sans", entry.data.data, xx entry.data.count, 0); } -create_texture_from_pack :: (path: string) -> sg_image { +create_texture_from_pack :: (path: string) -> (sg_image, s32, s32) { ok, entry := table_find_new(*g_asset_pack.lookup, path); if !ok { print("Failed to find texture % from pack...\n", path); img : sg_image; - return img; + return img, 0, 0; } x : s32; @@ -79,7 +80,7 @@ create_texture_from_pack :: (path: string) -> sg_image { stbi.stbi_image_free(data); - return img; + return img, x, y; } load_string_from_pack :: (path: string) -> string { @@ -104,7 +105,7 @@ asset_list :: () -> string #expand { return tprint("> A total of % assets.", count); } @Command -// Returns tprinted pointer, please copy it somewhere. +// Returns tprinted string, please copy it somewhere. format_size :: (bytes: int) -> string { bytes_counter := bytes; bytes_float := cast(float) bytes; diff --git a/src/main.jai b/src/main.jai index 8017787..fde890c 100644 --- a/src/main.jai +++ b/src/main.jai @@ -119,6 +119,7 @@ init_after_asset_pack :: () { } init_editor(); lworlds(); + init_spritesheets(); init_rendering(); load_post_process_from_pack(); diff --git a/src/rendering/animation.jai b/src/rendering/animation.jai new file mode 100644 index 0000000..6eb8655 --- /dev/null +++ b/src/rendering/animation.jai @@ -0,0 +1,65 @@ +g_spritesheets : Table(string, Spritesheet); +g_animations: Table(string, Animation); + +String :: #import "String"; + +Spritesheet :: struct { + name : string; + step_x : u32 = 32; + step_y : u32 = 32; + w : s32 = 0; + h : s32 = 0; + sheet : sg_image; +} + +Animation :: struct { + spritesheet : string; + ids : [..]u32; + fps : float; +} + +load_spritesheets :: () { + Jaison :: #import "Jaison"; + s := load_string_from_pack("./game/resources/spritesheets.json"); + success, sheets := Jaison.json_parse_string(s, [..]Spritesheet,, temp); + if !success then return; + for sheets { + print("Loaded %\n", it.name); + img, w, h := create_texture_from_pack(tprint("./game/resources/sprites/%", it.name)); + name_cpy := sprint("%", it.name); + newSheet := Spritesheet.{ + name = name_cpy, + step_x = it.step_x, + step_y = it.step_y, + sheet = img, + w = w, + h = h, + }; + table_add(*g_spritesheets, name_cpy, newSheet); + } +} + +init_spritesheets :: () { + load_spritesheets(); + add_new_spritesheets_from_pack(); +} + +add_new_spritesheets_from_pack :: () { + for v : g_asset_pack.lookup { + isSpritesheet, remainder := String.contains(v.name, "/sprites/"); + if isSpritesheet { + ok, sheet := table_find_new(*g_spritesheets, remainder); + if !ok { + print("Adding sheet: %\n", remainder); + img, w, h := create_texture_from_pack(v.name); + newSheet := Spritesheet.{ + name = remainder, + sheet = img, + w = w, + h = h, + }; + table_add(*g_spritesheets, remainder, newSheet); + } + } + } +} diff --git a/src/rendering/backend.jai b/src/rendering/backend.jai index 08ab13a..ffbabb9 100644 --- a/src/rendering/backend.jai +++ b/src/rendering/backend.jai @@ -16,7 +16,6 @@ Render_Command_Type :: enum { DRAW_SKY; SET_CAMERA; DRAW_GROUND; - GENERATE_GROUND; ADD_TRILE_POSITIONS; DRAW_TRILE_POSITIONS; UPDATE_TRIXELS; @@ -72,12 +71,6 @@ Render_Command_Draw_Ground :: struct { worldConfig : *World_Config; } -Render_Command_Generate_Ground_Texture :: struct { - #as using c : Render_Command; - c.type = .GENERATE_GROUND; - world : *World; -} - Render_Command_Set_Camera :: struct { #as using c : Render_Command; c.type = .SET_CAMERA; diff --git a/src/rendering/backend_sokol.jai b/src/rendering/backend_sokol.jai index 789ba34..a1ccfc8 100644 --- a/src/rendering/backend_sokol.jai +++ b/src/rendering/backend_sokol.jai @@ -25,9 +25,6 @@ backend_handle_command :: (cmd: *Render_Command) { case .SET_CAMERA; camera_command := cast(*Render_Command_Set_Camera)cmd; camera = camera_command.camera; - case .GENERATE_GROUND; - gen_command := cast(*Render_Command_Generate_Ground_Texture)cmd; - update_image_from_ground(gen_command.world, *gPipelines.plane.bind.images[1]); case .DRAW_GROUND; ground_command := cast(*Render_Command_Draw_Ground)cmd; if in_gbuffer_pass { diff --git a/src/rendering/pipelines.jai b/src/rendering/pipelines.jai index 0fc815e..93f9ee2 100644 --- a/src/rendering/pipelines.jai +++ b/src/rendering/pipelines.jai @@ -943,7 +943,7 @@ create_ssao_pipeline :: () { } init_plane_textures :: () { - gPipelines.plane.bind.images[3] = create_texture_from_pack("./resources/utiltex/water.png"); + gPipelines.plane.bind.images[3] = create_texture_from_pack("./resources/utiltex/water_small.png"); } g_plane_gbuffer_vertex_buffer : sg_buffer; diff --git a/src/rendering/rendering.jai b/src/rendering/rendering.jai index 509b938..f797f06 100644 --- a/src/rendering/rendering.jai +++ b/src/rendering/rendering.jai @@ -15,6 +15,7 @@ #load "arbtri.jai"; #load "meshgen.jai"; #load "helpers.jai"; +#load "animation.jai"; #load "pipelines.jai"; #load "post_processing.jai"; #load "backend_sokol_helpers.jai"; diff --git a/src/rendering/tasks.jai b/src/rendering/tasks.jai index ef8e7d3..69fb03a 100644 --- a/src/rendering/tasks.jai +++ b/src/rendering/tasks.jai @@ -113,8 +113,6 @@ tasks_to_commands :: () { case .GROUND; commandDrawGround := New(Render_Command_Draw_Ground,, temp); commandDrawGround.worldConfig = *(cast(*Rendering_Task_Ground)it).world.conf; - commandGenGround := New(Render_Command_Generate_Ground_Texture,, temp); - commandGenGround.world = (cast(*Rendering_Task_Ground)it).world; array_add(*render_command_buckets.main, commandDrawGround); array_add(*render_command_buckets.gbuffer, commandDrawGround); case .SET_CAMERA; diff --git a/src/world.jai b/src/world.jai index 499652c..0279382 100644 --- a/src/world.jai +++ b/src/world.jai @@ -105,17 +105,10 @@ TrilePositions :: struct { positions: [..]Vector4; } -Ground_Tile :: enum u8 { - WATER :: 0; - GRASS :: 1; - SAND :: 2; -} - World :: struct { name : string; conf : World_Config; positions : [..]TrilePositions; - ground : [1000][1000]Ground_Tile; } Trile_Positions_Serialized :: struct { @@ -127,7 +120,6 @@ World_Serialized :: struct { name : string; conf : World_Config; positions : [..]Trile_Positions_Serialized; - ground : string; } // You should call this function with the temp allocator as context allocator. @@ -147,14 +139,6 @@ serialize_world :: (world: *World) -> World_Serialized { array_add(*ws.positions, tsp); } - groundstring : [..]u8; - for i: 0..999 { - for j: 0..999 { - array_add(*groundstring, (cast(u8) world.ground[i][j]) + #char "a"); - } - } - ws.ground.data = groundstring.data; - ws.ground.count = groundstring.count; return ws; } @@ -175,45 +159,6 @@ deserialize_world :: (ws: *World_Serialized, world: *World) { } array_add(*world.positions, tp); } - - for c, ci : ws.ground { - world.ground[ci/1000][ci%1000] = cast(Ground_Tile)((cast(u8)c)-#char "a"); - } -} - -update_image_from_ground :: (world: *World, img: *sg_image) { - materialdata : [1000*1000*4]u8; - counter : int = 0; - for x: 0..999 { - for y: 0..999 { - if world.ground[x][y] == .GRASS { - materialdata[counter + 0] = 0; - materialdata[counter + 1] = 255; - materialdata[counter + 2] = 0; - materialdata[counter + 3] = 255; - - } - if world.ground[x][y] == .WATER { - materialdata[counter + 0] = 0; - materialdata[counter + 1] = 0; - materialdata[counter + 2] = 255; - materialdata[counter + 3] = 255; - - } - if world.ground[x][y] == .SAND { - materialdata[counter + 0] = 255; - materialdata[counter + 1] = 0; - materialdata[counter + 2] = 0; - materialdata[counter + 3] = 255; - - } - counter += 4; - } - } - imgdata : sg_image_data; - imgdata.subimage[0][0] = .{materialdata.data, materialdata.count}; - - sg_update_image(img, *imgdata); } draw_world_picker :: (r_in: GR.Rect, theme: *GR.Overall_Theme) {