RUIC 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,164 @@
1
+ #encoding: utf-8
2
+ class UIC::Property
3
+ class << self; attr_accessor :default; end
4
+ def initialize(el); @el = el; end
5
+ def name; @name||=@el['name']; end
6
+ def type; @type||=@el['type']; end
7
+ def formal; @formal||=@el['formalName'] || @el['name']; end
8
+ def min; @el['min']; end
9
+ def max; @el['max']; end
10
+ def description; @desc||=@el['description']; end
11
+ def default; @def ||= (@el['default'] || self.class.default); end
12
+ def get(asset,slide)
13
+ if asset.slide? || asset.has_slide?(slide)
14
+ asset.presentation.get_attribute(asset.el,name,slide) || default
15
+ end
16
+ end
17
+ def set(asset,new_value,slide_name_or_index)
18
+ asset.presentation.set_attribute(asset.el,name,slide_name_or_index,new_value)
19
+ end
20
+ def inspect
21
+ "<#{type} '#{name}'>"
22
+ end
23
+
24
+ class String < self
25
+ self.default = ''
26
+ end
27
+ MultiLineString = String
28
+
29
+ class Float < self
30
+ self.default = 0.0
31
+ def get(asset,slide); super.to_f; end
32
+ end
33
+ class Long < self
34
+ self.default = 0
35
+ def get(asset,slide); super.to_i; end
36
+ end
37
+ class Boolean < self
38
+ self.default = false
39
+ def get(asset,slide); super=='True'; end
40
+ def set(asset,new_value,slide_name_or_index)
41
+ super( asset, new_value ? 'True' : 'False', slide_name_or_index )
42
+ end
43
+ end
44
+ class Vector < self
45
+ self.default = '0 0 0'
46
+ def get(asset,slide)
47
+ VectorValue.new(asset,self,slide,super)
48
+ end
49
+ def set(asset,new_value,slide_name_or_index)
50
+ new_value = new_value.join(' ') if new_value.is_a?(Array)
51
+ super( asset, new_value, slide_name_or_index )
52
+ end
53
+ end
54
+ Rotation = Vector
55
+ Color = Vector
56
+ class Image < self
57
+ self.default = nil
58
+ def get(asset,slide)
59
+ if idref = super
60
+ result = asset.presentation.asset_by_id( idref[1..-1] )
61
+ slide ? result.on_slide( slide ) : result
62
+ end
63
+ end
64
+ def set(asset,new_value,slide)
65
+ raise "Setting image attributes not yet supported"
66
+ end
67
+ end
68
+ class Texture < String
69
+ def get(asset,slide)
70
+ if path=super
71
+ path.empty? ? nil : path
72
+ end
73
+ end
74
+ end
75
+
76
+ class ObjectRef < self
77
+ self.default = nil
78
+ def get(asset,slide)
79
+ ref = super
80
+ type = :absolute
81
+ obj = nil
82
+ unless ref=='' || ref.nil?
83
+ type = ref[0]=='#' ? :absolute : :path
84
+ ref = type==:absolute ? asset.presentation.asset_by_id( ref[1..-1] ) : asset.presentation.at( ref, asset.el )
85
+ end
86
+ ObjectReference.new(asset,self,slide,ref,type)
87
+ end
88
+ def set(asset,new_object,slide)
89
+ get(asset,slide).object = new_object
90
+ end
91
+ end
92
+
93
+ class ObjectReference
94
+ attr_reader :object, :type
95
+ def initialize(asset,property,slide,object=nil,type=nil)
96
+ @asset = asset
97
+ @name = property.name
98
+ @slide = slide
99
+ @object = object
100
+ @type = type
101
+ end
102
+ def object=(new_object)
103
+ raise "ObjectRef must be set to an asset (not a #{new_object.class.name})" unless new_object.is_a?(UIC::Asset::Root)
104
+ @object = new_object
105
+ write_value!
106
+ end
107
+ def type=(new_type)
108
+ raise "ObjectRef types must be either :absolute or :path (not #{new_type.inspect})" unless [:absolute,:path].include?(new_type)
109
+ @type = new_type
110
+ write_value!
111
+ end
112
+ private
113
+ def write_value!
114
+ path = case @object
115
+ when NilClass then ""
116
+ else case @type
117
+ when :absolute then "##{@object.el['id']}"
118
+ when :path then @asset.presentation.path_to( @object.el, @asset.el ).sub(/^[^:.]+:/,'')
119
+ # when :root then @asset.presentation.path_to( @object.el ).sub(/^[^:.]+:/,'')
120
+ end
121
+ end
122
+ @asset.presentation.set_attribute( @asset.el, @name, @slide, path )
123
+ end
124
+ end
125
+
126
+ Import = String #TODO: a real class
127
+ Mesh = String #TODO: a real class
128
+ Renderable = String #TODO: a real class
129
+ Font = String #TODO: a real class
130
+ FontSize = Long
131
+
132
+ StringListOrInt = String #TODO: a real class
133
+
134
+ class VectorValue
135
+ attr_reader :x, :y, :z
136
+ def initialize(asset,property,slide,str)
137
+ @asset = asset
138
+ @property = property
139
+ @slide = slide
140
+ @x, @y, @z = str.split(/\s+/).map(&:to_f)
141
+ end
142
+ def setall
143
+ @property.set( @asset, to_s, @slide )
144
+ end
145
+ def x=(n); @x=n; setall end
146
+ def y=(n); @y=n; setall end
147
+ def z=(n); @z=n; setall end
148
+ alias_method :r, :x
149
+ alias_method :g, :y
150
+ alias_method :b, :z
151
+ alias_method :r=, :x=
152
+ alias_method :g=, :y=
153
+ alias_method :b=, :z=
154
+ def inspect
155
+ "<#{@asset.path}.#{@property.name}: #{self}>"
156
+ end
157
+ def to_s
158
+ to_a.join(' ')
159
+ end
160
+ def to_a
161
+ [x,y,z]
162
+ end
163
+ end
164
+ end
File without changes
@@ -18,15 +18,15 @@ end
18
18
 
