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.
- checksums.yaml +4 -4
- data/README.md +207 -201
- data/bin/ruic +22 -14
- data/gui/TODO +2 -2
- data/gui/appattributesmodel.rb +51 -51
- data/gui/appelementsmodel.rb +126 -126
- data/gui/launch.rb +19 -19
- data/gui/makefile +14 -14
- data/gui/resources/style/dark.qss +459 -459
- data/gui/window.rb +90 -90
- data/gui/window.ui +753 -753
- data/lib/ruic.rb +45 -9
- data/lib/ruic/application.rb +4 -0
- data/lib/ruic/{asset_classes.rb → assets.rb} +281 -447
- data/lib/ruic/attributes.rb +164 -0
- data/lib/ruic/behaviors.rb +0 -0
- data/lib/ruic/interfaces.rb +5 -5
- data/lib/ruic/presentation.rb +13 -11
- data/lib/ruic/statemachine.rb +0 -0
- data/lib/ruic/version.rb +2 -2
- data/ruic.gemspec +24 -22
- data/test/customclasses.ruic +0 -0
- data/test/filtering.ruic +38 -38
- data/test/nonmaster.ruic +0 -0
- data/test/properties.ruic +0 -0
- data/test/referencematerials.ruic +52 -53
- data/test/usage.ruic +20 -20
- metadata +33 -20
@@ -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
|
data/lib/ruic/behaviors.rb
CHANGED
File without changes
|
data/lib/ruic/interfaces.rb
CHANGED
@@ -18,15 +18,15 @@ end
|
|
18
18
|
|
19
19
|
module UIC::ElementBacked
|
20
20
|
attr_accessor :owner, :el
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
29
|
+
end
|
30
30
|
end
|
31
31
|
|
32
32
|
module UIC::PresentableHash
|
data/lib/ruic/presentation.rb
CHANGED
@@ -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
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
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
|
data/lib/ruic/statemachine.rb
CHANGED
File without changes
|
data/lib/ruic/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
class RUIC
|
2
|
-
VERSION = '0.0
|
1
|
+
class RUIC
|
2
|
+
VERSION = '0.1.0'
|
3
3
|
end
|
data/ruic.gemspec
CHANGED
@@ -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.
|
19
|
-
|
20
|
-
s.
|
21
|
-
s.
|
22
|
-
s.
|
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
|
data/test/customclasses.ruic
CHANGED
File without changes
|
data/test/filtering.ruic
CHANGED
@@ -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
|
data/test/nonmaster.ruic
CHANGED
File without changes
|
data/test/properties.ruic
CHANGED
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!
|