diff options
Diffstat (limited to 'src/room_editor.lua')
| -rw-r--r-- | src/room_editor.lua | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/src/room_editor.lua b/src/room_editor.lua new file mode 100644 index 0000000..01d5c90 --- /dev/null +++ b/src/room_editor.lua @@ -0,0 +1,283 @@ +register_input("Next_Tileset", {{"key", "v"}}) +register_input("Prev_Tileset", {{"key", "c"}}) +register_input("Tile_Brush", {{"key", "t"}}) +register_input("Entity_Brush", {{"key", "e"}}) +register_input("Delete", {{"key", "delete"}, {"key", "backspace"}}) + +local basic_entity_properties = { + {"flip_h", false}, + {"flip_v", false}, +} + +local entity_definitions = {} + +function define_entity(name, tex_name, properties, spawner) + table.insert(entity_definitions, name) + entity_definitions[name] = { + spawner = spawner, + tex_name = tex_name, + properties = properties, + idx = #entity_definitions, + } +end + +register_comp("Room_Editor", function(ent) + ent.room_editor = { + -- Valid values are Tile, Entity + -- TODO: + -- * Prop (place stuff on top of tiles automatically) + brush = "Tile", + tile = 1, + entity = "Muntik", + entity_snap = true, + selected_ent = -1, + placed_entities = {}, + } +end) + +register_comp("Editor_Entity", function(ent, room_editor, ent_type, x, y) + ent.x = x + ent.y = y + local entity_def = entity_definitions[ent_type] + local properties = {} + for _, property in ipairs(basic_entity_properties) do + local name = property[1] + local default = property[2] + properties[name] = default + end + for _, property in ipairs(entity_def.properties) do + local name = property[1] + local default = property[2] + properties[name] = default + end + ent.editor_dat = { + type = ent_type, + room_editor = room_editor, + properties = properties, + } +end) + +local function get_selected_entity(room_editor) + return room_editor.placed_entities[room_editor.selected_ent] +end + +local function new_editor_entity(room_editor, ent_type, x, y) + local ent = new_entity() + add_comp(ent, "Editor_Entity", room_editor, ent_type, x, y) + add_comp(ent, "Sprite", entity_definitions[ent_type].tex_name, {}) + return ent +end + +function draw_editor_entity_sys(ent) + local editor_dat = ent.editor_dat + local selected_ent = get_selected_entity(editor_dat.room_editor) + + if selected_ent == ent then + -- show selected mhmm + lg.rectangle("line", ent.x, ent.y, ent.sprite.width, ent.sprite.height) + end +end + +local property_ui = { + ["number"] = function(name, editor_dat, property) + im.layout({0.5, 1}) + im.text(name) + im.text(tostring(snap(editor_dat.properties[name], 0.01))) + im.layout() + editor_dat.properties[name] = im.slider( + editor_dat.properties[name], + property.min or 0, + property.max or 1, + property.step or 0.1 + ) + end, + ["boolean"] = function(name, editor_dat, property) + im.layout({0.25, 0.5, 1}) + im.text(name) + im.text(tostring(editor_dat.properties[name])) + if im.button("Toggle") then + editor_dat.properties[name] = not editor_dat.properties[name] + end + end, +} + +local function property_list(ent, properties) + local editor_dat = ent.editor_dat + for _, property in ipairs(properties) do + local name = property[1] + local prop_type = type(property[2]) + property_ui[prop_type](name, editor_dat, property) + im.layout() + end +end + +function editor_entity_ui_sys(ent) + local editor_dat = ent.editor_dat + if editor_dat.room_editor.brush ~= "Entity" then + return + end + + local selected_ent = get_selected_entity(editor_dat.room_editor) + + if selected_ent == ent then + local entity_def = entity_definitions[editor_dat.type] + im.begin_window("Entity Properties", 190, 5, 180, 340, {}) + im.text("Base Properties") + im.separator() + property_list(ent, basic_entity_properties) + im.separator() + im.text("Type Properties") + im.separator() + property_list(ent, entity_def.properties) + im.end_window() + end +end + +local function get_snapped_to_grid(room_editor, x, y) + if room_editor.entity_snap then + return snap(x, TILESIZE), snap(y, TILESIZE) + else + -- Still snap to the pixel cause yes + return round(x), round(y) + end +end + +local brushes = { + ["Tile"] = function(room_editor) + if is_input_pressed("Left_Click") then + local scn = get_current_scene() + assert(scn, "no scene set.") + + local mx, my = get_mouse_pos() + local tx, ty = to_tile_coords(mx, my) + set_tile(scn.tilemap, tx, ty, room_editor.tile) + end + if is_input_pressed("Right_Click") then + local scn = get_current_scene() + assert(scn, "no scene set.") + + local mx, my = get_mouse_pos() + local tx, ty = to_tile_coords(mx, my) + remove_tile(scn.tilemap, tx, ty) + end + end, + ["Entity"] = function(room_editor) + local mx, my = get_mouse_pos() + if is_input_just_pressed("Left_Click") then + -- first check if we're selecting an entity + local selected = false + for i, ent in ipairs(room_editor.placed_entities) do + if point_in_rect( + mx, my, + ent.x, ent.y, + ent.sprite.width, ent.sprite.height + ) then + room_editor.selected_ent = i + selected = true + break + end + end + + -- Place one frfr + if not selected then + mx, my = get_snapped_to_grid(room_editor, mx, my) + local ent = new_editor_entity(room_editor, room_editor.entity, mx, my) + table.insert(room_editor.placed_entities, ent) + room_editor.selected_ent = #room_editor.placed_entities + end + end + end +} + +function tile_place_sys(ent) + local room_editor = ent.room_editor + + if not im.has_focus() then + brushes[room_editor.brush](room_editor) + end + + if is_input_just_pressed("Next_Tileset") then + room_editor.tile = math.min(room_editor.tile + 1, get_tileset_count()) + end + if is_input_just_pressed("Prev_Tileset") then + room_editor.tile = math.max(room_editor.tile - 1, 1) + end + + if is_input_just_pressed("Tile_Brush") then + room_editor.brush = "Tile" + end + if is_input_just_pressed("Entity_Brush") then + room_editor.brush = "Entity" + end +end + +function room_editor_ui_sys(ent) + local room_editor = ent.room_editor + + im.begin_window("Room Editor", 5, 5, 180, 180, {}) + im.text("Brushes") + im.layout({0.1, 1}) + im.text("t") + if im.button("Tile") then + room_editor.brush = "Tile" + end + im.text("e") + if im.button("Entity") then + room_editor.brush = "Entity" + end + im.layout() + im.end_window() + + if room_editor.brush == "Tile" then + im.begin_window("Tile Editor", 5, 190, 180, 340, {}) + im.text("Tile: " .. tostring(room_editor.tile)) + im.separator() + im.layout({0.1, 0.6, 1}) + + for tileset_id=1, get_tileset_count() do + local text = " " + if tileset_id == room_editor.tile then + text = "*" + elseif tileset_id == room_editor.tile - 1 then + text = "c" + elseif tileset_id == room_editor.tile + 1 then + text = "v" + end + im.text(text) + if im.button("select") then + room_editor.tile = tileset_id + end + im.image(TILE_TEX, get_tileset_quad(tileset_id)) + end + + im.layout() + im.end_window() + elseif room_editor.brush == "Entity" then + im.begin_window("Entity Editor", 5, 190, 180, 340, {}) + im.layout({0.2, 1}) + + im.text(room_editor.entity_snap and "On" or "Off") + if im.button("Position Snapping") then + room_editor.entity_snap = not room_editor.entity_snap + end + + im.layout({0.1, 0.6, 1}) + + for _, entity_name in ipairs(entity_definitions) do + local entity_def = entity_definitions[entity_name] + + local text = " " + if entity_name == room_editor.entity then + text = "*" + end + im.text(text) + if im.button("select") then + room_editor.entity = entity_name + end + im.image(get_tex(entity_def.tex_name)) + end + + im.layout() + im.end_window() + end +end |
