.hidden property and groups (scripting)

Next
 From:  pressure (PEER)
11120.1 
Hi Michael,

I'm having some problems with changing the .hidden property when groups are involved. For example, setting hidden = false on a sub-object isn't enough to make that sub-object visible: all of its parent objects must also have hidden = false set. It seems like setting hidden on a parent object recursively sets hidden to the same value on all of that parent's children, but that the same sort of thing doesn't happen when setting a child.

What's a nice way to show a child object when some of its parents are hidden? In particular, if I'm hiding some objects and also showing others, how do I make sure that what I want to show stays non-hidden that that what I want to hide stays hidden without any interaction between these operations?

- Peer
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
11120.2 In reply to 11120.1 
Hi Peer, just to make sure I understand, you're talking about setting the .hidden property from inside some of your own script code, not about setting it using the regular MoI UI, right?


> It seems like setting hidden on a parent object recursively sets hidden to the same value on all of
> that parent's children,

Yes.


> but that the same sort of thing doesn't happen when setting a child.

Yes, that's correct, if it did try to do the same thing it could have some potentially strange effects. Like if you set .hidden = false on a child object, it would probably be weird for hidden = false to be set on parent groups which would cause objects in other sibling sub trees of the group to get hidden.


> What's a nice way to show a child object when some of its parents are hidden? In
> particular, if I'm hiding some objects and also showing others, how do I make sure
> that what I want to show stays non-hidden that that what I want to hide stays
> hidden without any interaction between these operations?

You'll probably need to do the showing first. If the object you want to have shown is inside of a group then set hidden = false on the top level group:

obj.hidden = false;
var toplevel = obj.getTopLevelParent();
if ( toplevel.isGroup )
   toplevel.hidden = false;

Do that on all objects you want shown.

Then set .hidden = true on stuff that you want hidden.

- Michael

EDIT: Fixed typo - set .hidden = true on stuff you want hidden.

EDITED: 7 Jun 2023 by MICHAEL GIBSON

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  pressure (PEER)
11120.3 In reply to 11120.2 
Thanks Michael for your lightning-fast reply!

Yes I'm talking about setting .hidden in my own script code. Setting it in the regular UI is working well.

I didn't think of just setting the top-level parent group. I'll give that a try.

- Peer
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  pressure (PEER)
11120.4 In reply to 11120.2 
Hi Michael,


Re:
> if it did try to do the same thing it could have some potentially
> strange effects. Like if you set .hidden = false on a child object, it
> would probably be weird for hidden = false to be set on parent groups
> which would cause objects in other sibling sub trees of the group to get
> hidden.

At the end you mean "shown", like hidden = false, right?

That basically describes the problem I was having: I wanted to do something like in a scene where everything is hidden just show one face of a solid that's in a group with some other solids without showing any of the other faces of that solid or any of the other solids. Like how if I name a face then I can click in the eye column of the browser next to that name and show just that face.

Re:
> obj.hidden = false;
> var toplevel = obj.getTopLevelParent();
> if ( toplevel.isGroup )
> toplevel.hidden = false;

Showing the top-level parent group causes everything in that group to get shown, which is not what I want.

Here's what I ended up doing, but it seems like I'm maybe not understanding something and am also reinventing the wheel since I'm basically trying to get the same behavior as when setting object visibility with the browser.

Two things that caused some trouble are:
  1. Setting hidden = true on a non-group object fails to set hidden = true on sub-objects
  2. .getSubObjects() operates recursively rather than just giving immediate children

I also tried using .getNextNode(), but since it enters a group rather than returning it, it causes the same trouble as .getSubObjects().

code:
var obj = moi.geometryDatabase.findObject('{874ac4db-5919-4fbd-9bbc-2c9604332b65}'); // face
// var obj = moi.geometryDatabase.findObject('{4e824df8-dbb6-4c4a-a9b7-40c52acaab6e}'); // box
// var obj = moi.geometryDatabase.findObject('{7ff98c04-d959-4567-ada2-93a8ecbf8128}'); // Group05

