here is what i have… there are many problems and probably bugs there but the idea works. check this out:
plugin simpleManipulator GroupControl
name:"GroupControl"
classID:#(0x2feb1967, 0x111c058a)
--invisible:on
category:"Manipulators"
(
local updated = off
local rd = colorMan.getColor #manipulatorsSelected
local ye = colorMan.getColor #manipulatorsInactive
local node
fn getNode = (refs.dependentnodes this)[1]
local size = [1,1,1], offset = [0,0,0]
fn hierarchyBBox =
(
local bmin = [1e9, 1e9, 1e9]
local bmax = [-1e9, -1e9, -1e9]
children = deleteitem (join #() node) 1
for c in children do
(
cmin = c.min
cmax = c.max
bmin.x = amin bmin.x cmin.x
bmin.y = amin bmin.y cmin.y
bmin.z = amin bmin.z cmin.z
bmax.x = amax bmax.x cmax.x
bmax.y = amax bmax.y cmax.y
bmax.z = amax bmax.z cmax.z
)
size = bmax - bmin
offset = bmin
)
parameters mainParams
(
update type:#boolean animatable:on
)
on canManipulate target return off
tool create
(
on mousePoint click do case click of
(
1:
(
nodeTM.translation = gridPoint
#stop
)
)
)
mapped fn addPoint p giz =
(
if p == #new then giz.startNewLine() else giz.addPoint p
)
local giz
fn makeBoxGizmo =
(
giz = manip.makeGizmoShape()
addPoint #(#new, [0,0,0],[0,1,0],[1,1,0],[1,0,0],[0,0,0],[0,0,1],[0,1,1],[1,1,1],[1,0,1],[0,0,1]) giz
addPoint #(#new, [0,1,0],[0,1,1]) giz
addPoint #(#new, [1,1,0],[1,1,1]) giz
addPoint #(#new, [1,0,0],[1,0,1]) giz
giz
)
fn makeGizmos light:off = if isvalidnode node and not isAnimPlaying() do animate off undo off
(
this.clearGizmos()
if update then
(
hierarchyBBox()
)
else
(
size = [1,1,1]
offset = [0,0,0]
)
giz = makeBoxGizmo()
giz.transform (translate (scalematrix size) offset)
giz.transform (inverse node.transform)
this.addGizmoShape giz 0 ye rd
)
on updateGizmos do
(
if isvalidnode (node = getNode()) do
(
if not (c = update.controller).VariableExists "node" do
(
c.addnode "node" node
source = "dependson node
"
source += "node.children.count
"
c.setexpression source
)
--format "make: %
" (join #() node)
)
makeGizmos()
)
on create do
(
this.update.controller = createinstance float_script
)
on clone target do
(
this.update.controller = createinstance float_script
)
)
fn updateGroupControls event: =
(
node = callbacks.notificationParam()
-- format "% %
" event node
for group in (getclassinstances GroupControl) do group.makeGizmos()
)
callbacks.removescripts id:#progroupcontrol
callbacks.addscript #nodeLinked "updateGroupControls event:#link" id:#progroupcontrol
callbacks.addscript #nodeUnlinked "updateGroupControls event:#unlink" id:#progroupcontrol
i’m using LO’s function to get children BBox
Can’t figure out how to get your code working Denis, where’s the instruction manual
run the code (or place the script to stdplugs\stdscripts and reload max), after that you will see in create panel -> helpers -> manipulators the object GroupControl. create it. link anything to the control and check. you can also animate the control and its children… the bounding box has to automatically adjust.
Nice!
Put this code on the end of Denis’s if you want the groupbox to be automatically created.
thegroup = GroupControl pos:selection.center
for o in selection do o.parent = thegroup
So just to confirm, at the moment moving the members of the group doesn’t change the size of the GroupBox?
Bugs: You can’t move the pivot only, it breaks the box’s transform.
i know about it. i just don’t have time now to continue the project. to fix it we need to find a way how to send children transform change message to the control.
Well if you change the timeslider it’ll update the bounding box, but not interactively when you move objects.
Bug: Selecting a GroupBox and pressing Z centers on world 0,0,0 not the box.
the project updates:
plugin simpleManipulator GroupControl
name:"GroupControl"
classID:#(0x2feb1967, 0x111c058a)
--invisible:on
category:"Manipulators"
(
local updated = off
local rd = colorMan.getColor #manipulatorsSelected
local ye = colorMan.getColor #manipulatorsInactive
local node
fn getNode = (refs.dependentnodes this)[1]
local size = [1,1,1], offset = [0,0,0]
fn hierarchyBBox =
(
local bmin = [1e9, 1e9, 1e9]
local bmax = [-1e9, -1e9, -1e9]
children = deleteitem (join #() node) 1
for c in children do
(
cmin = c.min
cmax = c.max
bmin.x = amin bmin.x cmin.x
bmin.y = amin bmin.y cmin.y
bmin.z = amin bmin.z cmin.z
bmax.x = amax bmax.x cmax.x
bmax.y = amax bmax.y cmax.y
bmax.z = amax bmax.z cmax.z
)
size = bmax - bmin
offset = bmin
)
parameters mainParams rollout:mainParams
(
update type:#boolean animatable:on
links type:#maxobjectTab tabSizeVariable:on
gizmocolor type:#rgb animatable:off default:yellow ui:ui_gizmocolor
)
rollout mainParams "Parameters"
(
colorpicker ui_gizmocolor "Gizmo Color:" fieldwidth:32 height:16 align:#right offset:[0,0] modal:off
)
on canManipulate target return off
tool create
(
on mousePoint click do case click of
(
1:
(
nodeTM.translation = gridPoint
#stop
)
)
)
mapped fn addPoint p giz =
(
if p == #new then giz.startNewLine() else giz.addPoint p
)
local giz
fn makeBoxGizmo =
(
giz = manip.makeGizmoShape()
addPoint #(#new, [0,0,0],[0,1,0],[1,1,0],[1,0,0],[0,0,0],[0,0,1],[0,1,1],[1,1,1],[1,0,1],[0,0,1]) giz
addPoint #(#new, [0,1,0],[0,1,1]) giz
addPoint #(#new, [1,1,0],[1,1,1]) giz
addPoint #(#new, [1,0,0],[1,0,1]) giz
giz
)
fn makeGizmos light:off = if isvalidnode node and not isAnimPlaying() do animate off undo off
(
this.clearGizmos()
giz = makeBoxGizmo()
if update then
(
hierarchyBBox()
)
else
(
size = [1,1,1]
offset = [0,0,0]
)
giz.transform (translate (scalematrix size) offset)
giz.transform (inverse node.objecttransform)
this.addGizmoShape giz 0 (this.gizmocolor as point4) rd
)
on updateGizmos do
(
if isvalidnode (node = getNode()) do
(
if not (c = update.controller).VariableExists "node" do
(
c.addnode "node" node
source = "dependson node
"
source += "node.children.count
"
c.setexpression source
)
--format "make: %
" (join #() node)
)
makeGizmos()
)
on create do
(
this.update.controller = createinstance float_script
)
on clone target do
(
this.update.controller = createinstance float_script
)
)
fn updateGroupControls event: =
(
node = callbacks.notificationParam()
-- format "% >> % %
" event node node.parent
case event of
(
#link: if node.parent != undefined do
(
for group in (getclassinstances GroupControl) where isvalidnode group.node do
(
if (finditem (join #() group.node) node) != 0 do
(
for n in (join #() node) do append group.links (NodeTransformMonitor node:n)
group.makeGizmos()
exit
)
)
)
#unlink: if node.parent != undefined do
(
for group in (getclassinstances GroupControl) where isvalidnode group.node do
(
if (finditem (join #() group.node) node) != 0 do
(
children = join #() node
for k = group.links.count to 1 by -1 where iskindof group.links[k] NodeTransformMonitor do
if (finditem children group.links[k].node) != 0 do deleteitem group.links k
group.makeGizmos()
exit
)
)
)
)
)
callbacks.removescripts id:#progroupcontrol
callbacks.addscript #nodeLinked "updateGroupControls event:#link" id:#progroupcontrol
callbacks.addscript #nodeUnlinked "updateGroupControls event:#unlink" id:#progroupcontrol
check how i solved the problem of gizmo updating when any group’s child changes it transform.
cool, isn’t it? (thanks LO for the join node trick)
also i fixed the “only pivot changes” bug.
Epic maxscript skills, some really interesting tips there.
The pivot fix appears to have half sorted the Z zooming issue… it at least orbits around the groupBox but it doesn’t have the correct zoom and the it’s a weird offsetted orbit.
that’s because the manipulator is a specific class. it is always in mode of ignoring zoom extends. there is another trick to solve the issue. i show it when i would have a time.
Some form of callback to catch the Z being pressed or button being pressed, establish the bounding box of the selected group(s), and pass back the transform to the viewport camera?
no! much more elegant. (sorry)
i can give a clue. can the scripted helper delegate a manipulator?