1-- Solarus 1.0 to 1.1. 2-- Sprite data files change to a more readable syntax. 3-- The sprite features remain the same. 4 5local converter = {} 6 7-- Parses a sprite data file in 1.0 format and returns a table representing 8-- the sprite information. 9local function load_sprite(quest_path, sprite_id) 10 11 local input_file_name = quest_path .. "/data/sprites/" .. sprite_id .. ".dat" 12 local input_file, error_message = io.open(input_file_name) 13 if input_file == nil then 14 error("Cannot open old sprite file for reading: " .. error_message) 15 end 16 17 local sprite = {} 18 local line_number = 0 19 local animation = nil 20 local num_directions = 0 21 for line in input_file:lines() do 22 23 line_number = line_number + 1 24 25 if #line > 0 then -- Skip empty lines. 26 27 if animation == nil then 28 29 -- The line is a new animation declaration. 30 animation = {} 31 animation.directions = {} 32 animation.name, animation.src_image, num_directions, animation.frame_delay, animation.frame_to_loop_on = 33 line:match("^(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*$") 34 35 num_directions = tonumber(num_directions) 36 animation.frame_delay = tonumber(animation.frame_delay) 37 animation.frame_to_loop_on = tonumber(animation.frame_to_loop_on) 38 if animation.name == nil 39 or num_directions == nil 40 or animation.frame_delay == nil 41 or animation.frame_to_loop_on == nil then 42 error(input_file_name .. ": line " .. line_number .. ": Invalid animation declaration") 43 end 44 45 if animation.frame_delay == 0 then 46 -- nil or 0 means no frame end in Solarus 1.1 47 animation.frame_delay = nil 48 end 49 50 if animation.frame_to_loop_on == -1 then 51 -- nil means no loop in Solarus 1.1. 52 animation.frame_to_loop_on = nil 53 end 54 55 else 56 -- The line is a direction. 57 local direction = {} 58 direction.x, direction.y, direction.frame_width, direction.frame_height, 59 direction.origin_x, direction.origin_y, direction.num_frames, direction.num_columns = 60 line:match("^(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*$") 61 62 direction.x = tonumber(direction.x) 63 direction.y = tonumber(direction.y) 64 direction.frame_width = tonumber(direction.frame_width) 65 direction.frame_height = tonumber(direction.frame_height) 66 direction.origin_x = tonumber(direction.origin_x) 67 direction.origin_y = tonumber(direction.origin_y) 68 direction.num_frames = tonumber(direction.num_frames) 69 direction.num_columns = tonumber(direction.num_columns) 70 71 if direction.x == nil 72 or direction.y == nil 73 or direction.frame_width == nil 74 or direction.frame_height == nil 75 or direction.origin_x == nil 76 or direction.origin_y == nil 77 or direction.num_frames == nil 78 or direction.num_columns == nil then 79 error(input_file_name .. ": line " .. line_number .. ": Invalid direction definition") 80 end 81 82 -- 0,0 is the default origin. 83 if direction.origin_x == 0 then 84 direction.origin_x = nil 85 end 86 if direction.origin_y == 0 then 87 direction.origin_y = nil 88 end 89 90 if direction.num_columns == direction.num_frames then 91 -- nil means num_frames columns. 92 direction.num_columns = nil 93 end 94 95 if direction.num_frames == 1 then 96 -- Default value. 97 direction.num_frames = nil 98 end 99 100 animation.directions[#animation.directions + 1] = direction 101 102 if #animation.directions == num_directions then 103 -- All directions of this animations were parsed. 104 sprite[#sprite + 1] = animation 105 animation = nil 106 end 107 end 108 end 109 end 110 111 input_file:close() 112 113 return sprite 114end 115 116function converter.convert(quest_path, sprite_id) 117 118 local sprite = load_sprite(quest_path, sprite_id) 119 120 local output_file_name = quest_path .. "/data/sprites/" .. sprite_id .. ".dat" 121 local output_file, error_message = io.open(output_file_name, "w") 122 if output_file == nil then 123 error("Cannot open new sprite file for writing: " .. error_message) 124 end 125 126 for _, animation in ipairs(sprite) do 127 128 -- Write the animation properties. 129 output_file:write("animation{\n"); 130 output_file:write(" name = \"", animation.name, "\",\n") 131 output_file:write(" src_image = \"", animation.src_image, "\",\n") 132 133 if animation.frame_delay ~= nil then 134 output_file:write(" frame_delay = ", animation.frame_delay, ",\n") 135 end 136 137 if animation.frame_to_loop_on ~= nil then 138 output_file:write(" frame_to_loop_on = ", animation.frame_to_loop_on, ",\n") 139 end 140 141 output_file:write(" directions = {\n") 142 143 for _, direction in ipairs(animation.directions) do 144 output_file:write(" { x = ", direction.x, 145 ", y = ", direction.y, 146 ", frame_width = ", direction.frame_width, 147 ", frame_height = ", direction.frame_height) 148 if direction.origin_x ~= nil then 149 output_file:write(", origin_x = ", direction.origin_x) 150 end 151 if direction.origin_y ~= nil then 152 output_file:write(", origin_y = ", direction.origin_y) 153 end 154 if direction.num_frames ~= nil then 155 output_file:write(", num_frames = ", direction.num_frames) 156 end 157 if direction.num_columns ~= nil then 158 output_file:write(", num_columns = ", direction.num_columns) 159 end 160 output_file:write(" },\n") 161 end 162 163 output_file:write(" },\n") 164 output_file:write("}\n\n") 165 end 166 167 output_file:close() 168end 169 170return converter 171 172