oozby 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/oozby +17 -5
- data/lib/oozby.rb +1 -0
- data/lib/oozby/base.rb +16 -4
- data/lib/oozby/environment.rb +60 -2
- data/lib/oozby/method_preprocessor.rb +136 -8
- data/lib/oozby/render.rb +5 -1
- data/lib/oozby/version.rb +7 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5011b1b0b04f3a797f17d23572edc2bcefab387c
|
4
|
+
data.tar.gz: 20e1ce49a8c42a847bb40930d4c76b041674e85b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad55acc6736bbcd0c1fdc4c41b22daacbcae995dd9c915c7c95aac4a24038fbe66db4cfa622c0eacb3b8a133957a005a3642c2e5a8b56c3a5c6496c99f9b07fe
|
7
|
+
data.tar.gz: 1f47fca1a937a05c199686a62007b8f7246dde56112278fa9bfc34ee201eb165ade3da96e092795d62a4dd5fdf7caa68d3b465d1ddd20df68f9e12bc094b20ef
|
data/bin/oozby
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
$:.unshift File.dirname(__FILE__) + "/../lib"
|
3
2
|
require 'thor'
|
4
3
|
require 'listen'
|
5
4
|
require 'pp'
|
6
|
-
require 'oozby'
|
5
|
+
require File.join(__dir__, '..', 'lib', 'oozby')
|
6
|
+
|
7
|
+
# motivational exit messages!
|
8
|
+
$quit_message = {
|
9
|
+
'0.2.2' => "Have a nice day!",
|
10
|
+
'0.2.3' => "You're a superstar!",
|
11
|
+
'0.2.4' => "Keep up the great work!",
|
12
|
+
'0.2.5' => "Nice job!",
|
13
|
+
'0.2.6' => "It was a pleasure working with you!"
|
14
|
+
}
|
7
15
|
|
8
16
|
class OozbyUtility < Thor
|
9
17
|
desc "compile some#{File::SEPARATOR}folder", "The Oozby Utility searches a directory and compiles all the .oozby files it finds, creating identically named files with .scad stuck on the end, translated in to OpenSCAD nonsense. Open those files in OpenSCAD app and enable Automatic Reload and Compile in the Design menu, then get to work."
|
@@ -14,6 +22,9 @@ class OozbyUtility < Thor
|
|
14
22
|
def compile path
|
15
23
|
if File.file? path
|
16
24
|
ooz = Oozby.new
|
25
|
+
ooz.filter_errors = !options[:verbose]
|
26
|
+
ooz.debug = options[:verbose]
|
27
|
+
|
17
28
|
begin
|
18
29
|
ooz.parse_file path
|
19
30
|
|
@@ -27,10 +38,11 @@ class OozbyUtility < Thor
|
|
27
38
|
end
|
28
39
|
|
29
40
|
puts "compiled #{File.basename(path)}"
|
30
|
-
rescue StandardError, ScriptError => err
|
41
|
+
rescue StandardError, ScriptError, NoMethodError => err
|
31
42
|
local_pwd = Dir.pwd
|
32
43
|
puts "#{err.class.name}: #{err.message.sub(local_pwd + File::SEPARATOR, '')}"
|
33
44
|
err.backtrace.each { |line| puts line.sub(local_pwd + File::SEPARATOR, '') }
|
45
|
+
puts nil, nil
|
34
46
|
end
|
35
47
|
|
36
48
|
elsif File.directory? path
|
@@ -53,7 +65,7 @@ class OozbyUtility < Thor
|
|
53
65
|
removed.each do |path|
|
54
66
|
puts "#{File.basename(path)} deleted."
|
55
67
|
if File.exists? "#{path}.scad"
|
56
|
-
File.delete("{path}.scad")
|
68
|
+
File.delete("#{path}.scad")
|
57
69
|
puts "Deleted generated .scad file for obsolete #{File.basename(path)}"
|
58
70
|
end
|
59
71
|
end
|
@@ -62,7 +74,7 @@ class OozbyUtility < Thor
|
|
62
74
|
end
|
63
75
|
rescue Interrupt => e
|
64
76
|
puts ""
|
65
|
-
puts
|
77
|
+
puts $quit_message[Oozby.version] || $quit_message.values.last
|
66
78
|
end
|
67
79
|
end
|
68
80
|
|
data/lib/oozby.rb
CHANGED
data/lib/oozby/base.rb
CHANGED
@@ -2,25 +2,37 @@ require 'pp'
|
|
2
2
|
|
3
3
|
# Oozby class loads up files and evaluates them to a syntax tree, and renders to openscad source code
|
4
4
|
class Oozby
|
5
|
+
attr_accessor :filter_errors, :debug
|
6
|
+
|
5
7
|
def initialize
|
6
8
|
@code_tree = []
|
9
|
+
@filter_errors = false
|
10
|
+
@debug = false
|
7
11
|
end
|
8
12
|
|
9
13
|
# parse oozby code in to a syntax tree
|
10
14
|
def parse code, filename: 'eval'
|
11
15
|
env = Oozby::Environment.new(ooz: self)
|
16
|
+
if File.exists? filename
|
17
|
+
current_dir = Dir.pwd
|
18
|
+
Dir.chdir File.dirname(filename)
|
19
|
+
end
|
12
20
|
|
13
21
|
# rescue block to filter out junk oozby library stuff from backtraces
|
14
22
|
begin
|
15
23
|
compiled = eval("lambda {; #{code};\n }", nil, filename)
|
16
24
|
env.instance_exec(&compiled)
|
17
|
-
rescue
|
18
|
-
warn "Recent Calls: " + env.instance_variable_get(:@method_history).last(10).reverse.inspect
|
25
|
+
rescue StandardError, NoMethodError => err
|
19
26
|
backtrace = $!.backtrace
|
20
|
-
backtrace = backtrace.select { |item| !item.include? __dir__ } unless backtrace.first.include? __dir__
|
27
|
+
#backtrace = backtrace.select { |item| !item.include? __dir__ } unless backtrace.first.include? __dir__
|
28
|
+
backtrace.delete_if { |item| item.to_s =~ /(\.rb|\/oozby):/ } if @filter_errors
|
29
|
+
|
21
30
|
raise $!, $!.message, backtrace
|
22
31
|
end
|
23
32
|
@code_tree = env._abstract_tree
|
33
|
+
|
34
|
+
ensure
|
35
|
+
Dir.chdir current_dir if current_dir
|
24
36
|
end
|
25
37
|
|
26
38
|
# parse a file containing oozby code in to a syntax tree
|
@@ -31,7 +43,7 @@ class Oozby
|
|
31
43
|
# render the last parsed oozby code in to openscad source code
|
32
44
|
def render
|
33
45
|
renderer = Oozby::Render.new(ooz: self)
|
34
|
-
renderer.render(@code_tree, clean: true).join("\n")
|
46
|
+
renderer.render(@code_tree, clean: true).join("\n") + "\n"
|
35
47
|
end
|
36
48
|
|
37
49
|
def abstract_tree
|
data/lib/oozby/environment.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'amatch' # used to find possible intended method names
|
2
|
+
|
1
3
|
class Oozby::Environment
|
2
4
|
ResolutionDefaults = {
|
3
5
|
degrees_per_fragment: 12,
|
@@ -14,8 +16,8 @@ class Oozby::Environment
|
|
14
16
|
@modifier = nil
|
15
17
|
@one_time_modifier = nil
|
16
18
|
@preprocess = true
|
17
|
-
@method_history = []
|
18
19
|
@method_preprocessor = Oozby::MethodPreprocessor.new(env: self, ooz: @parent)
|
20
|
+
@scanned_scad_files = []
|
19
21
|
end
|
20
22
|
|
21
23
|
# create a new scope that inherits from this one, and capture syntax tree created
|
@@ -44,6 +46,21 @@ class Oozby::Environment
|
|
44
46
|
end
|
45
47
|
|
46
48
|
def method_missing method_name, *args, **hash, &proc
|
49
|
+
# unless we know of this method in OpenSCAD or the preprocessor, abort!
|
50
|
+
unless @method_preprocessor.known?(method_name) or !@preprocess
|
51
|
+
# grab a list of all known methods, suggest a guess to user
|
52
|
+
known = @method_preprocessor.known
|
53
|
+
known.push(*public_methods(false))
|
54
|
+
known.delete_if { |x| x.to_s.start_with? '_' }
|
55
|
+
matcher = Amatch::Sellers.new(method_name.to_s)
|
56
|
+
suggestion = known.min_by { |item| matcher.match(item.to_s) }
|
57
|
+
|
58
|
+
warn "Called unknown method #{method_name}()"
|
59
|
+
warn "Perhaps you meant #{suggestion}()?" if suggestion
|
60
|
+
|
61
|
+
return super # continue to raise the usual error and all that
|
62
|
+
end
|
63
|
+
|
47
64
|
if proc
|
48
65
|
children = _subscope(&proc)
|
49
66
|
else
|
@@ -58,11 +75,13 @@ class Oozby::Environment
|
|
58
75
|
call_address: @ast.length
|
59
76
|
}
|
60
77
|
|
78
|
+
@ast.push(comment: "oozby code: " + JSON.generate(call)) if @parent.debug
|
79
|
+
|
61
80
|
@ast.push call
|
62
81
|
element = Oozby::Element.new(call, @ast)
|
63
82
|
@method_preprocessor.transform_call(element) if @preprocess
|
64
83
|
@one_time_modifier = nil
|
65
|
-
|
84
|
+
|
66
85
|
return element
|
67
86
|
end
|
68
87
|
|
@@ -169,7 +188,44 @@ class Oozby::Environment
|
|
169
188
|
_apply_modifier('!', &proc)
|
170
189
|
end
|
171
190
|
|
191
|
+
def require *args
|
192
|
+
file = args.first
|
193
|
+
if file.end_with? '.scad'
|
194
|
+
_require_scad_file(*args)
|
195
|
+
elsif File.exists? "#{file}.scad"
|
196
|
+
_require_scad_file("#{args.shift}.scad", *args)
|
197
|
+
else
|
198
|
+
Kernel.require(*args)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def _require_scad_file filename, execute: true
|
203
|
+
raise "OpenSCAD file #{filename} not found" unless File.exists? filename
|
204
|
+
_scan_methods_from_scad_file filename
|
205
|
+
|
206
|
+
# add include statement to resulting openscad code
|
207
|
+
@ast.push(execute: !!execute, import: filename)
|
208
|
+
end
|
172
209
|
|
210
|
+
def _scan_methods_from_scad_file filename
|
211
|
+
raise "OpenSCAD file #{filename} not found" unless File.exists? filename
|
212
|
+
data = File.read(filename)
|
213
|
+
@scanned_scad_files.push filename
|
214
|
+
|
215
|
+
# parse out method definitions to add to our environment
|
216
|
+
data.gsub!(/\/\/.+?\n/m, "\n") # filter off single line comments
|
217
|
+
data.gsub!(/\/\*.+?\*\//m, '') # filter out multiline comments
|
218
|
+
data.scan /module[ \t]([a-zA-Z_9-9]+)/ do |module_name|
|
219
|
+
@method_preprocessor.openscad_methods.push module_name.first.to_sym
|
220
|
+
end
|
221
|
+
|
222
|
+
# find any references to more files and recurse in to those
|
223
|
+
data.scan /(use|include)[ \t]\<(.+?)\>/ do |filename|
|
224
|
+
unless @scanned_scad_files.include? filename
|
225
|
+
_scan_methods_from_scad_file filename
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
173
229
|
|
174
230
|
def _apply_modifier new_modifier, &children
|
175
231
|
if children
|
@@ -185,6 +241,8 @@ class Oozby::Environment
|
|
185
241
|
|
186
242
|
# returns the abstract tree
|
187
243
|
def _abstract_tree; @ast; end
|
244
|
+
|
245
|
+
def inspect; "OozbyFile"; end
|
188
246
|
end
|
189
247
|
|
190
248
|
|
@@ -1,18 +1,49 @@
|
|
1
|
+
# The Oozby Method Preprocessor handles requests via the transform_call method
|
2
|
+
# and transforms the Oozby::Element passed in, patching in any extra features
|
3
|
+
# and trying to alert the user of obvious bugs
|
4
|
+
|
5
|
+
|
1
6
|
class Oozby::MethodPreprocessor
|
2
|
-
|
7
|
+
# never pass resolution data in to these methods - it's pointless:
|
8
|
+
NoResolution = %i(translate rotate scale mirror resize difference union intersection hull minkowski color)
|
9
|
+
# list of OpenSCAD standard methods - these can pass through without error:
|
10
|
+
DefaultOpenSCADMethods = %i(
|
11
|
+
cube sphere cylinder polyhedron
|
12
|
+
circle square polygon
|
13
|
+
scale resize rotate translate mirror multmatrix color minkowski hull
|
14
|
+
linear_extrude rotate_extrude import projection
|
15
|
+
union difference intersection render
|
16
|
+
)
|
3
17
|
|
18
|
+
attr_accessor :openscad_methods
|
19
|
+
# setup a new method preprocessor
|
4
20
|
def initialize env: nil, ooz: nil
|
5
21
|
@env = env
|
6
22
|
@parent = ooz
|
23
|
+
@openscad_methods = DefaultOpenSCADMethods.dup
|
7
24
|
end
|
8
25
|
|
26
|
+
# accepts an Oozby::Element and transforms it according to the processors' rules
|
9
27
|
def transform_call(call_info)
|
10
28
|
send("_#{call_info.method}", call_info) if respond_to? "_#{call_info.method}"
|
11
29
|
resolution call_info unless NoResolution.include? call_info.method # apply resolution settings from scope
|
12
30
|
return call_info
|
13
31
|
end
|
14
32
|
|
15
|
-
#
|
33
|
+
# does this processor know of a method named whatever?
|
34
|
+
def known? name
|
35
|
+
return true if respond_to? "_#{name}"
|
36
|
+
return @openscad_methods.include? name.to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
# array of all known method names
|
40
|
+
def known
|
41
|
+
list = @openscad_methods.dup
|
42
|
+
list.push *public_methods(false).select { |method_name| method_name.to_s.start_with? '_' }.map { |x| x.to_s.sub(/_/, '').to_sym }
|
43
|
+
list.uniq
|
44
|
+
end
|
45
|
+
|
46
|
+
# allow method to take x, y, z named args instead of array, with defaults to 0
|
16
47
|
def xyz_to_array(info, default: 0, arg: false, depth: true)
|
17
48
|
if [:x, :y, :z].any? { |name| info[:named_args].include? name }
|
18
49
|
|
@@ -42,12 +73,12 @@ class Oozby::MethodPreprocessor
|
|
42
73
|
end
|
43
74
|
end
|
44
75
|
|
45
|
-
# layout defaults like center
|
76
|
+
# layout defaults like {center: true}
|
46
77
|
def layout_defaults(info)
|
47
78
|
info[:named_args] = @env.defaults.dup.merge(info[:named_args])
|
48
79
|
end
|
49
80
|
|
50
|
-
# apply resolution settings to
|
81
|
+
# apply resolution settings to element
|
51
82
|
ResolutionLookupTable = {degrees_per_fragment: :"$fa", minimum: :"$fs", fragments: :"$fn"}
|
52
83
|
def resolution(info)
|
53
84
|
res = @env.resolution
|
@@ -73,6 +104,12 @@ class Oozby::MethodPreprocessor
|
|
73
104
|
end
|
74
105
|
end
|
75
106
|
|
107
|
+
# general processing of arguments:
|
108
|
+
# -o> Friendly names - use radius instead of r if you like
|
109
|
+
# -o> Ranges - can specify radius: 5...10 instead of r1: 5, r2: 10
|
110
|
+
# -o> Make h/height consistent (either works everywhere)
|
111
|
+
# -o> Support inner radius, when number of sides is specified
|
112
|
+
# -o> Specify diameter and have it halved automatically
|
76
113
|
def expanded_names(info, height_label: :h)
|
77
114
|
# let users use 'radius' as longhand for 'r'
|
78
115
|
info.named_args[:r] = info.named_args.delete(:radius) if info.named_args[:radius]
|
@@ -83,11 +120,20 @@ class Oozby::MethodPreprocessor
|
|
83
120
|
|
84
121
|
info.named_args[:"$fn"] = info.named_args.delete(:facets) if info.named_args[:facets]
|
85
122
|
info.named_args[:"$fn"] = info.named_args.delete(:fragments) if info.named_args[:fragments]
|
123
|
+
info.named_args[:"$fn"] = info.named_args.delete(:sides) if info.named_args[:sides]
|
124
|
+
|
125
|
+
info.named_args[:ir] = info.named_args.delete(:inr) if info.named_args[:inr]
|
126
|
+
info.named_args[:ir] = info.named_args.delete(:inradius) if info.named_args[:inradius]
|
127
|
+
info.named_args[:ir] = info.named_args.delete(:inner_r) if info.named_args[:inner_r]
|
128
|
+
info.named_args[:ir] = info.named_args.delete(:inner_radius) if info.named_args[:inner_radius]
|
86
129
|
|
87
130
|
# let users specify diameter instead of radius - convert it
|
88
131
|
{ diameter: :r, dia: :r, d: :r,
|
89
132
|
diameter1: :r1, diameter_1: :r1, dia1: :r1, dia_1: :r1, d1: :r1,
|
90
|
-
diameter2: :r2, diameter_2: :r2, dia2: :r2, dia_2: :r2, d2: :r2
|
133
|
+
diameter2: :r2, diameter_2: :r2, dia2: :r2, dia_2: :r2, d2: :r2,
|
134
|
+
id: :ir, inner_diameter: :ir, inner_d: :ir,
|
135
|
+
id1: :ir1, inner_diameter_1: :ir1, inner_diameter1: :ir1,
|
136
|
+
id2: :ir2, inner_diameter_2: :ir2, inner_diameter2: :ir2
|
91
137
|
}.each do |d, r|
|
92
138
|
if info.named_args.key? d
|
93
139
|
data = info.named_args.delete(d)
|
@@ -100,6 +146,24 @@ class Oozby::MethodPreprocessor
|
|
100
146
|
end
|
101
147
|
end
|
102
148
|
|
149
|
+
# process 'inner radius' bits
|
150
|
+
{ ir: :r, ir1: :r1, ir2: :r2 }.each do |ir, r|
|
151
|
+
if info.named_args.key? ir
|
152
|
+
sides = info.named_args[:"$fn"].to_i
|
153
|
+
raise "Use of inner radius requires sides/facets/fragments argument to #{info.method}()" unless sides
|
154
|
+
raise "Sides must be at least 3" unless sides >= 3
|
155
|
+
inradius = info.named_args.delete(ir)
|
156
|
+
if inradius.is_a? Range
|
157
|
+
circumradius = Range.new(inradius.first.to_f / @env.cos(180.0 / sides),
|
158
|
+
inradius.first.to_f / @env.cos(180.0 / sides),
|
159
|
+
inradius.exclude_end?)
|
160
|
+
else
|
161
|
+
circumradius = inradius.to_f / @env.cos(180.0 / sides)
|
162
|
+
end
|
163
|
+
info.named_args[r] = circumradius
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
103
167
|
# allow range for radius
|
104
168
|
if info.named_args[:r].is_a? Range
|
105
169
|
range = info.named_args.delete(:r)
|
@@ -130,6 +194,7 @@ class Oozby::MethodPreprocessor
|
|
130
194
|
end
|
131
195
|
|
132
196
|
def rounded_rect size: [1,1], center: false, r: 0.0, facets: nil
|
197
|
+
size = [size] * 2 if size.is_a? Numeric
|
133
198
|
diameter = r * 2
|
134
199
|
circle_x = (size[0] / 2.0) - r
|
135
200
|
circle_y = (size[1] / 2.0) - r
|
@@ -155,6 +220,7 @@ class Oozby::MethodPreprocessor
|
|
155
220
|
end
|
156
221
|
|
157
222
|
def rounded_cube size: [1,1,1], center: false, r: 0.0, facets: nil
|
223
|
+
size = [size] * 3 if size.is_a? Numeric
|
158
224
|
size = [size[0] || 1, size[1] || 1, size[2] || 1]
|
159
225
|
diameter = r.to_f * 2.0
|
160
226
|
|
@@ -173,7 +239,7 @@ class Oozby::MethodPreprocessor
|
|
173
239
|
inject_abstract_tree(preprocessor.rounded_rect(size: [size[2], size[1]], center: true, r: r)) }}
|
174
240
|
|
175
241
|
# fill in the corners with spheres
|
176
|
-
xr, yr, zr = size.map { |x| (x / 2) - r }
|
242
|
+
xr, yr, zr = size.map { |x| (x / 2.0) - r }
|
177
243
|
corner_coordinates = [
|
178
244
|
[ xr, yr, zr],
|
179
245
|
[ xr, yr,-zr],
|
@@ -185,14 +251,14 @@ class Oozby::MethodPreprocessor
|
|
185
251
|
[-xr,-yr,-zr]
|
186
252
|
]
|
187
253
|
preprocessor true do
|
188
|
-
resolution(fragments: (_fragments_for(radius: r).to_f / 4.0).round * 4.0) do
|
254
|
+
resolution(fragments: (_fragments_for(radius: r.to_f).to_f / 4.0).round * 4.0) do
|
189
255
|
corner_coordinates.each do |coordinate|
|
190
256
|
translate(coordinate) do
|
191
257
|
# generate sphere shape
|
192
258
|
rotate_extrude do
|
193
259
|
intersection do
|
194
260
|
circle(r: r)
|
195
|
-
translate([r, 0, 0]) { square([r * 2, r * 4], center: true) }
|
261
|
+
translate([r, 0, 0]) { square([r * 2.0, r * 4.0], center: true) }
|
196
262
|
end
|
197
263
|
end
|
198
264
|
end
|
@@ -222,6 +288,68 @@ class Oozby::MethodPreprocessor
|
|
222
288
|
}
|
223
289
|
}).first
|
224
290
|
end
|
291
|
+
|
292
|
+
# meta! construct aliases which preset some values
|
293
|
+
def self.oozby_alias from, to, extra_args = {}
|
294
|
+
define_method "_#{from}" do |info|
|
295
|
+
info.method = to
|
296
|
+
info.named_args.merge! extra_args
|
297
|
+
send("_#{to}", info) if self.respond_to? "_#{to}"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# some regular shapes - from:
|
302
|
+
# http://en.wikipedia.org/wiki/Regular_polygon#Regular_convex_polygons
|
303
|
+
polygon_names = {
|
304
|
+
triangle: 3,
|
305
|
+
equilateral_triangle: 3,
|
306
|
+
pentagon: 5,
|
307
|
+
hexagon: 6,
|
308
|
+
heptagon: 7,
|
309
|
+
octagon: 8,
|
310
|
+
nonagon: 9,
|
311
|
+
enneagon: 9,
|
312
|
+
decagon: 10,
|
313
|
+
hendecagon: 11,
|
314
|
+
undecagon: 11,
|
315
|
+
dodecagon: 12,
|
316
|
+
tridecagon: 13,
|
317
|
+
tetradecagon: 14,
|
318
|
+
pentadecagon: 15,
|
319
|
+
hexadecagon: 16,
|
320
|
+
heptadecagon: 17,
|
321
|
+
octadecagon: 18,
|
322
|
+
enneadecagon: 19,
|
323
|
+
icosagon: 20,
|
324
|
+
triacontagon: 30,
|
325
|
+
tetracontagon: 40,
|
326
|
+
pentacontagon: 50,
|
327
|
+
hexacontagon: 60,
|
328
|
+
heptacontagon: 70,
|
329
|
+
octacontagon: 80,
|
330
|
+
enneacontagon: 90,
|
331
|
+
hectogon: 100
|
332
|
+
}
|
333
|
+
polygon_names.each do |shape_name, sides|
|
334
|
+
oozby_alias shape_name, :circle, sides: sides
|
335
|
+
end
|
336
|
+
|
337
|
+
# make a polygon with an arbitrary number of sides
|
338
|
+
oozby_alias :ngon, :circle, sides: 3
|
339
|
+
# make a prism with an arbitrary number of sides
|
340
|
+
oozby_alias :prism, :cylinder, sides: 3
|
341
|
+
|
342
|
+
# triangles are an edge case
|
343
|
+
oozby_alias :triangular_prism, :cylinder, sides: 3
|
344
|
+
|
345
|
+
# for all the rest, transform the prism names automatically
|
346
|
+
polygon_names.each do |poly_name, sides|
|
347
|
+
name = poly_name.to_s
|
348
|
+
if name.end_with? 'gon'
|
349
|
+
name += 'al_prism'
|
350
|
+
oozby_alias name, :cylinder, sides: sides
|
351
|
+
end
|
352
|
+
end
|
225
353
|
end
|
226
354
|
|
227
355
|
|
data/lib/oozby/render.rb
CHANGED
@@ -35,8 +35,12 @@ class Oozby::Render
|
|
35
35
|
output.push "}"
|
36
36
|
end
|
37
37
|
|
38
|
+
elsif node.key? :comment
|
39
|
+
output.push "/* #{node[:comment]} */"
|
38
40
|
elsif node.key? :assign
|
39
|
-
output
|
41
|
+
output.push "#{node[:assign]} = #{escape(node[:value])};"
|
42
|
+
elsif node.key? :import
|
43
|
+
output.push "#{node[:execute] ? 'include' : 'use'} <#{node[:import]}>;"
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oozby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bluebie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: listen
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.18.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: amatch
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.11
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.11
|
41
55
|
description: OpenSCAD - a cad language for creating solid 3d objects, useful for CNC
|
42
56
|
and 3D Printing, is incredibly annoying. It doesn't even support variables! Oozby
|
43
57
|
is a markup builder like Markaby or XML Builder, so you can write OpenSCAD programs
|
@@ -55,6 +69,7 @@ files:
|
|
55
69
|
- lib/oozby/environment.rb
|
56
70
|
- lib/oozby/method_preprocessor.rb
|
57
71
|
- lib/oozby/render.rb
|
72
|
+
- lib/oozby/version.rb
|
58
73
|
- lib/oozby.rb
|
59
74
|
- readme.md
|
60
75
|
- license.txt
|