tileset_tooling 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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