showObj(obj);

// sets hidden = false on obj and its parents recursively, but avoids changing .hidden on siblings
function showObj(obj) {

    var parentObj = obj.getParentObject();

    /*
    if obj is a child of hidden non-Group object
    need to set hidden = true on all sub-objects of that hidden parent
    */
    var firstHiddenParentInArray = getHiddenParent(obj);
    if (firstHiddenParentInArray.length === 1) {
        var firstHiddenParent = firstHiddenParentInArray[0];
        var subObjList = firstHiddenParent.getSubObjects();
        subObjList.setProperty('hidden', true);
    }

    // record state of siblings
    var siblingList = getSiblings(obj);
    var siblingStateDict = {};
    for (var i = 0; i < siblingList.length; ++i) {
        var sibling = siblingList.item(i);
        siblingStateDict[sibling.id] = sibling.hidden;
    }

    obj.hidden = false;

    if (parentObj != null) {
        showObj(parentObj);
        for (var i = 0; i < siblingList.length; ++i) {
            var sibling = siblingList.item(i);
            sibling.hidden = siblingStateDict[sibling.id];
        }
    }
}

// returns array containing the top-most *non-Group* parent of obj that is hidden
// if hidden = false on all non-Group parents then returns empty array
function getHiddenParent(obj) {

    var hiddenParentInArray = [];

    doGetIsInHiddenObject(obj, hiddenParentInArray);

    return hiddenParentInArray;

    function doGetIsInHiddenObject(obj, hiddenParentInArray) {

        var parent;
        if (obj != null) {
            parent = obj.getParentObject();
        } else {
            parent = null;
        }

        if (
            parent != null &&
            parent.hidden === true &&
            parent.isGroup === false
        ) {
            hiddenParentInArray[0] = parent;
        }

        if (parent != null) {
            doGetIsInHiddenObject(parent, hiddenParentInArray);
        }
    }
}

// returns an objectList of the immediate siblings of obj
// in other words, all objects that have the same immediate parent as obj
// excludes obj itself
// excludes curveSegments since they aren't targetable in the viewports
function getSiblings(obj) {

    if (obj.isCurveSegment) {
        moi.ui.alert('attempted to get sibling of a curve segment in getSiblings()');
    }

    var immediateSiblingsList = moi.geometryDatabase.createObjectList();

    var parentObj = obj.getParentObject();
    if (parentObj != null) {
        var siblingsList = parentObj.getSubObjects();
        for (var i = 0; i < siblingsList.length; ++i) {
            var sibling = siblingsList.item(i);
            var siblingParent = sibling.getParentObject();
            if (
                sibling.isCurveSegment === false &&
                sibling.id != obj.id &&
                siblingParent != null &&
                // getSubobjects() is recursive so need to verify that it's the same parent and not a parent
                // somewhere else in the heirarchy
                siblingParent.id === parentObj.id 
            ) {
                immediateSiblingsList.addObject(sibling);
            }
        }
    }
    return immediateSiblingsList;
}


- Peer
Attachments:

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
11120.5 In reply to 11120.4 
Hi Peer,

re:
> Showing the top-level parent group causes everything in that group to get shown, which is not what I want.

Right, but that's not the complete operation, after everything is shown you can then set what you want hidden to obj.hidden = true; without needing to do any climbing up group parent trees.


> Two things that caused some trouble are:
>
> Setting hidden = true on a non-group object fails to set hidden = true on sub-objects
> .getSubObjects() operates recursively rather than just giving immediate children

There isn't really any way to change this behavior without potentially breaking already existing scripts.

But if you want to get only the immediate children of a group, there is an .objects property on a group that will give that.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
 From:  pressure (PEER)
11120.6 In reply to 11120.5 
Hi Michael,

Thanks for reiterating that the way to do this is by showing everything and then hiding the stuff I want hidden. It took me a little while, but now I think I see what you meant and why this isn't built into setting hidden = false.

Good to know about the .objects property, though like you were hinting, I didn't end up needing it.

- Peer
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged
 

Reply to All Reply to All