fml 0.2.1 → 0.2.2
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.
- 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
|