19
19
  module UIC::ElementBacked
20
20
  attr_accessor :owner, :el
21
- def self.included(base)
22
- base.extend(ClassMethods)
23
- end
24
- module ClassMethods
21
+ def self.included(base)
22
+ base.extend(ClassMethods)
23
+ end
24
+ module ClassMethods
25
25
  def xmlattribute(name,&block)
26
26
  define_method(name){ @el[name] }
27
27
  define_method("#{name}=", &(block || ->(new_value){ @el[name]=new_value.to_s }))
28
28
  end
29
- end
29
+ end
30
30
  end
31
31
 
32
32
  module UIC::PresentableHash
@@ -301,19 +301,25 @@ class UIC::Presentation
301
301
  next if options.key?(:master) && master?(el)!= options[:master]
302
302
  asset = asset_for_el(el)
303
303
  next if options.key?(:attributes) && options[:attributes].any?{ |att,val|
304
- value = asset[att.to_s].value
305
- case val
306
- when Regexp then val !~ value.to_s
307
- when Numeric then (val-value).abs >= 0.001
308
- when Array then value.to_a.zip(val).map{ |a,b| b && (a-b).abs>=0.001 }.any?
309
- else value != val
310
- end if asset.properties[att.to_s]
304
+ if asset.properties[att.to_s]
305
+ value = asset[att.to_s].value
306
+ case val
307
+ when Regexp then val !~ value.to_s
308
+ when Numeric then (val-value).abs >= 0.001
309
+ when Array then value.to_a.zip(val).map{ |a,b| b && (a-b).abs>=0.001 }.any?
310
+ else value != val
311
+ end
312
+ end
311
313
  }
312
314
  yield asset, index+=1 if block_given?
313
315
  result << asset
314
316
  end
