tileset_tooling 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4ef2f1fdedff5ed99ecaa3e5ae8abff27f0713d4aeb345b441260e1170dcf0b
4
- data.tar.gz: 8aedce5b1c13268daf71424f6c759be677eab14d8046b6a07260fa891a9caa99
3
+ metadata.gz: c708dba05b753997be72b94e89172f4f6dc0388a561ed9af27cd5136ef63371e
4
+ data.tar.gz: 013ff8cd539154a20637eb14ef2b4eae9c831301a31a87d3c999ffb27eb65a89
5
5
  SHA512:
6
- metadata.gz: f1cae98cca145f189b410bd1b823c2a8c82307dba322672b9a6db2692b1362d56d0063bda2e17560a468cf26b9c5e4e2a19bb8fbfdaaa309931a7b44f0e6f082
7
- data.tar.gz: bb6567a71e7433d737a49592996f93cff8e158145dd214aa85e737736f1501a7ecc0fb5d9093d5e76a1266844ba2e0604d7e489aae3624e8542a01d598aaca9c
6
+ metadata.gz: 9c1e7efa99996036fb4c801d626ef7d5662f896d60908e79864214f533fac0406b5d29d06c756c5ba79686c8498d9ff7d66603aea862b38e0409dfa67074c958
7
+ data.tar.gz: 513fdaad596bfe275002fa6008a4018cbbdfd70c4e62145ebc4ba550f6d81d0e41f126b63887df4b87c12c7dea3b33bcf86b887441bb108dc2bb3051593b8d35
data/.gitignore CHANGED
@@ -5,4 +5,4 @@ test/data/tmp_output.png
5
5
  results.html
