mooncats 1.0.1 → 1.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: 2008a93c19babb5a74bb5ebc80ad37dc676fe40b43988131815b3d71ddc78b1a
4
- data.tar.gz: c0335955e826d1843c9a8579ac21e65e94800bdd62cd8f7d55e59640ec458870
3
+ metadata.gz: bf22f607c257a0cef8877f44594782f1c6f704a9c580c01af96a39d49f985209
4
+ data.tar.gz: f6b10d2506c5b3dc05477ad4d8ba18c24eada0382cbcc29fdbfa0c572a04c892
5
5
  SHA512:
6
- metadata.gz: 32e5e79b6614917d835c4312113082a75de32ea3e6ba41a11cf50e05d05b3003b0de5f64aaca260816d1fabf87939b3d50fa5ab3cf6665202fa09bbc61e389d9
7
- data.tar.gz: 7e2adae8f892f14804ee3510cd60af41d51bfd0b262308a9fdca40bd154836d6d1c7e0e1341f273ed9b1cabbee6417afdb1d78b3b0e6ddda08454af8f88320c4
6
+ metadata.gz: 4e20d5394cd29624a64d0b7a830fbf7bc0b0890c021a25c077a7c51771600b9d7187220abd2e76c5a94b2f1a50d66fae040727950fca4be859db8a821791082a
7
+ data.tar.gz: 6028eadc62a9861e3e9c5be6215ec0bb142701cffd15e88d681ce4c30cfc137df4ee102f9b09de0c41f9d1a4715771d631d488a1b49326a8fba96bf211615e08
data/Manifest.txt CHANGED
@@ -6,6 +6,7 @@ bin/mooncat
6
6
  lib/mooncats.rb
7
7
  lib/mooncats/composite.rb
8
8
  lib/mooncats/dataset.rb
9
+ lib/mooncats/design.rb
9
10
  lib/mooncats/designs.rb
10
11
  lib/mooncats/image.rb
11
12
  lib/mooncats/structs.rb
data/lib/mooncats.rb CHANGED
@@ -12,6 +12,7 @@ require 'optparse'
12
12
  require 'mooncats/version' # note: let version always go first
13
13
  require 'mooncats/designs'
14
14
  require 'mooncats/structs'
15
+ require 'mooncats/design'
15
16
  require 'mooncats/image'
16
17
  require 'mooncats/composite'
17
18
  require 'mooncats/dataset'
@@ -93,4 +94,11 @@ module Mooncats
93
94
  MoonCats = Mooncats
94
95
 
95
96
 
97
+
98
+
99
+ ###
100
+ # note: for convenience auto include Pixelart namespace!!! - why? why not?
101
+ include Pixelart
102
+
103
+
96
104
  puts Mooncats.banner # say hello
@@ -10,7 +10,7 @@ CANVAS_HEIGHT = 24
10
10
  def initialize( cols=100, rows=255 )
11
11
  @composite = ChunkyPNG::Image.new( cols*CANVAS_WIDTH,
12
12
  rows*CANVAS_HEIGHT,
13
- ChunkyPNG::Color::WHITE ) # why? why not? - use TRANSPARENT (is default?)
13
+ ChunkyPNG::Color::TRANSPARENT ) # why? why not? - use TRANSPARENT (is default?)
14
14
 
15
15
  ## todo/check - find a better name for cols/rows - why? why not?
16
16
  @cols = cols
