instances to separate layers

Guys here's the script idea:
I need a script that would move all the instances (of multiple definitions) from the current selection to the separate layers
For example in the current selection I have 10 instances called AAA_ , 10 instances called BBB_ , 10 instances called CCC_ etc..
The script would create the separate layers in accordance to instances names, but starting with prefix z_ :
z_AAA
z_BBB
z_CCC
and move the instances to related layers (all AAA_ instances will be moved to layer z_AAA, BBBs to layer z_BBB etc)
P.S. Instances have numbers in its names, typically AAA_001, AAA_002 etc - the script should ignore them
P.P.S. Ideally I'd like the this script to continue and create dedicated Forest Sets based on those new layers, but maybe I'm asking too much :)
The script is needed for creating reference forests based CAD blocks coming from Sketchup, Autocad, etc..
Thank you

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
1rv's picture

This will launch this script

This will launch this script to stratosphere:
Is it possible to add an optional button "add FP geo"?
(I'd create FP in the rRef mode with selected entities) :)
P.S. I PMed you (@free.fr)

SimonBourgeois's picture

updated script

https://www.mediafire.com/file/y9izl2rf83sgzqb/Instances_to_layers_For_F...
Previous version has a bug when forest pro version was used.
there is still a limitation to this script, every sets of instances need to have a different base name or the script crashes because layers are created based on those instances names stripped of the "_00x"part.
for example: Object_001,Object_002,Object_003,etc... and Other-Object_001,Other-Object_002,Other-Object_003,etc...

miauu's picture

...

(
	local strZ_ = "Z_"
	local str0123456789_ = "0123456789_"
	local imGetInstances = InstanceMgr.GetInstances
 
	function UniqueNodes nodes: = 
	(
		local handles = #{}
		for o in nodes where not handles[GetHandleByAnim o] collect
		(
			imGetInstances o &inst
			for i in inst do handles[GetHandleByAnim i] = true
			o
		)
	)	
	UniqueObjsArr = UniqueNodes nodes:(selection as array)
 
	for o in UniqueObjsArr do
	(	
		objsArr = #()
		if (imGetInstances o &inst) > 1 do (if findItem objsArr o == 0 do join objsArr inst)		
		layerName = (strZ_ + (trimRight o.name str0123456789_))
		if (objLayer = layerManager.newLayerFromName layerName) != undefined then
			objLayer.addNodes objsArr
		else
			(layerManager.getLayerFromName layerName).addNodes objsArr
	)
)
SimonBourgeois's picture

Hi miauu,Good idea for the

Hi miauu,

Good idea for the (trimRight o.name str0123456789_), its better then my (substring obj.name 1 (obj.name.count - 4), also your function for collecting unique nodes looks better,and the check for already existing layer with the same name is also a good idea.;)
But there is something that doesn't work well in your script, if you have objects in selection that are referenced copys it will create a layer for them aswell, that is why i added this line: trueInstances = for n in instances where (areNodesInstances obj n) collect n
also i noticed that your script was creating a layer for objects that aren't instanced if selection contain non instanced object.
i've updated my earlier post to add the forestset creation, now that i see your post, maybe we should merge the two versions...:)
By the way thanks for all your post, you have been really helpfull, i am new to scripting and i've been learning a lot from you.
Also, i was wondering how to post code in a "window" like you, mine has been all messed up when i posted it (every line start at the begining of a line).
edit:
Here is a merged version of both script:
(
local imGetInstances = InstanceMgr.GetInstances

fn collectUniqueNodes nodes: =
(
local handles = #{}
for o in nodes where not handles[GetHandleByAnim o] collect
(
imGetInstances o &inst
for i in inst do handles[GetHandleByAnim i] = true
o
)
)

local uniquenodes = collectUniqueNodes nodes:selection as array

for obj in uniquenodes do
(
imGetInstances obj &instances
trueInstances = for n in instances where (areNodesInstances obj n) collect n
if trueInstances.count > 1 do
(
local layername = "Z_"+(trimRight obj.name "0123456789_")

if (objLayer = layerManager.newLayerFromName layerName) != undefined then objLayer.addNodes trueInstances
else (layerManager.getLayerFromName layerName).addNodes trueInstances

if isForestPack != undefined do ForestSet pos:obj.pos layerimport:on layernames:layername
)

)
)

miauu's picture

...

Hi, Simon!

I don't know if my code will work properly or not, because I don't have a scene to test with.
If you want you can scalp what you need from my code.

To properly post your code in the forum use this(without the quotes):
["code"]

-- your code here

["/code"]

SimonBourgeois's picture

Hi

thx Miauu,
For some reason i can't edit the earlier message but i can edit this one, so here is the updated code :

(
	local imGetInstances = InstanceMgr.GetInstances
 
	fn collectUniqueNodes nodes: = 
	(
		local handles = #{}
		for o in nodes where not handles[GetHandleByAnim o] collect
		(
			imGetInstances o &inst
			for i in inst do handles[GetHandleByAnim i] = true
			o
		)
	)	
 
	local uniquenodes = collectUniqueNodes nodes:selection as array
 
	for obj in uniquenodes do
	(
		imGetInstances obj &instances
		trueInstances = for n in instances where (areNodesInstances obj n) collect n
		if trueInstances.count > 1 do
		(
			local layername = "Z_"+(trimRight obj.name "0123456789_")
 
			if (objLayer = layerManager.newLayerFromName layerName) != undefined then objLayer.addNodes trueInstances
			else (layerManager.getLayerFromName layerName).addNodes trueInstances
 
			if isForestPack != undefined do ForestSet pos:obj.pos layerimport:on layernames:layername
		)
 
	)
)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.