6
6
  test/data/*_result.png
7
7
 
8
- tileset_tooling-0.0.1.gem
8
+ tileset_tooling-*.gem
@@ -13,6 +13,9 @@ AllCops:
13
13
  Metrics/AbcSize:
14
14
  Max: 50
15
15
 
16
+ Metrics/BlockLength:
17
+ Max: 50
18
+
16
19
  Metrics/CyclomaticComplexity:
17
20
  Max: 8
18
21
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tileset_tooling (0.0.1)
4
+ tileset_tooling (0.1.0)
5
5
  dry-struct (~> 1.3, >= 1.3.0)
6
6
  gli (~> 2.19, = 2.19.2)
7
7
  highline (~> 2.0, >= 2.0.3)
@@ -1,7 +1,8 @@
1
1
  = tileset_tooling
2
2
 
3
3
  {<img src="https://github.com/calestar/tileset_tooling/workflows/Ruby/badge.svg?branch=master" alt="Build Status" />}[https://github.com/calestar/tileset_tooling/actions?query=workflow%3ARuby]
4
- {<img src="https://ruby-gem-downloads-badge.herokuapp.com/tileset_tooling?metric=true" alt="Build Status" />}[https://rubygems.org/gems/tileset_tooling]
4
+ {<img src="https://badgen.net/rubygems/dt/tileset_tooling" alt="Number of downloads" />}[https://rubygems.org/gems/tileset_tooling]
5
+ {<img src="https://badge.fury.io/rb/tileset_tooling.svg" alt="Gem Version" />}[https://badge.fury.io/rb/tileset_tooling]
5
6
 
6
7
  Bits of tooling I use for working with tilesets.
7
8
 
@@ -13,8 +13,8 @@ Feature: App inserts bleed correctly
13
13
  Then I type "0"
14
14
  Then I type "0"
15
15
  Then I type "0"
16
- Then the exit status should be 1
17
- Then the output should contain "Current implementation needs an existing margin"
16
+ Then the exit status should be 0
17
+ Then generated file should be the same as data result "simple_no_margin.png"
18
18
 
19
19
  Scenario: Insert bleed generate default output
20
20
  When I insert bleed to test data "simple_with_margin.png"
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'gli'
5
+ require 'mini_magick'
5
6
  require 'semantic_logger'
6
7
 
7
8
  require 'tileset_tooling/version'
@@ -29,6 +30,7 @@ class ::TilesetTooling::App
29
30
  ::SemanticLogger.default_level = :trace
30
31
  ::SemanticLogger.add_appender(io: $stdout, formatter: :color)
31
32
 
33
+ # ::MiniMagick.logger.level = ::Logger::DEBUG
32
34
  true
33
35
  end
34
36
 
@@ -49,7 +51,8 @@ class ::TilesetTooling::App
49
51
  insert_command.switch([:'skip-specs'], desc: 'Skips the reading of the specs')
50
52
  insert_command.flag([:output], default_value: nil, desc: 'Path where to store result', arg_name: 'path')
51
53
  insert_command.action do |_, options, args|
52
- command = ::TilesetTooling::Commands::InsertBleed.new(options, args)
54
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
55
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
53
56
  command.unpack!
54
57
  command.run
55
58
  end
@@ -2,11 +2,18 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'tileset_tooling/data'
5
+ require 'tileset_tooling/utils'
5
6
 
6
7
  require 'yaml'
7
8
 
8
9
  # Command used to insert bleed around tiles
9
10
  class ::TilesetTooling::Commands::InsertBleed < ::TilesetTooling::Commands::Command
11
+ # Constructor, initializes a few internal
12
+ def initialize(options, args, specs_loader)
13
+ @specs_loader = specs_loader
14
+ super(options, args)
15
+ end
16
+
10
17
  # Validates arguments/options and unpacks them
11
18
  def unpack!
12
19
  raise(::StandardError, 'Missing argument') unless @args.count == 1
@@ -21,27 +28,56 @@ class ::TilesetTooling::Commands::InsertBleed < ::TilesetTooling::Commands::Comm
21
28
  @logger.info("Adding bleed to tiles in image file '#{@image_path}'")
22
29
  tileset = gather_image_information
23
30
 
24
- raise(::StandardError, 'Current implementation needs an existing margin') unless tileset.margin.positive?
31
+ if tileset.margin.positive?
32
+ modify_margin(tileset)
33
+ else
34
+ add_margin(tileset)
35
+ end
36
+
37
+ @logger.info("Result stored in '#{result_path}'")
38
+ end
39
+
40
+ private
25
41
 
42
+ def modify_margin(tileset)
26
43
  ::MiniMagick::Tool::Convert.new do |convert|
27
44
  convert.background('none')
28
45
  convert << tileset.original_image_path
29
46
 
30
47
  tileset.for_each_tile do |tile|
31
- copy_rect(convert, tile.left, tile.top, 1, tile.width, tile.left, tile.top - 1) unless tile.top <= 0
32
- copy_rect(convert, tile.left, tile.bottom - 1, 1, tile.width, tile.left, tile.bottom) unless tile.bottom >= tileset.height
33
- copy_rect(convert, tile.left, tile.top, tile.height, 1, tile.left - 1, tile.top) unless tile.left <= 0
34
- copy_rect(convert, tile.right - 1, tile.top, tile.height, 1, tile.right, tile.top) unless tile.right >= tileset.width
48
+ generate_bleed(convert, tileset, tile)
35
49
  end
36
50
 
37
51
  convert.flatten
38
52
  convert << result_path
39
53
  end
40
-
41
- @logger.info("Result stored in '#{result_path}'")
42
54
  end
43
55
 
44
- private
56
+ def add_margin(tileset)
57
+ nb_pixels_in_bleed = 1
58
+ new_tileset = ::TilesetTooling::Utils.tileset_with_margin_from(tileset, nb_pixels_in_bleed)
59
+ image_path = tileset.original_image_path
60
+
61
+ ::MiniMagick::Tool::Convert.new do |convert|
62
+ convert.background('none')
63
+
64
+ # Copy the original and resize so that we keep all the image specs
65
+ convert << image_path
66
+ convert.resize("#{new_tileset.width}x#{new_tileset.height}!")
67
+ convert.fill('white').draw("rectangle 0,0 #{new_tileset.width},#{new_tileset.height}").transparent('white')
68
+ convert.compose('Over')
69
+
70
+ # Copy tiles and bled
71
+ tileset.for_each_tile do |tile|
72
+ dest = new_tileset.tile_at(tile.row_index, tile.column_index)
73
+ copy_tile(convert, image_path, tile, dest)
74
+ generate_bleed(convert, tileset, tile, destination: dest, image_path: image_path)
75
+ end
76
+
77
+ convert.flatten
78
+ convert << result_path
79
+ end
80
+ end
45
81
 
46
82
  def result_path
47
83
  return @options[:output] if @options[:output]
@@ -53,55 +89,10 @@ class ::TilesetTooling::Commands::InsertBleed < ::TilesetTooling::Commands::Comm
53
89
  "#{directory}/#{file_name}_result#{extension}"
54
90
  end
55
91
 
56
- def ask_specs
57
- tile_height =
58
- @cli.ask('Tile height? ', ::Integer) do |q|
59
- q.default = 0
60
- q.in = 1..256
61
- end
62
- tile_width =
63
- @cli.ask('Tile width? ', ::Integer) do |q|
64
- q.default = 0
65
- q.in = 1..256
66
- end
67
- margin = @cli.ask('Margin? ', ::Integer) { |q| q.default = 0 }
68
- offset_top = @cli.ask('Top Offset? ', ::Integer) { |q| q.default = 0 }
69
- offset_left = @cli.ask('Left Offset? ', ::Integer) { |q| q.default = 0 }
70
-
71
- [tile_height, tile_width, margin, offset_top, offset_left]
72
- end
73
-
74
- def load_specs_from_file(file_path)
75
- @logger.info("Extracting specs from '#{file_path}'")
76
- specs = ::YAML.load_file(file_path)
77
-
78
- begin
79
- tile_height = specs['specs']['details']['tile_height']
80
- tile_width = specs['specs']['details']['tile_width']
81
- margin = specs['specs']['details']['margin']
82
- offset_top = specs['specs']['details']['offset_top']
83
- offset_left = specs['specs']['details']['offset_left']
84
- rescue ::NoMethodError
85
- raise(::StandardError, 'Invalid specs file')
86
- end
87
- [tile_height, tile_width, margin, offset_top, offset_left]
88
- end
89
-
90
- def find_specs
91
- specs_file = ::TilesetTooling::Utils.image_spec_file_path(@image_path)
92
- if !@options[:'skip-specs'] && ::File.exist?(specs_file)
93
- tile_height, tile_width, margin, offset_top, offset_left = load_specs_from_file(specs_file)
94
- else
95
- tile_height, tile_width, margin, offset_top, offset_left = ask_specs
96
- end
97
- [tile_height, tile_width, margin, offset_top, offset_left]
98
- end
99
-
100
- # Asks for information about the image and build a tileset
101
92
  def gather_image_information
102
- tile_height, tile_width, margin, offset_top, offset_left = find_specs
93
+ tile_height, tile_width, margin, offset_top, offset_left = @specs_loader.find_specs_for(@image_path, @options[:'skip-specs'])
103
94
 
104
- ::TilesetTooling::Data::TileSet.new(
95
+ ::TilesetTooling::Data::FileTileSet.new(
105
96
  image: ::MiniMagick::Image.open(@image_path),
106
97
  original_image_path: @image_path,
107
98
  tile_height: tile_height,
@@ -112,15 +103,44 @@ class ::TilesetTooling::Commands::InsertBleed < ::TilesetTooling::Commands::Comm
112
103
  )
113
104
  end
114
105
 
115
- def copy_rect(convert, x1, y1, height, width, x2, y2)
116
- # convert image \( +clone -crop WxH+X1+Y1 +repage \) -geometry +X2+Y2 -compose over -composite result
106
+ def copy_rect(convert, width, height, source, destination, image_path: nil)
117
107
  convert.stack do |stack|
118
- stack.clone.+ # rubocop:disable Lint/Void
119
- stack.crop("#{width}x#{height}+#{x1}+#{y1}")
120
- stack.repage.+
108
+ if image_path.nil?
109
+ stack.clone.+
110
+ else
111
+ stack << image_path
112
+ end
113
+ stack.crop("#{width}x#{height}+#{source.x}+#{source.y}").repage.+
121
114
  end
122
- convert.geometry("+#{x2}+#{y2}")
123
- convert.compose('Over')
124
- convert.composite
115
+ convert.geometry("+#{destination.x}+#{destination.y}")
116
+ convert.compose('Over').composite
117
+ end
118
+
119
+ def copy_tile(convert, image_path, source, destination)
120
+ copy_rect(convert, source.width, source.height, source.top_left, destination.top_left, image_path: image_path)
121
+ end
122
+
123
+ def generate_bleed(convert, tileset, source, destination: nil, image_path: nil)
124
+ destination = source if destination.nil?
125
+
126
+ # Top
127
+ source_coord = ::TilesetTooling::Data::Point.new(x: source.left, y: source.top)
128
+ dest_coord = ::TilesetTooling::Data::Point.new(x: destination.left, y: destination.top - 1)
129
+ copy_rect(convert, source.width, 1, source_coord, dest_coord, image_path: image_path) unless source.top <= 0
130
+
131
+ # Bottom
132
+ source_coord = ::TilesetTooling::Data::Point.new(x: source.left, y: source.bottom - 1)
133
+ dest_coord = ::TilesetTooling::Data::Point.new(x: destination.left, y: destination.bottom)
134
+ copy_rect(convert, source.width, 1, source_coord, dest_coord, image_path: image_path) unless source.bottom >= tileset.height
135
+
136
+ # Left
137
+ source_coord = ::TilesetTooling::Data::Point.new(x: source.left, y: source.top)
138
+ dest_coord = ::TilesetTooling::Data::Point.new(x: destination.left - 1, y: destination.top)
139
+ copy_rect(convert, 1, source.height, source_coord, dest_coord, image_path: image_path) unless source.left <= 0
140
+
141
+ # Right
142
+ source_coord = ::TilesetTooling::Data::Point.new(x: source.right - 1, y: source.top)
143
+ dest_coord = ::TilesetTooling::Data::Point.new(x: destination.right, y: destination.top)
144
+ copy_rect(convert, 1, source.height, source_coord, dest_coord, image_path: image_path) unless source.right >= tileset.width
125
145
  end
126
146
  end
@@ -8,6 +8,9 @@ require 'mini_magick'
8
8
  module ::TilesetTooling::Data
9
9
  end
10
10
 
11
+ # Needs to be first
11
12
  require 'tileset_tooling/data/types'
13
+
14
+ require 'tileset_tooling/data/point'
12
15
  require 'tileset_tooling/data/tile'
13
16
  require 'tileset_tooling/data/tileset'
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2020 Jean-Sebastien Gelinas, see LICENSE.txt
2
+ # frozen_string_literal: true
3
+
4
+ # Simple structure to represent a point (X,Y)
5
+ class ::TilesetTooling::Data::Point < ::Dry::Struct
6
+ attribute :x, ::TilesetTooling::Data::Types::Integer
7
+ attribute :y, ::TilesetTooling::Data::Types::Integer
8
+ end
@@ -1,6 +1,8 @@
1
1
  # Copyright (c) 2020 Jean-Sebastien Gelinas, see LICENSE.txt
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'tileset_tooling/data/point'
5
+
4
6
  # Class representing a TileSet's information
5
7
  class ::TilesetTooling::Data::Tile < ::Dry::Struct
6
8
  attribute :top, ::TilesetTooling::Data::Types::Integer
@@ -13,10 +15,8 @@ class ::TilesetTooling::Data::Tile < ::Dry::Struct
13
15
  attribute :margin_bottom, ::TilesetTooling::Data::Types::Integer
14
16
  attribute :margin_right, ::TilesetTooling::Data::Types::Integer
15
17
 
16
- # Helper to print the information of the tile
17
- def to_s
18
- "#{top},#{left} [#{margin_top},#{margin_left},#{margin_bottom},#{margin_right}]"
19
- end
18
+ attribute :row_index, ::TilesetTooling::Data::Types::Integer
19
+ attribute :column_index, ::TilesetTooling::Data::Types::Integer
20
20
 
21
21
  # Helper to get the bottom coordinate
22
22
  def bottom
@@ -27,4 +27,9 @@ class ::TilesetTooling::Data::Tile < ::Dry::Struct
27
27
  def right
28
28
  left + width
29
29
  end
30
+
31
+ # Helper to get the top-left point of this tile
32
+ def top_left
33
+ ::TilesetTooling::Data::Point.new(x: left, y: top)
34
+ end
30
35
  end
@@ -13,28 +13,16 @@ class ::TilesetTooling::Data::TileSetRow
13
13
  attr_reader :tiles
14
14
  end
15
15
 
16
- # Class representing a TileSet's information
17
- class ::TilesetTooling::Data::TileSet < ::Dry::Struct
18
- attribute :image, ::TilesetTooling::Data::Types::ImageType
19
- attribute :original_image_path, ::TilesetTooling::Data::Types::String
16
+ # Class representing any TileSet's information
17
+ class ::TilesetTooling::Data::TileSetBase < ::Dry::Struct
18
+ attribute :height, ::TilesetTooling::Data::Types::Integer
19
+ attribute :width, ::TilesetTooling::Data::Types::Integer
20
20
  attribute :tile_height, ::TilesetTooling::Data::Types::Integer
21
21
  attribute :tile_width, ::TilesetTooling::Data::Types::Integer
22
22
  attribute :margin, ::TilesetTooling::Data::Types::Integer
23
23
  attribute :offset_top, ::TilesetTooling::Data::Types::Integer
24
24
  attribute :offset_left, ::TilesetTooling::Data::Types::Integer
25
25
 
26
- # Helper to print all information in the image
27
- def to_s
28
- %(
29
- Image '#{original_image_path}'
30
- Tile height: #{tile_height}
31
- Tile width: #{tile_width}
32
- Margin: #{margin}
33
- Top offset: #{offset_top}
34
- Left offset: #{offset_left}
35
- Number of tiles: #{rows.count * rows[0].tiles.count})
36
- end
37
-
38
26
  # Runs the given bloc on each tile of the tileset
39
27
  def for_each_tile(&block)
40
28
  rows.each do |row|
@@ -44,14 +32,19 @@ Image '#{original_image_path}'
44
32
  end
45
33
  end
46
34
 
47
- # Gets the height of the tileset/image
48
- def height
49
- image.height
35
+ # Gets the number of tiles per row
36
+ def nb_tiles_per_row
37
+ rows[0].tiles.length
50
38
  end
51
39
 
52
- # Gets the width of the tileset/image
53
- def width
54
- image.width
40
+ # Gets the number of tiles per column
41
+ def nb_tiles_per_column
42
+ rows.length
43
+ end
44
+
45
+ # Gets the tile at the specified row/column
46
+ def tile_at(row_index, column_index)
47
+ rows[row_index].tiles[column_index]
55
48
  end
56
49
 
57
50
  private
@@ -62,11 +55,13 @@ Image '#{original_image_path}'
62
55
 
63
56
  @rows = []
64
57
  top = offset_top
58
+ row_index = 0
65
59
  loop do
66
60
  left = offset_left
67
61
  tiles = []
68
62
  margin_top = top.positive? ? margin : 0
69
63
  margin_bottom = top + tile_height < height ? margin : 0
64
+ column_index = 0
70
65
 
71
66
  loop do
72
67
  margin_left = left.positive? ? margin : 0
@@ -80,17 +75,40 @@ Image '#{original_image_path}'
80
75
  margin_top: margin_top,
81
76
  margin_left: margin_left,
82
77
  margin_bottom: margin_bottom,
83
- margin_right: margin_right
78
+ margin_right: margin_right,
79
+ row_index: row_index,
80
+ column_index: column_index
84
81
  )
85
82
  left += tile_width + margin_left + margin_right
83
+ column_index += 1
86
84
  break if left >= width
87
85
  end
88
86
 
89
87
  @rows << ::TilesetTooling::Data::TileSetRow.new(tiles)
90
88
  top += tile_height + margin_top + margin_bottom
89
+ row_index += 1
91
90
  break if top >= height
92
91
  end
93
92
 
94
93
  @rows
95
94
  end
96
95
  end
96
+
97
+ # Real tileset, associated with an actual image on disk
98
+ class ::TilesetTooling::Data::FileTileSet < ::TilesetTooling::Data::TileSetBase
99
+ attribute :image, ::TilesetTooling::Data::Types::ImageType
100
+ attribute :original_image_path, ::TilesetTooling::Data::Types::String
101
+
102
+ def self.new(**kwargs)
103
+ image = kwargs[:image]
104
+ kwargs[:image] = image
105
+ kwargs[:height] = image.height
106
+ kwargs[:width] = image.width
107
+
108
+ super(**kwargs)
109
+ end
110
+ end
111
+
112
+ # Virtual tileset, not associated with an actual image
113
+ class ::TilesetTooling::Data::VirtualTileSet < ::TilesetTooling::Data::TileSetBase
114
+ end
@@ -1,26 +1,9 @@
1
1
  # Copyright (c) 2020 Jean-Sebastien Gelinas, see LICENSE.txt
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'mini_magick'
5
-
6
- # A few random utilities
4
+ # Module containing a few random utilities
7
5
  module ::TilesetTooling::Utils
8
- module_function
9
-
10
- # Generate a signature from the image data
11
- def image_signature(image_path)
12
- ::MiniMagick::Tool::Identify.new do |identity|
13
- identity.quiet
14
- identity.format('%#\\n')
15
- identity << image_path
16
- end
17
- end
18
-
19
- # Gets the path to the spec file that should go with the given image
20
- def image_spec_file_path(image_path)
21
- file_name = ::File.basename(image_path, '.*')
22
- directory = ::File.dirname(image_path)
23
-
24
- "#{directory}/#{file_name}.specs"
25
- end
26
6
  end
7
+
8
+ require 'tileset_tooling/utils/common'
9
+ require 'tileset_tooling/utils/specs_loader'
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2020 Jean-Sebastien Gelinas, see LICENSE.txt
2
+ # frozen_string_literal: true
3
+
4
+ require 'mini_magick'
5
+
6
+ # A few random utilities
7
+ module ::TilesetTooling::Utils
8
+ module_function
9
+
10
+ # Generate a signature from the image data
11
+ def image_signature(image_path)
12
+ ::MiniMagick::Tool::Identify.new do |identity|
13
+ identity.quiet
14
+ identity.format('%#\\n')
15
+ identity << image_path
16
+ end
17
+ end
18
+
19
+ # Generates a virtual tileset with added margin to be used for coordinate
20
+ def tileset_with_margin_from(original_tileset, nb_pixels_in_margin)
21
+ raise(::StandardError, 'Original tileset already contains a margin') unless original_tileset.margin.zero?
22
+
23
+ new_height = original_tileset.height + (original_tileset.nb_tiles_per_column * 2 * nb_pixels_in_margin) - 2 * nb_pixels_in_margin
24
+ new_width = original_tileset.width + (original_tileset.nb_tiles_per_row * 2 * nb_pixels_in_margin) - 2 * nb_pixels_in_margin
25
+
26
+ ::TilesetTooling::Data::VirtualTileSet.new(
27
+ tile_height: original_tileset.tile_height,
28
+ tile_width: original_tileset.tile_width,
29
+ margin: nb_pixels_in_margin,
30
+ offset_top: original_tileset.offset_top,
31
+ offset_left: original_tileset.offset_left,
32
+ height: new_height,
33
+ width: new_width
34
+ )
35
+ end
36
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2020 Jean-Sebastien Gelinas, see LICENSE.txt
2
+ # frozen_string_literal: true
3
+
4
+ # Class used to find/load specs for a given image
5
+ class ::TilesetTooling::Utils::SpecsLoader
6
+ # Constructor, initializes a few internals
7
+ def initialize
8
+ @logger = ::SemanticLogger[self.class.name.split('::').last]
9
+ @cli = ::HighLine.new
10
+ end
11
+
12
+ # Tries to find specs for the given image path
13
+ def find_specs_for(image_path, skip_specs_file)
14
+ specs_file = image_spec_file_path(image_path)
15
+ if !skip_specs_file && ::File.exist?(specs_file)
16
+ load_specs_from_file(specs_file)
17
+ else
18
+ ask_specs
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # Gets the path to the spec file that should go with the given image
25
+ def image_spec_file_path(image_path)
26
+ file_name = ::File.basename(image_path, '.*')
27
+ directory = ::File.dirname(image_path)
28
+
29
+ "#{directory}/#{file_name}.specs"
30
+ end
31
+
32
+ def ask_specs
33
+ tile_height =
34
+ @cli.ask('Tile height? ', ::Integer) do |q|
35
+ q.default = 0
36
+ q.in = 1..256
37
+ end
38
+ tile_width =
39
+ @cli.ask('Tile width? ', ::Integer) do |q|
40
+ q.default = 0
41
+ q.in = 1..256
42
+ end
43
+ margin = @cli.ask('Margin? ', ::Integer) { |q| q.default = 0 }
44
+ offset_top = @cli.ask('Top Offset? ', ::Integer) { |q| q.default = 0 }
45
+ offset_left = @cli.ask('Left Offset? ', ::Integer) { |q| q.default = 0 }
46
+
47
+ [tile_height, tile_width, margin, offset_top, offset_left]
48
+ end
49
+
50
+ def load_specs_from_file(file_path)
51
+ @logger.info("Extracting specs from '#{file_path}'")
52
+ specs = ::YAML.load_file(file_path)
53
+
54
+ begin
55
+ tile_height = specs['specs']['details']['tile_height']
56
+ tile_width = specs['specs']['details']['tile_width']
57
+ margin = specs['specs']['details']['margin']
58
+ offset_top = specs['specs']['details']['offset_top']
59
+ offset_left = specs['specs']['details']['offset_left']
60
+ rescue ::NoMethodError
61
+ raise(::StandardError, 'Invalid specs file')
62
+ end
63
+ [tile_height, tile_width, margin, offset_top, offset_left]
64
+ end
65
+ end
@@ -2,6 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module ::TilesetTooling
5
- VERSION = '0.0.2'
5
+ VERSION = '0.1.0'
6
6
  public_constant :VERSION
7
7
  end
@@ -5,23 +5,30 @@ require 'test_helper'
5
5
 
6
6
  class ::TestInsertBleed < ::Test::Unit::TestCase
7
7
  def test_margin_required
8
- input, = get_png_data('simple_no_margin.png')
9
- command = ::TilesetTooling::Commands::InsertBleed.new({}, [input])
10
- command.expects(:ask_specs).returns([16, 16, 0, 0, 0])
8
+ input, expected = get_png_data('simple_no_margin.png')
9
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
10
+ output = output_file_path
11
+ options = { output: output }
12
+ args = [input]
13
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
14
+ specs_loader.expects(:ask_specs).returns([16, 16, 0, 0, 0])
11
15
  command.unpack!
12
-
13
- assert_raise ::StandardError, 'Current implementation needs an existing margin' do
14
- command.run
15
- end
16
+ command.run
17
+ assert ::File.exist?(expected)
18
+ assert ::File.exist?(output)
19
+ output_signature = ::TilesetTooling::Utils.image_signature(output)
20
+ expected_signature = ::TilesetTooling::Utils.image_signature(expected)
21
+ assert_equal(expected_signature, output_signature)
16
22
  end
17
23
 
18
24
  def test_simple_file
19
25
  input, expected = get_png_data('simple_with_margin.png')
26
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
20
27
  output = output_file_path
21
28
  options = { output: output }
22
29
  args = [input]
23
- command = ::TilesetTooling::Commands::InsertBleed.new(options, args)
24
- command.expects(:ask_specs).returns([16, 16, 1, 0, 0])
30
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
31
+ specs_loader.expects(:ask_specs).returns([16, 16, 1, 0, 0])
25
32
  command.unpack!
26
33
  command.run
27
34
  assert ::File.exist?(expected)
@@ -33,10 +40,11 @@ class ::TestInsertBleed < ::Test::Unit::TestCase
33
40
 
34
41
  def test_simple_file_with_specs
35
42
  input, expected = get_png_data('simple_with_specs.png')
43
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
36
44
  output = output_file_path
37
45
  options = { output: output }
38
46
  args = [input]
39
- command = ::TilesetTooling::Commands::InsertBleed.new(options, args)
47
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
40
48
  command.unpack!
41
49
  command.run
42
50
  assert ::File.exist?(expected)
@@ -48,10 +56,11 @@ class ::TestInsertBleed < ::Test::Unit::TestCase
48
56
 
49
57
  def test_simple_file_with_bad_specs
50
58
  input, = get_png_data('simple_with_bad_specs.png')
59
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
51
60
  output = output_file_path
52
61
  options = { output: output }
53
62
  args = [input]
54
- command = ::TilesetTooling::Commands::InsertBleed.new(options, args)
63
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
55
64
  command.unpack!
56
65
  assert_raise ::StandardError, 'Invalid specs file' do
57
66
  command.run
@@ -60,11 +69,12 @@ class ::TestInsertBleed < ::Test::Unit::TestCase
60
69
 
61
70
  def test_simple_file_with_skip_specs
62
71
  input, expected = get_png_data('simple_with_bad_specs.png')
72
+ specs_loader = ::TilesetTooling::Utils::SpecsLoader.new
63
73
  output = output_file_path
64
74
  options = { output: output, 'skip-specs': true }
65
75
  args = [input]
66
- command = ::TilesetTooling::Commands::InsertBleed.new(options, args)
67
- command.expects(:ask_specs).returns([16, 16, 1, 0, 0])
76
+ command = ::TilesetTooling::Commands::InsertBleed.new(options, args, specs_loader)
77
+ specs_loader.expects(:ask_specs).returns([16, 16, 1, 0, 0])
68
78
  command.unpack!
69
79
  command.run
70
80
  assert ::File.exist?(expected)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tileset_tooling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Sebastien Gelinas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-14 00:00:00.000000000 Z
11
+ date: 2020-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aruba
@@ -263,13 +263,17 @@ files:
263
263
  - lib/tileset_tooling/commands.rb
264
264
  - lib/tileset_tooling/commands/insert_bleed.rb
265
265
  - lib/tileset_tooling/data.rb
266
+ - lib/tileset_tooling/data/point.rb
266
267
  - lib/tileset_tooling/data/tile.rb
267
268
  - lib/tileset_tooling/data/tileset.rb
268
269
  - lib/tileset_tooling/data/types.rb
269
270
  - lib/tileset_tooling/utils.rb
271
+ - lib/tileset_tooling/utils/common.rb
272
+ - lib/tileset_tooling/utils/specs_loader.rb
270
273
  - lib/tileset_tooling/version.rb
271
274
  - test/commands/insert_bleed_test.rb
272
275
  - test/data/UIpackSheet_transparent.png
276
+ - test/data/expected/simple_no_margin.png
273
277
  - test/data/expected/simple_with_bad_specs.png
274
278
  - test/data/expected/simple_with_margin.png
275
279
  - test/data/expected/simple_with_specs.png