@@ -0,0 +1,92 @@
1
+
2
+ module Mooncats
3
+
4
+
5
+ class Design
6
+ def self.find( num ) ## pass in design index number (0 to 127)
7
+ ## todo: add cache (memoize) - why? why not?
8
+ design = parse( DESIGNS[ num ] )
9
+
10
+ puts " design ##{num} (#{design.width}x#{design.height})"
11
+ ## pp design.data
12
+ ## puts
13
+
14
+ design
15
+ end
16
+
17
+
18
+
19
+ def self.parse( str )
20
+ ## support original "classic" compact single-line format
21
+ ## e.g. 00011111100000000.01113333310000000.13533333331110000....
22
+ ## note: this format needs to get rotated by 90 degree!!!
23
+ if str.start_with?( /[0-5]+\.[0-5]+\.[0-5]+/ ) ## quick (and dirty) heuristic check
24
+ data = str.split('.')
25
+
26
+ ## note: map colors encoded as a string to an array of integers - why? why not?
27
+ ## e.g. "00011111133344411"
28
+ ## =>
29
+ ## [0,0,0,1,1,1,1,1,1,3,3,3,4,4,4,1,1]
30
+ data = data.map do |row|
31
+ row.chars.map do |color|
32
+ color.to_i
33
+ end
34
+ end
35
+ data = data.transpose ## note: rotate by 90 degree!!!!!
36
+ else ## assume "modern" pixelart format
37
+ ## todo/check: delegate to pixelart parse or such - why? why not?
38
+
39
+ data = []
40
+ str.each_line do |line|
41
+ line = line.strip
42
+ next if line.empty? ## skipping empty line in pixel art source
43
+ next if line.start_with?( '#' ) ## skipping comment line in pixel art source
44
+
45
+ ## note: allow multiple spaces or tabs to separate pixel codes
46
+ data << line.split( /[ \t]+/)
47
+ end
48
+ ## todo/check: change to use strings (instead of nummbers) in the future?
49
+ ## why? why not? stay "compatible" to pixel art format/machinery?
50
+ data = data.map do |row|
51
+ row.map do |color|
52
+ color.to_i
53
+ end
54
+ end
55
+ end
56
+ new( data )
57
+ end
58
+
59
+
60
+ def initialize( data )
61
+ @data = data
62
+ end
63
+
64
+ def width
65
+ ## todo/check: use/find max - why? why not? lets you you used "unbalanced" / shortcut lines too
66
+ @data[0].size
67
+ end
68
+ def height() @data.size; end
69
+
70
+
71
+ def each_with_index( &blk )
72
+ @data.each_with_index { |row, y| blk.call( row, y ) }
73
+ end
74
+ def each( &blk )
75
+ @data.each { |row| blk.call( row ) }
76
+ end
77
+
78
+
79
+
80
+ def to_txt
81
+ buf = String.new('')
82
+
83
+ @data.each do |row|
84
+ buf << row.join( ' ' )
85
+ buf << "\n"
86
+ end
87
+ buf
88
+ end
89
+
90
+
91
+ end # class Design
92
+ end # module Mooncats
@@ -2,33 +2,6 @@
2
2
  module Mooncats
3
3
 
4
4
 
5
-
6
- ###
7
- ## todo/fix/cleanup - (re)use pixelart color helpers? possible? why? why not?
8
-
9
- class Color ## convenience helper to "abstract" ChunkyPNG usage away in "outside" (not internal) sample code
10
- def self.to_hex(color, include_alpha: false)
11
- if include_alpha
12
- '#%08x' % color
13
- else
14
- '#%06x' % [color >> 8]
15
- end
16
- end
17
-
18
- def self.rgb_to_hsl( r, g, b )
19
- rgb = ChunkyPNG::Color.rgb( r, g, b )
20
- hsl = ChunkyPNG::Color.to_hsl( rgb )
21
- hsl
22
- end
23
-
24
- def self.from_hsl( h, s, l )
25
- ChunkyPNG::Color.from_hsl( h, s, l )
26
- end
27
- end # class Color
28
-
29
-
30
-
31
-
32
5
  class Image < Pixelart::Image
33
6
 
34
7
 
@@ -81,17 +54,17 @@ def initialize( design: 0,
81
54
  end
82
55
 
83
56
  ## note: first color (index 0) is always nil (default/white or transparent)
84
- colors = [ nil ] + parse_colors( colors )
57
+ colors = [ nil ] + colors.map { |color| Pixelart::Color.parse( color ) }
85
58
 
86
59
  ## puts " colors:"
87
60
  ## pp colors
88
61
 
89
62
  img = ChunkyPNG::Image.new( design.width,
90
- design.height,
91
- ChunkyPNG::Color::TRANSPARENT ) # why? why not?
63
+ design.height,
64
+ ChunkyPNG::Color::TRANSPARENT ) # why? why not?
92
65
 
93
- design.each_with_index do |row, x|
94
- row.each_with_index do |color, y|
66
+ design.each_with_index do |row, y|
67
+ row.each_with_index do |color, x|
95
68
  if color > 0
