-- Trooper Group Manager -- V 0.1 Release -- V 0.2 Groups are only listed if the list button is pressed to avoid long processing time in heavy scenes with more than a thousand groups. -- V 0.3 Objects can be grouped even if they are in different groups. Objects can be attached to groups: select objects and then the target group. -- V 0.4 Changes to the attach function, with a lot of feedback and help from Simon Bourgeois. ( local groupObjectsArray = #() local phPosition = [0,0,0] local phSize = 10 local groupTag = "_G" local groupTagHelper = "_Group" local groupTagHelperPattern = "*_Group*" local listGroups = false local selectedObjs try(cui.UnRegisterDialogBar ::groupManagerRollout)catch() if groupManagerRollout != undefined then (destroyDialog ::groupManagerRollout) fn updateGroupObjectsArray = ( if listGroups == true then ( groupObjectsArray = for obj in objects where isGroupHead obj collect obj ) else ( free groupObjectsArray ) ) fn updateCustomGroupObjectsArray = ( groupObjectsArray = for obj in objects where matchPattern obj.name pattern:groupTagHelperPattern collect obj ) fn refreshListBox = ( if listGroups == true then ( groupManagerRollout.lb.items = for obj in groupObjectsArray collect obj.name ) else ( free groupManagerRollout.lb.items groupManagerRollout.lb.items = groupObjectsArray ) ) fn selectGroupObject index = ( if index > 0 do ( select groupObjectsArray[index] groupS = groupObjectsArray[index] -- select groupS.children -- selectmore groupS.children ) ) fn focusGroupObject index = ( if index > 0 do ( max zoomext sel ) ) fn toggleGroup index = ( if index > 0 do ( if isGroupMember groupObjectsArray[index] then groupOpen groupObjectsArray[index] else groupClose groupObjectsArray[index] ) ) fn refreshGroupListBasedOnToggle = ( if groupManagerRollout.chk_toggle_group_type.checked then ( updateCustomGroupObjectsArray() ) else ( updateGroupObjectsArray() ) refreshListBox() ) fn onGroupCreated = ( if listGroups == true do ( updateGroupObjectsArray() refreshListBox() ) ) fn checkIfGrouped = ( selectedObjs = selection as array for obj in selectedObjs do ( if obj.parent != undefined do ( if (isGroupHead obj.parent) and (classOf obj != ObjectSet) do ( detachNodesFromGroup obj ) ) ) select selectedObjs ) fn createGroupLocal = ( undo on( checkIfGrouped() if selectedObjs.count > 0 then ( firstObj = selectedObjs[1] firstObjMatrix = firstObj.transform tempDummy = Dummy name:(firstObj.name + "_group_dummy") dummyGroup = group tempDummy name:(firstObj.name + groupTag) dummyGroup.transform = firstObjMatrix attachNodesToGroup selectedObjs dummyGroup delete tempDummy select dummyGroup ) else ( print "select at least one object" ) ) ) fn createPointHelperAtFirstObject = ( undo on( selectedObjs = selection as array if selectedObjs.count > 0 then ( firstObj = selectedObjs[1] firstObjMatrix = firstObj.transform pointHelper = Point name:(firstObj.name + groupTagHelper) pointHelper.transform = firstObjMatrix select pointHelper selectedObjs.parent = pointHelper ) else ( print "select at least one object" ) ) ) fn createPointHelperAtPosition position size = ( ph = Point() ph.position = position ph.size = size ph.name = (selection[1].name + groupTagHelper) return ph ) fn attachObjectsToGroup selectedObjs = ( local destinationGroup local sourceGroup if selectedObjs.count > 1 then ( destinationGroup = for o in selectedObjs where isGroupHead o collect o --collect only the groupheads avoiding try to attachtogroup on a non grouphead object clearselection() setGroupOpen destinationGroup[destinationGroup.count] false --close the lastgrouphead in the array to select all child from this group. select destinationGroup[destinationGroup.count] -- not a very clean way of getting the children of the targeted group, a better approach would be to use destinationGroup[destinationGroup.count].children and create an array that contain destinationGroup[destinationGroup.count] + destinationGroup[destinationGroup.count].children objectAlreadyinDestGroup = selection as array --creates an array of objects that are already in the targeted group clearselection() --not really necessary i think it would work without it objToAttach = for o in selectedObjs where finditem objectAlreadyinDestGroup o == 0 collect o ---create an array of the objects that are in selectedobjs but are also in objectAlreadyinDestGroup to get an array the nodes that needs to be attached to the group if isGroupHead destinationGroup[destinationGroup.count] do ( setGroupOpen destinationGroup[destinationGroup.count] true ) --deleteItem selectedObjs selectedObjs.count--not needed anymore--it was removing last obj in selection but without being sure that it was the grouphead, you need to remove the right grouphead to avoid dependency crash and also you needed to remove nodes that were already in the targeted group for obj in objToAttach do ( obj.parent = undefined obj.parent = destinationGroup[destinationGroup.count] ) attachNodesToGroup objToAttach destinationGroup[destinationGroup.count] ---actually attaching the filtered nodes setGroupOpen destinationGroup[destinationGroup.count] false ---close the group select destinationGroup[destinationGroup.count] ---select it centerpivot destinationGroup[destinationGroup.count] --and centerpivot )-- the correction makes it work but it should be a little tweaked to be sure to get the right group head, i tried on nested groups and it attached the selected objects to a group within the group but not to the "master" grouphead you would need to do a qsort function by parent order to be sure to target the right grouphead ) callbacks.addScript #sceneNodeAdded onGroupCreated id:#groupCreationCallback callbacks.addScript #nodePostDelete onGroupCreated id:#groupCreationCallback -- callbacks.addScript #groupChanged onGroupCreated id:#groupCreationCallback rollout groupManagerRollout "Group Manager" width:144 height:600 ( button 'btnFloat' "F" pos:[104,8] width:16 height:14 toolTip:"Float Dialog" align:#left button 'btnDockLeft' "<" pos:[86,8] width:16 height:14 toolTip:"Dock Left" align:#left button 'btnDockRight' ">" pos:[121,8] width:16 height:14 toolTip:"Dock Right" align:#left checkbutton 'btnUpdateToggle' "List" pos:[50,8]width:32 height:14 align:#left toolTip:"List" listbox 'lb' "Groups" pos:[10,10] width:124 height:25 align:#left checkbutton 'chk_toggle_group_type' "Show '_Group' Objects" pos:[8,368] width:128 height:21 align:#left toolTip:"Toggle between showing groups and helper groups" button 'btnGroupLoc' "Group (Loc)" pos:[8,400] width:82 height:24 align:#left toolTip:"Create a group based on the selection,with first selected object's local transformation" button 'btnGroup' "Group (World)" pos:[8,424] width:82 height:24 align:#left toolTip:"Create a group from selection" button 'btnUngroup' "Ungroup" pos:[92,400] width:44 height:48 align:#left toolTip:"Ungroup selected group" button 'btnPointHelperLoc' "Helper Group (Loc)" pos:[8,456] width:128 height:24 align:#left toolTip:"Create a parent helper based on the first selected object's local transformation, tagged _group" button 'btnPointHelperWorld' "Helper Group (World)" pos:[8,480] width:128 height:24 align:#left toolTip:"Create a parent helper, tagged _group" button 'chkToggleGroup' "Toggle Group Open/Close" pos:[8,520] width:128 height:24 align:#left toolTip:"Toggle group open/closed" button 'btnAttach' "Attach" pos:[8,546] width:63 height:24 align:#left toolTip:"Object selection is attached to the last selected Group" button 'btnDetach' "Detach" pos:[73,546] width:63 height:24 align:#left toolTip:"Detach selection from Group" on btnFloat pressed do ( try(cui.UnRegisterDialogBar groupManagerRollout) catch() createDialog groupManagerRollout SetDialogSize groupManagerRollout [144,600] ) on btnDockLeft pressed do ( try(cui.UnRegisterDialogBar groupManagerRollout) catch() createDialog groupManagerRollout cui.RegisterDialogBar groupManagerRollout cui.DockDialogBar groupManagerRollout #cui_dock_left ) on btnDockRight pressed do ( try(cui.UnRegisterDialogBar groupManagerRollout) catch() createDialog groupManagerRollout cui.RegisterDialogBar groupManagerRollout cui.DockDialogBar groupManagerRollout #cui_dock_right ) on groupManagerRollout open do ( free groupObjectsArray ) on groupManagerRollout close do ( callbacks.removeScripts id:#groupCreationCallback ) on groupManagerRollout resized val do ( lb.height = val.y-266 chk_toggle_group_type.pos.y = val.y-232 btnGroupLoc.pos.y = val.y-200 btnGroup.pos.y = val.y-176 btnUngroup.pos.y = val.y-200 btnPointHelperLoc.pos.y = val.y-144 btnPointHelperWorld.pos.y = val.y-120 chkToggleGroup.pos.y = val.y-80 btnAttach.pos.y = val.y-50 btnDetach.pos.y = val.y-50 ) on lb selected item do ( selectGroupObject item ) on lb doubleClicked item do ( focusGroupObject item ) on lb rightClicked item do ( toggleGroup item ) on chk_toggle_group_type changed state do ( if listGroups == true do ( refreshGroupListBasedOnToggle() ) ) on btnGroupLoc pressed do ( createGroupLocal() ) on btnPointHelperWorld pressed do ( selectionArray = selection as array if selectionArray.count > 0 then ( undo on( phPosition = selectionArray[1].position newPointHelper = createPointHelperAtPosition phPosition phSize for obj in selectionArray do ( obj.parent = newPointHelper ) select newPointHelper ) ) else ( print "No objects selected" ) ) on btnPointHelperLoc pressed do ( createPointHelperAtFirstObject() ) on btnUpdateToggle changed stateA do ( if stateA == true do listGroups = true if stateA == false do listGroups = false updateGroupObjectsArray() refreshListBox() ) on chkToggleGroup pressed do ( if selection.count > 0 and (classOf selection[1].parent == Dummy) then ( if isOpenGroupHead selection[1].parent then ( setGroupOpen selection[1].parent false select selection[1] ) else if isGroupHead selection[1].parent then ( setGroupOpen selection[1].parent true select selection[1] ) ) else ( print "No group selected" ) if selection.count > 0 and (classOf selection[1] == Dummy) do ( if isGroupHead selection[1] do ( setGroupOpen selection[1] false select selection[1] ) ) ) on btnGroup pressed do ( undo on( if selection.count > 0 then ( checkIfGrouped() group selection name:(selection[1].name + groupTag) select selection[1].parent ) else ( print "No objects selected" ) ) ) on btnUngroup pressed do ( max group ungroup ) on btnAttach pressed do ( selectedObjs = selection as array if selectedObjs.count > 0 do ( attachObjectsToGroup selectedObjs ) ) on btnDetach pressed do ( selectedObjs = selection as array if selectedObjs.count > 0 do ( detachNodesFromGroup selectedObjs ) ) ) createDialog groupManagerRollout style:#(#style_resizing,#style_titleba,#style_toolwindow,#style_sysmenu)lockHeight:false lockWidth:true SetDialogPos groupManagerRollout [1740,190] )