315
317
  end
316
318
  end
319
+
320
+ def inspect
321
+ "<#{self.class} #{File.basename(file)}>"
322
+ end
317
323
  end
318
324
 
319
325
  def UIC.Presentation( uip_path )
@@ -341,10 +347,6 @@ class UIC::Application::Presentation < UIC::Presentation
341
347
  def path_to( el, from=nil )
342
348
  "#{id}:#{super}"
343
349
  end
344
-
345
- def inspect
346
- "<presentation #{file}>"
347
- end
348
350
  end
349
351
 
350
352
  class Nokogiri::XML::Element
File without changes
@@ -1,3 +1,3 @@
1
- class RUIC
2
- VERSION = '0.0.1'
1
+ class RUIC
2
+ VERSION = '0.1.0'
3
3
  end
@@ -1,23 +1,25 @@
1
- # encoding: UTF-8
2
- $: << File.expand_path("../lib", __FILE__)
3
- require "ruic/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "RUIC"
7
- s.version = RUIC::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Gavin Kistner"]
10
- s.email = ["gavin@phrogz.net"]
11
- s.license = "MIT License"
12
- s.summary = %q{Library and DSL analyzing and manipulating UI Composer applications and presentations.}
13
- s.description = %q{RUIC is a library that understands the XML formats used by NVIDIA's "UI Composer" tool suite. In addition to APIs for analyzing and manipulating these files—the UIC portion of the library—it also includes a mini DSL for writing scripts that can be run by the `ruic` interpreter.}
14
- s.homepage = "https://github.com/Phrogz/RUIC"
15
-
16
- s.add_runtime_dependency "nokogiri", '~> 1'
17
-
18
- s.files = `git ls-files`.split("\n")
19
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
- s.require_paths = ["lib"]
22
- s.bindir = 'bin'
1
+ # encoding: UTF-8
2
+ $: << File.expand_path("../lib", __FILE__)
3
+ require "ruic/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "RUIC"
7
+ s.version = RUIC::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Gavin Kistner"]
10
+ s.email = ["gavin@phrogz.net"]
11
+ s.license = "MIT License"
12
+ s.summary = %q{Library and DSL analyzing and manipulating UI Composer applications and presentations.}
13
+ s.description = %q{RUIC is a library that understands the XML formats used by NVIDIA's "UI Composer" tool suite. In addition to APIs for analyzing and manipulating these files—the UIC portion of the library—it also includes a mini DSL for writing scripts that can be run by the `ruic` interpreter.}
14
+ s.homepage = "https://github.com/Phrogz/RUIC"
15
+
16
+ s.add_runtime_dependency "nokogiri", '~> 1'
17
+ s.add_runtime_dependency "ripl", '~> 0'
18
+ s.add_runtime_dependency "ripl-multi_line", '~> 0'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ s.bindir = 'bin'
23
25
  end
File without changes
@@ -1,39 +1,39 @@
1
- metadata 'MetaData.xml'
2
-
3
- uia 'projects/SimpleScene/SimpleScene.uia'
4
- show app.errors if app.errors?
5
-
6
- main = app.main_presentation
7
-
8
- assert main.find( type:'Model' ).length==4
9
- assert main.find( type:'Model', slide:0 ).length==3
10
- assert main.find( type:'Model', slide:1 ).length==4
11
- assert main.find( type:'Model', slide:1, master:false ).length==1
12
- assert main.find( type:'Model', attributes:{position:[-150,60,0]} ).length==2
13
- assert main.find( type:'Model', attributes:{position:[-150,60,0]} ).length==2
14
- assert main.find( type:'Model', attributes:{position:[nil,60,nil]} ).length==4
15
- assert main.find( type:'Model', attributes:{sourcepath:'#Cube'} ).length==1
16
- assert main.find( under:main/"Scene.Layer.Sphere1" ).length==1
17
- assert main.find( attributes:{name:'Material'} ).length==4
18
- assert main.find( attributes:{name:/^Sphere/} ).length==2
19
-
20
- # You can use name not as an attribute
21
- assert main.find( name:'Material' ).length==4
22
- assert main.find( name:/^Sphere/ ).length==2
23
-
24
- # Return values are in Scene graph order
25
- assert main.find.first == main/"Scene"
26
- assert main.find.last == main/"Scene.Layer.NonMaster.Material"
27
-
28
- # Any asset can be used as the 'root'
29
- sphere = main/"Scene.Layer.Sphere1"
30
- assert sphere.find.length==1
31
-
32
- # Supplying a block will iterate, including the index
33
- expected = main.find type:'Model'
34
- found = 0
35
- main.find type:'Model' do |mod,i|
36
- found += 1
37
- assert mod == expected[i]
38
- end
1
+ metadata 'MetaData.xml'
2
+
3
+ uia 'projects/SimpleScene/SimpleScene.uia'
4
+ show app.errors if app.errors?
5
+
6
+ main = app.main_presentation
7
+
8
+ assert main.find( type:'Model' ).length==4
9
+ assert main.find( type:'Model', slide:0 ).length==3
10
+ assert main.find( type:'Model', slide:1 ).length==4
11
+ assert main.find( type:'Model', slide:1, master:false ).length==1
12
+ assert main.find( type:'Model', attributes:{position:[-150,60,0]} ).length==2
13
+ assert main.find( type:'Model', attributes:{position:[-150,60,0]} ).length==2
14
+ assert main.find( type:'Model', attributes:{position:[nil,60,nil]} ).length==4
15
+ assert main.find( type:'Model', attributes:{sourcepath:'#Cube'} ).length==1
16
+ assert main.find( under:main/"Scene.Layer.Sphere1" ).length==1
17
+ assert main.find( attributes:{name:'Material'} ).length==4
18
+ assert main.find( attributes:{name:/^Sphere/} ).length==2
19
+
20
+ # You can use name not as an attribute
21
+ assert main.find( name:'Material' ).length==4
22
+ assert main.find( name:/^Sphere/ ).length==2
23
+
24
+ # Return values are in Scene graph order
25
+ assert main.find.first == main/"Scene"
26
+ assert main.find.last == main/"Scene.Layer.NonMaster.Material"
27
+
28
+ # Any asset can be used as the 'root'
29
+ sphere = main/"Scene.Layer.Sphere1"
30
+ assert sphere.find.length==1
31
+
32
+ # Supplying a block will iterate, including the index
33
+ expected = main.find type:'Model'
34
+ found = 0
35
+ main.find type:'Model' do |mod,i|
36
+ found += 1
37
+ assert mod == expected[i]
38
+ end
39
39
  assert found==4
File without changes
File without changes
@@ -1,53 +1,52 @@
1
- require 'fileutils'
2
- FileUtils.copy_entry('projects/ReferencedMaterials','projects/_RefMat',false,false,true)
3
-
4
- metadata 'MetaData.xml'
5
-
6
- uia 'projects/_RefMat/ReferencedMaterials.uia'
7
- show app.errors if app.errors?
8
-
9
- layer = app/'main:Scene.Layer'
10
- cubemat = layer/"Cube"/"Material"
11
-
12
- # Ensure that the diffuse attribute is linked and present on multiple slides
13
- assert cubemat['diffuse'].linked?
14
- assert cubemat.has_slide?(0)
15
- assert cubemat.has_slide?(1)
16
- assert cubemat.has_slide?(2)
17
- assert cubemat['diffuse',1].r == 0.5
18
- assert cubemat['diffuse',2].r == 0.5
19
-
20
- # When we do not unlink, values remain shared
21
- cubemat['diffuse',1].r = 1
22
- cubemat['diffuse',2].r = 0.2
23
- assert cubemat['diffuse',1].r == cubemat['diffuse',2].r
24
-
25
- # Ensure that we can unlink an attribute and vary the values per slide
26
- cubemat['diffuse'].unlink
27
- assert !cubemat['diffuse'].linked?
28
- cubemat['diffuse',1].r = 1
29
- cubemat['diffuse',2].r = 0.2
30
- assert cubemat['diffuse',1].r == 1
31
- assert cubemat['diffuse',2].r == 0.2
32
-
33
- # We can swap a material with a referenced material
34
- model = cubemat.parent
35
- assert model
36
- ref = cubemat.replace_with_referenced_material
37
- assert cubemat.parent.nil? # The old material is removed from the graph
38
- assert ref.parent==model # The new material is where the old was
39
- assert ref['id'] == cubemat['id'] # The new material has the same id and name
40
- assert ref.name == 'Material'
41
- assert ref['referencedmaterial',0].object.nil? # New referenced materials start out with no reference
42
- assert ref['referencedmaterial',0].type == :absolute # New references default to absolute
43
-
44
- ref['referencedmaterial'].unlink
45
- %w[Sphere Sphere2].each.with_index do |name,s|
46
- # You can set a reference directly to an object, or alternatively
47
- # ref['referencedmaterial',1].object = layer/name/"Material"
48
- ref['referencedmaterial',s+1] = layer/name/"Material"
49
- ref['referencedmaterial',s+1].type = :path
50
- end
51
-
52
-
53
- app.save_all!
1
+ require 'fileutils'
2
+ FileUtils.copy_entry('projects/ReferencedMaterials','projects/_RefMat',false,false,true)
3
+
4
+ metadata 'MetaData.xml'
5
+
6
+ uia 'projects/_RefMat/ReferencedMaterials.uia'
7
+ show app.errors if app.errors?
8
+
9
+ layer = app/'main:Scene.Layer'
10
+ cubemat = layer/"Cube"/"Material"
11
+
12
+ # Ensure that the diffuse attribute is linked and present on multiple slides
13
+ assert cubemat['diffuse'].linked?
14
+ assert cubemat.has_slide?(0)
15
+ assert cubemat.has_slide?(1)
16
+ assert cubemat.has_slide?(2)
17
+ assert cubemat['diffuse',1].r == 0.5
18
+ assert cubemat['diffuse',2].r == 0.5
19
+
20
+ # When we do not unlink, values remain shared
21
+ cubemat['diffuse',1].r = 1
22
+ cubemat['diffuse',2].r = 0.2
23
+ assert cubemat['diffuse',1].r == cubemat['diffuse',2].r
24
+
25
+ # Ensure that we can unlink an attribute and vary the values per slide
26
+ cubemat['diffuse'].unlink
27
+ assert !cubemat['diffuse'].linked?
28
+ cubemat['diffuse',1].r = 1
29
+ cubemat['diffuse',2].r = 0.2
30
+ assert cubemat['diffuse',1].r == 1
31
+ assert cubemat['diffuse',2].r == 0.2
32
+
33
+ # We can swap a material with a referenced material
34
+ model = cubemat.parent
35
+ assert model
36
+ ref = cubemat.replace_with_referenced_material
37
+ assert cubemat.parent.nil? # The old material is removed from the graph
38
+ assert ref.parent==model # The new material is where the old was
39
+ assert ref['id'] == cubemat['id'] # The new material has the same id and name
40
+ assert ref.name == 'Material'
41
+ assert ref['referencedmaterial',0].object.nil? # New referenced materials start out with no reference
42
+ assert ref['referencedmaterial',0].type == :absolute # New references default to absolute
43
+
44
+ ref['referencedmaterial'].unlink
45
+ %w[Sphere Sphere2].each.with_index do |name,s|
46
+ # You can set a reference directly to an object, or alternatively
47
+ # ref['referencedmaterial',1].object = layer/name/"Material"
48
+ ref['referencedmaterial',s+1] = layer/name/"Material"
49
+ ref['referencedmaterial',s+1].type = :path
50
+ end
51
+
52
+ app.save_all!