fml 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/fml2dae.rb +2 -2
- data/fml.gemspec +2 -2
- data/lib/config.yml +0 -2
- data/lib/floorplanner.rb +0 -6
- data/lib/floorplanner/asset.rb +2 -2
- data/lib/floorplanner/collada_export.rb +5 -5
- data/lib/floorplanner/design.rb +20 -21
- data/lib/floorplanner/document.rb +35 -8
- data/lib/floorplanner/wall_builder.rb +3 -3
- data/tasks/github-gem.rake +32 -19
- data/views/design.dae.erb +7 -7
- metadata +26 -13
data/bin/fml2dae.rb
CHANGED
data/fml.gemspec
CHANGED
data/lib/config.yml
CHANGED
@@ -2,8 +2,6 @@ content_base_url: http://cdn.floorplanner.com/assets/
|
|
2
2
|
dae_cache_path: /home/skrat/workspace/floorplanner/fml2dae_cache/
|
3
3
|
area_textures_path: /home/skrat/workspace/floorplanner/fml2dae_cache/textures_2d/
|
4
4
|
|
5
|
-
wall_height: 2.2
|
6
|
-
wall_thickness: 0.25
|
7
5
|
geom_snap: 0.1
|
8
6
|
uniq_snap: 0.0000005
|
9
7
|
openings:
|
data/lib/floorplanner.rb
CHANGED
@@ -4,7 +4,6 @@ require 'find'
|
|
4
4
|
require 'open-uri'
|
5
5
|
require 'net/http'
|
6
6
|
require 'fileutils'
|
7
|
-
require 'logger'
|
8
7
|
|
9
8
|
require 'rubygems'
|
10
9
|
require 'zip/zip'
|
@@ -13,11 +12,6 @@ require 'xml'
|
|
13
12
|
$LOAD_PATH.push(File.dirname(__FILE__))
|
14
13
|
|
15
14
|
module Floorplanner
|
16
|
-
|
17
|
-
Log = Logger.new STDOUT
|
18
|
-
Log.level = Logger::WARN
|
19
|
-
Log.datetime_format = "%Y-%m-%d %H:%M:%S "
|
20
|
-
|
21
15
|
def self.config
|
22
16
|
@@config ||= YAML.load_file(File.join(File.dirname(__FILE__),'config.yml'))
|
23
17
|
end
|
data/lib/floorplanner/asset.rb
CHANGED
@@ -19,11 +19,11 @@ module Floorplanner
|
|
19
19
|
|
20
20
|
cached_path = File.join(CACHE_PATH,asset_id)
|
21
21
|
if File.exists?(cached_path)
|
22
|
-
|
22
|
+
$stderr.puts("Cached asset: %s" % asset_id)
|
23
23
|
@kmz = Keyhole::Archive.new(cached_path)
|
24
24
|
Asset.new(asset_id,asset_title,@kmz)
|
25
25
|
else
|
26
|
-
|
26
|
+
$stderr.puts("Downloading asset: %s" % asset_url)
|
27
27
|
cached = File.new(cached_path,'w')
|
28
28
|
remote = open(asset_url)
|
29
29
|
cached.write(remote.read)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Floorplanner
|
2
2
|
class Document
|
3
3
|
|
4
|
-
def to_dae(out_path,xrefs=false)
|
5
|
-
@design = Design.new(@xml)
|
4
|
+
def to_dae(design_id,out_path,xrefs=false)
|
5
|
+
@design = Design.new(@xml,design_id)
|
6
6
|
@design.build_geometries
|
7
7
|
@design.save_textures(File.dirname(out_path)) unless xrefs
|
8
8
|
dae = File.new(out_path,'w')
|
@@ -13,7 +13,7 @@ module Floorplanner
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module ColladaExport
|
16
|
-
DESIGN_QUERY = "/design"
|
16
|
+
DESIGN_QUERY = "/project/floors/floor/designs/design[id='%s']"
|
17
17
|
ASSET_QUERY = DESIGN_QUERY+"/assets/asset[@id='%s']"
|
18
18
|
ASSETS_QUERY = DESIGN_QUERY+"/assets/asset"
|
19
19
|
OBJECTS_QUERY = DESIGN_QUERY+"/objects/object"
|
@@ -37,7 +37,7 @@ module Floorplanner
|
|
37
37
|
def assets
|
38
38
|
return @assets if @assets
|
39
39
|
@assets = {}
|
40
|
-
@xml.find(ASSETS_QUERY).each do |asset_node|
|
40
|
+
@xml.find(ASSETS_QUERY % @design_id).each do |asset_node|
|
41
41
|
asset_id = asset_node.attributes['id']
|
42
42
|
name = asset_node.find('name').first.content
|
43
43
|
url3d = asset_node.find('url3d').first
|
@@ -54,7 +54,7 @@ module Floorplanner
|
|
54
54
|
|
55
55
|
def objects
|
56
56
|
result = []
|
57
|
-
@xml.find(OBJECTS_QUERY).each do |object|
|
57
|
+
@xml.find(OBJECTS_QUERY % @design_id).each do |object|
|
58
58
|
begin
|
59
59
|
refid = object.find('asset').first.attributes['refid']
|
60
60
|
next unless assets[refid]
|
data/lib/floorplanner/design.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Floorplanner
|
2
2
|
class Design
|
3
|
-
DESIGN_QUERY = "/design"
|
3
|
+
DESIGN_QUERY = "/project/floors/floor/designs/design[id='%s']"
|
4
|
+
DESIGN_N_QUERY = "/project/floors/floor/designs/design[name='%s']"
|
4
5
|
ASSET_QUERY = DESIGN_QUERY+"/assets/asset[@id='%s']"
|
5
6
|
ASSET_URL2D = ASSET_QUERY+"/url2d"
|
6
7
|
LINES_QUERY = DESIGN_QUERY+"/lines/line"
|
@@ -16,13 +17,18 @@ module Floorplanner
|
|
16
17
|
##
|
17
18
|
# Constructs new floorplan design from FML
|
18
19
|
##
|
19
|
-
def initialize(fml)
|
20
|
+
def initialize(fml,design_id)
|
20
21
|
begin
|
21
22
|
@xml = fml
|
22
|
-
|
23
|
+
unless fml.find(DESIGN_QUERY % design_id).length.zero?
|
24
|
+
@design_id = design_id
|
25
|
+
else
|
26
|
+
@design_id = fml.find(DESIGN_N_QUERY % design_id).first.find("id").first.content
|
27
|
+
end
|
28
|
+
@name = @xml.find(NAME_QUERY % @design_id).first.content
|
23
29
|
@author = "John Doe" # TODO from <author> element if included in FML
|
24
30
|
rescue NoMethodError
|
25
|
-
|
31
|
+
$stderr.puts "Can't find Design with ID or name: %s" % design_id
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
@@ -31,18 +37,13 @@ module Floorplanner
|
|
31
37
|
##
|
32
38
|
def build_geometries
|
33
39
|
@areas = AreaBuilder.new do |b|
|
34
|
-
@xml.find(AREAS_QUERY).each do |area|
|
35
|
-
name = area.find('name').first
|
36
|
-
|
37
|
-
color = area.find('color').first
|
38
|
-
color = color.content if color
|
40
|
+
@xml.find(AREAS_QUERY % @design_id).each do |area|
|
41
|
+
name = area.find('name').first.content
|
42
|
+
color = area.find('color').first.content
|
39
43
|
type = area.find('type').first.content
|
40
44
|
|
41
|
-
asset_id = area.find('asset').first
|
42
|
-
|
43
|
-
if asset_id
|
44
|
-
texture_url = @xml.find(ASSET_URL2D % [asset_id]).first.content
|
45
|
-
end
|
45
|
+
asset_id = area.find('asset').first.attributes['refid']
|
46
|
+
texture_url = @xml.find(ASSET_URL2D % [@design_id,asset_id]).first.content
|
46
47
|
|
47
48
|
vertices = Array.new
|
48
49
|
area.find('points').first.content.split(',').each do |str_v|
|
@@ -65,13 +66,11 @@ module Floorplanner
|
|
65
66
|
end
|
66
67
|
min_height = 10
|
67
68
|
@walls = WallBuilder.new do |b|
|
68
|
-
@xml.find(LINES_QUERY).each do |line|
|
69
|
+
@xml.find(LINES_QUERY % @design_id).each do |line|
|
69
70
|
floats = line.find('points').first.get_floats
|
70
71
|
|
71
|
-
thickness = line.find('thickness').first
|
72
|
-
|
73
|
-
height = line.find('height').first
|
74
|
-
height = height ? height.content.to_f : Floorplanner.config['wall_height']
|
72
|
+
thickness = line.find('thickness').first.content.to_f
|
73
|
+
height = line.find('height').first.content.to_f
|
75
74
|
|
76
75
|
# TODO: fix this in Flash app
|
77
76
|
floats[1] *= -1.0; floats[4] *= -1.0
|
@@ -87,7 +86,7 @@ module Floorplanner
|
|
87
86
|
@areas.update min_height
|
88
87
|
|
89
88
|
@walls.prepare
|
90
|
-
@xml.find(OPENINGS_QUERY).each do |opening|
|
89
|
+
@xml.find(OPENINGS_QUERY % @design_id).each do |opening|
|
91
90
|
pos_floats = opening.find('points').first.get_floats
|
92
91
|
|
93
92
|
# TODO: fix y coord in Flash app
|
@@ -98,7 +97,7 @@ module Floorplanner
|
|
98
97
|
size = Geom::Number3D.new(*size_floats)
|
99
98
|
|
100
99
|
asset_id = opening.find('asset').first.attributes['refid']
|
101
|
-
asset = @xml.find(ASSET_QUERY % [asset_id]).first
|
100
|
+
asset = @xml.find(ASSET_QUERY % [@design_id,asset_id]).first
|
102
101
|
type = asset.find('url2d').first.content.match(/door/i) ? Opening3D::TYPE_DOOR : Opening3D::TYPE_WINDOW
|
103
102
|
@walls.opening(position,size,type)
|
104
103
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Floorplanner
|
2
2
|
|
3
3
|
class Document
|
4
|
-
|
5
4
|
POINTS_QUERY = "/project/floors/floor/designs/design/area/line/points"
|
6
5
|
LINE_POINTS_REGEXP = /^((\s*[-+]?[0-9]*\.?[0-9]+\s+){5,8}\s*[-+]?[0-9]*\.?[0-9]+\s*?(?:,)?)*$/
|
7
6
|
|
@@ -10,11 +9,11 @@ module Floorplanner
|
|
10
9
|
end
|
11
10
|
|
12
11
|
def self.validate(doc)
|
13
|
-
schema = XML::
|
14
|
-
XML::Document.file(File.join(File.dirname(__FILE__), "..", "..", "xml", "fml
|
12
|
+
schema = XML::RelaxNG.document(
|
13
|
+
XML::Document.file(File.join(File.dirname(__FILE__), "..", "..", "xml", "fml.rng"))
|
15
14
|
)
|
16
15
|
doc = XML::Document.file(doc) if doc.instance_of?(String)
|
17
|
-
doc.
|
16
|
+
doc.validate_relaxng(schema) do |message,error|
|
18
17
|
# TODO throw an exception
|
19
18
|
puts message if error
|
20
19
|
end
|
@@ -34,8 +33,16 @@ module Floorplanner
|
|
34
33
|
|
35
34
|
class DesignDocument
|
36
35
|
|
37
|
-
def initialize(
|
38
|
-
|
36
|
+
def initialize(fml)
|
37
|
+
if fml.kind_of? String # filename
|
38
|
+
@xml = XML::Document.file(fml)
|
39
|
+
elsif fml.kind_of? XML::Document
|
40
|
+
@xml = fml
|
41
|
+
elsif fml.respond_to?(:read) # IO
|
42
|
+
@xml = XML::Document.io(fml)
|
43
|
+
else
|
44
|
+
raise ArgumentError.new("values must be one of: filename, IO, XML::Document")
|
45
|
+
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def update_heights(new_height)
|
@@ -60,8 +67,28 @@ module Floorplanner
|
|
60
67
|
end
|
61
68
|
end
|
62
69
|
|
63
|
-
def
|
64
|
-
@xml.
|
70
|
+
def update_thumb_2d_url(thumb_2d_url)
|
71
|
+
if thumb_node = @xml.find_first('/design/thumb-2d-url')
|
72
|
+
thumb_node.content = thumb_2d_url
|
73
|
+
elsif design_node = @xml.find_first('/design')
|
74
|
+
thumb_node = XML::Node.new('thumb-2d-url')
|
75
|
+
thumb_node.content = thumb_2d_url
|
76
|
+
design_node << thumb_node
|
77
|
+
else
|
78
|
+
raise "Cannot update the 2D thumb URL!"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def save(path)
|
83
|
+
@xml.save path
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_xml
|
87
|
+
@xml
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
@xml.to_s
|
65
92
|
end
|
66
93
|
end
|
67
94
|
|
@@ -111,7 +111,7 @@ module Floorplanner
|
|
111
111
|
@faces.concat(wall.faces)
|
112
112
|
end
|
113
113
|
|
114
|
-
|
114
|
+
$stderr.puts "Walls Vertices before: #{@vertices.length.to_s}"
|
115
115
|
# remove same instances
|
116
116
|
@vertices.uniq!
|
117
117
|
# remove same vertices
|
@@ -120,8 +120,8 @@ module Floorplanner
|
|
120
120
|
old.each do |v|
|
121
121
|
@vertices.push(v) unless @vertices.include?(v) # find_vertex(@vertices,v) #
|
122
122
|
end
|
123
|
-
|
124
|
-
|
123
|
+
$stderr.puts "Walls Vertices: #{@vertices.length.to_s}"
|
124
|
+
$stderr.puts "Walls Faces : #{@faces.length.to_s}"
|
125
125
|
end
|
126
126
|
|
127
127
|
# make use of cache
|
data/tasks/github-gem.rake
CHANGED
@@ -119,19 +119,20 @@ module GithubGem
|
|
119
119
|
checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
|
120
120
|
checks.unshift('spec:basic') if has_specs?
|
121
121
|
checks.unshift('test:basic') if has_tests?
|
122
|
-
checks.push << [:check_rubyforge] if gemspec.rubyforge_project
|
122
|
+
# checks.push << [:check_rubyforge] if gemspec.rubyforge_project
|
123
123
|
|
124
124
|
desc "Perform all checks that would occur before a release"
|
125
125
|
task(:release_checks => checks)
|
126
126
|
|
127
|
-
release_tasks = [:release_checks, :set_version, :build, :github_release]
|
128
|
-
release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
|
127
|
+
release_tasks = [:release_checks, :set_version, :build, :github_release, :gemcutter_release]
|
128
|
+
# release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
|
129
129
|
|
130
130
|
desc "Release a new verison of the gem"
|
131
131
|
task(:release => release_tasks) { release_task }
|
132
132
|
|
133
|
-
task(:check_rubyforge) { check_rubyforge_task }
|
134
|
-
task(:rubyforge_release) { rubyforge_release_task }
|
133
|
+
# task(:check_rubyforge) { check_rubyforge_task }
|
134
|
+
# task(:rubyforge_release) { rubyforge_release_task }
|
135
|
+
task(:gemcutter_release) { gemcutter_release_task }
|
135
136
|
task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
|
136
137
|
task(:tag_version) { tag_version_task }
|
137
138
|
task(:commit_modified_files) { commit_modified_files_task }
|
@@ -179,7 +180,7 @@ module GithubGem
|
|
179
180
|
|
180
181
|
# Checks whether the current branch is not diverged from the remote branch
|
181
182
|
def check_not_diverged_task
|
182
|
-
raise "The current branch is diverged from the remote branch!" if git.log.between('HEAD', git.
|
183
|
+
raise "The current branch is diverged from the remote branch!" if git.log.between('HEAD', git.remote(remote).branch(remote_branch).gcommit).any?
|
183
184
|
end
|
184
185
|
|
185
186
|
# Checks whether the repository status ic clean
|
@@ -215,18 +216,22 @@ module GithubGem
|
|
215
216
|
git.push(remote, remote_branch, true)
|
216
217
|
end
|
217
218
|
|
218
|
-
# Checks whether Rubyforge is configured properly
|
219
|
-
def check_rubyforge_task
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
226
|
-
|
227
|
-
# Task to release the .gem file toRubyforge.
|
228
|
-
def rubyforge_release_task
|
229
|
-
|
219
|
+
# # Checks whether Rubyforge is configured properly
|
220
|
+
# def check_rubyforge_task
|
221
|
+
# # Login no longer necessary when using rubyforge 2.0.0 gem
|
222
|
+
# # raise "Could not login on rubyforge!" unless `rubyforge login 2>&1`.strip.empty?
|
223
|
+
# output = `rubyforge names`.split("\n")
|
224
|
+
# raise "Rubyforge group not found!" unless output.any? { |line| %r[^groups\s*\:.*\b#{Regexp.quote(gemspec.rubyforge_project)}\b.*] =~ line }
|
225
|
+
# raise "Rubyforge package not found!" unless output.any? { |line| %r[^packages\s*\:.*\b#{Regexp.quote(gemspec.name)}\b.*] =~ line }
|
226
|
+
# end
|
227
|
+
|
228
|
+
# # Task to release the .gem file toRubyforge.
|
229
|
+
# def rubyforge_release_task
|
230
|
+
# sh 'rubyforge', 'add_release', gemspec.rubyforge_project, gemspec.name, gemspec.version.to_s, "pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
231
|
+
# end
|
232
|
+
|
233
|
+
def gemcutter_release_task
|
234
|
+
sh "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
|
230
235
|
end
|
231
236
|
|
232
237
|
# Gem release task.
|
@@ -308,7 +313,15 @@ module GithubGem
|
|
308
313
|
response = http.get(path)
|
309
314
|
open(__FILE__, "w") { |file| file.write(response.body) }
|
310
315
|
end
|
311
|
-
|
316
|
+
|
317
|
+
relative_file = File.expand_path(__FILE__).sub(%r[^#{git.dir.path}/], '')
|
318
|
+
if git.status[relative_file] && git.status[relative_file].type == 'M'
|
319
|
+
git.add(relative_file)
|
320
|
+
git.commit("Updated to latest gem release management tasks.")
|
321
|
+
puts "Updated to latest version of gem release management tasks."
|
322
|
+
else
|
323
|
+
puts "Release managament tasks already are at the latest version."
|
324
|
+
end
|
312
325
|
end
|
313
326
|
|
314
327
|
end
|
data/views/design.dae.erb
CHANGED
@@ -16,6 +16,8 @@
|
|
16
16
|
<technique_common>
|
17
17
|
<perspective>
|
18
18
|
<yfov>70</yfov>
|
19
|
+
<znear>0.1</znear>
|
20
|
+
<zfar>100.0</zfar>
|
19
21
|
</perspective>
|
20
22
|
</technique_common>
|
21
23
|
</optics>
|
@@ -334,6 +336,7 @@
|
|
334
336
|
<resolution>800 600</resolution>
|
335
337
|
<aa>0 2</aa>
|
336
338
|
<filter>gaussian</filter>
|
339
|
+
<sampler>ipr</sampler>
|
337
340
|
</image>
|
338
341
|
<trace_depths>
|
339
342
|
<diffuse>4</diffuse>
|
@@ -346,25 +349,22 @@
|
|
346
349
|
<samples>64</samples>
|
347
350
|
<maxdist>3.0 </maxdist>
|
348
351
|
</gi>
|
349
|
-
<
|
350
|
-
<color>1.0 1.0 1.0</color>
|
351
|
-
</background>
|
352
|
-
<!--sunsky>
|
352
|
+
<sunsky>
|
353
353
|
<up>0 0 1</up>
|
354
354
|
<east>1 0 0</east>
|
355
355
|
<sundir>0.2 0.4 0.7</sundir>
|
356
356
|
<ground>1 1 1</ground>
|
357
|
-
</sunsky
|
357
|
+
</sunsky>
|
358
358
|
</technique>
|
359
359
|
</extra>
|
360
|
-
|
360
|
+
<node id="Camera" name="Camera">
|
361
361
|
<lookat>
|
362
362
|
9.0 -1.0 1.4
|
363
363
|
8.0 -2.0 1.4
|
364
364
|
0.0 0.0 1.0
|
365
365
|
</lookat>
|
366
366
|
<instance_camera url="#main-cam"/>
|
367
|
-
</node
|
367
|
+
</node>
|
368
368
|
<node id="Walls" name="Walls">
|
369
369
|
<instance_geometry url="#walls-geom">
|
370
370
|
<bind_material>
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 2
|
9
|
+
version: 0.2.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Dusan Maliarik
|
@@ -9,29 +14,33 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-04-26 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: libxml-ruby
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
23
29
|
version: "0"
|
24
|
-
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
25
32
|
- !ruby/object:Gem::Dependency
|
26
33
|
name: rubyzip
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - ">="
|
32
38
|
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
33
41
|
version: "0"
|
34
|
-
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
35
44
|
description: Floor plan document toolkit
|
36
45
|
email: dusan.maliarik@gmail.com
|
37
46
|
executables:
|
@@ -98,18 +107,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
107
|
requirements:
|
99
108
|
- - ">="
|
100
109
|
- !ruby/object:Gem::Version
|
110
|
+
segments:
|
111
|
+
- 0
|
101
112
|
version: "0"
|
102
|
-
version:
|
103
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
114
|
requirements:
|
105
115
|
- - ">="
|
106
116
|
- !ruby/object:Gem::Version
|
117
|
+
segments:
|
118
|
+
- 1
|
119
|
+
- 3
|
120
|
+
- 0
|
107
121
|
version: 1.3.0
|
108
|
-
version:
|
109
122
|
requirements: []
|
110
123
|
|
111
124
|
rubyforge_project:
|
112
|
-
rubygems_version: 1.3.
|
125
|
+
rubygems_version: 1.3.6
|
113
126
|
signing_key:
|
114
127
|
specification_version: 2
|
115
128
|
summary: Floorplanner.com FML document toolkit
|