RUIC 0.0.1 → 0.1.0

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.
@@ -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!