mooncats 1.0.1 → 1.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: 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