96
69
  pixel = colors[ color ]
97
70
  img[x,y] = pixel
@@ -151,110 +124,6 @@ def self.derive_palette( r: nil, g: nil, b: nil,
151
124
  end
152
125
 
153
126
 
154
- ######
155
- # helpers
156
- def parse_colors( colors )
157
- ## convert into ChunkyPNG::Color
158
- colors.map { |color| parse_color( color ) }
159
- end
160
-
161
- def parse_color( color )
162
- if color.is_a?( Integer ) ## e.g. Assumess ChunkyPNG::Color.rgb() or such
163
- color ## pass through as is 1:1
164
- elsif color.is_a?(String)
165
- ## note: return an Integer !!! (not a Color class or such!!! )
166
- ChunkyPNG::Color.from_hex( color )
167
- else
168
- raise ArgumentError, "unknown color format; cannot parse - expected rgb hex string e.g. d3d3d3"
169
- end
170
- end
171
-
172
-
173
-
174
-
175
-
176
-
177
- class Bar ## (nested) class inside Image (e.g. Image::Bar)
178
- ## make a color bar
179
- def initialize( colors:, zoom: 24 )
180
- @bar = ChunkyPNG::Image.new( colors.size*zoom,
181
- zoom,
182
- ChunkyPNG::Color::WHITE ) # why? why not?
183
-
184
- colors.each_with_index do |color,i|
185
- zoom.times do |x|
186
- zoom.times do |y|
187
- @bar[x+zoom*i,y] = color
188
- end
189
- end
190
- end
191
- end # def initialize
192
-
193
- #####
194
- # (image) delegates
195
- ## todo/check: add some more??
196
- def save( path, constraints = {} )
197
- @bar.save( path, constraints )
198
- end
199
-
200
- def width() @bar.width; end
201
- def height() @bar.height; end
202
-
203
- ## return image ref - use a different name - why? why not?
204
- def image() @bar; end
205
- end # (nested) class Bar
206
127
  end # class Image
207
-
208
-
209
-
210
- class Design
211
- def self.find( num ) ## pass in design index number (0 to 127)
212
- ## todo: add cache (memoize) - why? why not?
213
- str = DESIGNS[ num ]
214
- design = parse( str )
215
-
216
- puts " design ##{num} (#{design.width}x#{design.height})"
217
- ## pp design.data
218
- ## puts
219
-
220
- design
221
- end
222
-
223
-
224
- def self.parse( str )
225
- data = str.split('.')
226
- new( data )
227
- end
228
-
229
- def initialize( data )
230
- ## todo: add cache (memoize) - why? why not?
231
-
232
- ## note: map colors encoded as a string to an array of integers - why? why not?
233
- ## e.g. "00011111133344411"
234
- ## =>
235
- ## [0,0,0,1,1,1,1,1,1,3,3,3,4,4,4,1,1]
236
-
237
- @data = data.map do |row|
238
- row.chars.map do |color|
239
- color.to_i
240
- end
241
- end
242
- end
243
-
244
- ## note: design data stored mirrored (data.size is the width NOT height)
245
- def width() @data.size; end
246
- def height() @data[0].size; end
247
-
248
- def data() @data; end
249
-
250
- def each_with_index( &blk )
251
- ## note: y,x is reversed - keep for now
252
- ## (todo/fix later? and "pivot" raw data on init - why? why not?)
253
- @data.each_with_index do |row, x|
254
- blk.call( row, x )
255
- end
256
- end
257
- end # class Design
258
-
259
128
  end # module Mooncats
260
129
 
@@ -11,20 +11,37 @@ POSES = [
11
11
  'Stalking', ## 11
12
12
  ]
13
13
 
14
- FACES = [
14
+
15
+ OLD_FACES = [ ## old names for face (expressions)
15
16
  'Smile', ## 00
16
17
  'Frown (Look Down)', ## 01
17
18
  'Frown (Look Up)', ## 10
18
19
  'Flat Whiskers', ## 11
19
20
  ]
20
21
 
21
- FURS = [
22
+ FACES = [ ## face expressions
23
+ 'Smiling', ## 00
24
+ 'Grumpy', ## 01
25
+ 'Pouting', ## 10
26
+ 'Shy', ## 11
27
+ ]
28
+
29
+
30
+ OLD_FURS = [ ## old names for fur (patterns)
22
31
  'Solid', ## 00
23
32
  'Striped', ## 01
24
33
  'Eyepatch', ## 10
25
34
  'Half/Half', ## 11
26
35
  ]
27
36
 
37
+ FURS = [ ## fur (patterns)
38
+ 'Pure', ## 00
39
+ 'Tabby', ## 01
40
+ 'Spotted', ## 10
41
+ 'Tortie', ## 11
42
+ ]
43
+
44
+
28
45
  FACINGS = [
29
46
  'Left', # 0
30
47
  'Right', # 1
@@ -50,12 +67,15 @@ class Metadata
50
67
  def facing
51
68
  @facing ||= FACINGS[ bits[1,1].to_i(2) ] ## use desgin > 63 instead - why? why not?
52
69
  end
53
- def face
70
+ def face ## face (expression)
54
71
  @face ||= FACES[ bits[2,2].to_i(2) ]
55
72
  end
56
- def fur
73
+ alias_method :expression, :face
74
+
75
+ def fur ## fur (pattern) - add pattern alias - why? why not?
57
76
  @fur ||= FURS[ bits[4,2].to_i(2) ]
58
77
  end
78
+
59
79
  def pose
60
80
  @poses ||= POSES[ bits[6,2].to_i(2) ] ## use design % 4 instead - why? why not?
61
81
  end
@@ -87,7 +107,10 @@ class Metadata
87
107
  def rgb() [r,g,b]; end ## add rgb shortcut helper - why? why not?
88
108
 
89
109
  def invert?() k >= 128; end
90
- def pattern() k % 64; end ## treat facing left|right as the same
110
+ alias_method :pale?, :invert?
111
+
112
+
113
+ def pattern() k % 64; end ## treat facing left|right as the same - note: conflicts with fur (pattern) - find a better/different name?
91
114
 
92
115
 
93
116
  def hue
@@ -155,6 +178,7 @@ class Metadata
155
178
 
156
179
  def facing() design.facing; end
157
180
  def face() design.face; end
181
+ alias_method :expression, :face
158
182
  def fur() design.fur; end
159
183
  def pose() design.pose; end
160
184
 
@@ -170,23 +194,25 @@ class Metadata
170
194
  # enable array-like access to - why? why not?
171
195
  def []( key )
172
196
  case key.to_sym
173
- when :id then id
174
- when :genesis then genesis?
175
- when :k then k
176
- when :r then r
177
- when :g then g
178
- when :b then b
179
- when :rgb then rgb
180
- when :invert then invert?
181
- when :hue then hue
182
- when :color then color
183
- when :design then design.to_i
184
- when :pattern then pattern
185
- when :facing then facing
186
- when :face then face
187
- when :fur then fur
188
- when :pose then pose
189
- when :year then year # note: from more via timestamp
197
+ when :id then id
198
+ when :genesis then genesis?
199
+ when :k then k
200
+ when :r then r
201
+ when :g then g
202
+ when :b then b
203
+ when :rgb then rgb
204
+ when :invert,
205
+ :pale then invert?
206
+ when :hue then hue
207
+ when :color then color
208
+ when :design then design.to_i
209
+ when :pattern then pattern
210
+ when :facing then facing
211
+ when :face,
212
+ :expression then face
213
+ when :fur then fur
214
+ when :pose then pose
215
+ when :year then year # note: from more via timestamp
190
216
  else
191
217
  @more[ key ]
192
218
  end
@@ -2,8 +2,8 @@
2
2
  module Mooncats
3
3
 
4
4
  MAJOR = 1
5
- MINOR = 0
6
- PATCH = 1
5
+ MINOR = 1
6
+ PATCH = 0
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mooncats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-25 00:00:00.000000000 Z
11
+ date: 2021-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pixelart
@@ -92,6 +92,7 @@ files:
92
92
  - lib/mooncats.rb
93
93
  - lib/mooncats/composite.rb
94
94
  - lib/mooncats/dataset.rb
95
+ - lib/mooncats/design.rb
95
96
  - lib/mooncats/designs.rb
96
97
  - lib/mooncats/image.rb
97
98
  - lib/mooncats/structs.rb