@tntdavid said:
@tig said:
What made you think you need to diverge from my guidance ?
I used a array to "match" because there will be several different definitions to delete.
TIG is showing you how to purge ONEdefinition and it's materials.
@tntdavid said:
Your code works perfectly for a single definition, ...
No it does not. because you made 3 edits that make it NOT work properly.
CORRECTION: Actually I found 4 errors that made it not delete all the components or materials.
The second use of the Regexp was ! d.name =~ /#{name}/ (the regexp var is match.)
matsNOTtogo=[] was defined as matsNOYtogo=[], resulting in NameError
The comparison of back_material was conditional upon inclusion of front material in two statements.
@tntdavid said:
... what if we have "CUBE", "TOTO" and "LOLA" to delete?
First, learn how and why TIG's code works for ONE definition, then learn how to modify it for multiple definitions.
Then either you wrap what TIG showed you into a method, and call it 3 times from a loop:
for cname in ['CUBE','TOTO','LOLA'] # WHOOPS this not needed --> do |cname|
purge_comp(cname)
end
... or you build a multi-match regular expression ( Regexp
cnames = ['CUBE','TOTO','LOLA'] match = /#{cnames.join('|')}/
Test file (SU2016):
CubeLolaToto.skp
"Color B04" and "Color J08" are unused.
"Color K03", "Color M06" are used by primitive faces.
"Material 2" is the leader color.
So here is a method with extra quirks:
- Returns false if array of cnames is empty.
- Short circuits and returns 0 if no definitions are found to delete.
- Reports both to console and message box number of definitions and materials purged.
- Returns number of definitions deleted.
# To test;
# purge_comps('CUBE','TOTO','LOLA')
# ... or;
# del = ['CUBE','TOTO','LOLA']
# purge_comps(del)
def purge_comps(*cnames)
#
return false if cnames.empty?
cnames.flatten!
#
match = /#{cnames.join('|')}/
#
model=Sketchup.active_model
# collect matching definitions
defstogo=model.definitions.find_all{|d| d.name =~ match }
return 0 if defstogo.empty?
# collect materials.
matstogo=[]
defstogo.each{|d|
# first used by instances
d.instances.each{|i|
matstogo << i.material unless matstogo.include?(i.material)
}
# now used by its entities
d.entities.each{|e|
matstogo << e.material unless matstogo.include?(e.material)
( matstogo << e.back_material unless matstogo.include?(e.back_material) ) if e.is_a?(Sketchup;;Face)
}
}
matstogo.compact!
matstogo.uniq!
# now check if materials used elsewhere
defsNOTtogo=model.definitions.find_all{|d| ! d.name =~ match }
# collect materials.
matsNOTtogo=[]
defsNOTtogo.each{|d|
# first used by instances
d.instances.each{|i|
matsNOTtogo << i.material unless matsNOTtogo.include?(i.material)
}
# now used by its entities
d.entities.each{|e|
matsNOTtogo << e.material unless matsNOTtogo.include?(e.material)
( matsNOTtogo << e.back_material unless matsNOTtogo.include?(e.back_material) ) if e.is_a?(Sketchup;;Face)
}
}
matsNOTtogo.compact!
matsNOTtogo.uniq!
# now reduce matstogo as necessary...
matstogo.clone.each{|e|
matstogo.delete(e) if matsNOTtogo.include?(e)
}
#
defsgone = defstogo.size
matsgone = matstogo.size
# start and operation to ensure Garbage Collection works...
model.start_operation('Purger', true)
# now delete the selected entities
defstogo.each{|d| d.entities.clear! }
# now delete the unneeded materials
matstogo.each{|m| model.materials.remove(m) }
# clear the arrays of references to deleted objects;
matstogo.clear
defstogo.clear
# commit
model.commit_operation
msg = "#{defsgone} definitions purged\n#{matsgone} materials purged"
puts msg
UI.messagebox(msg,MB_OK)
return defsgone
end
If you absolutely must, you can call GC.start to ensure Ruby garbage collection runs.