Container layout and sizing decoupled from its node placement

Hello,
please I would like to ask if there is some way to approach following problem. I would like to place my components in node graph based on their functionality. That means sometimes I need a component to be somewhere deep in other components - because it is logical to place it there.

However if these components provide UI (meaning they are containers), I have to place them differently - not where it makes sense, but in topmost container that aligns them properly along with other UI containers. This is causing me some organization problems.

Therefore I am looking for a way to have container layout and sizing information decoupled from its node placement. In a nutshell - I would like to place my container deep down in network (in some Base COMPs), but still have it aligned and sized based on some topmost container.

I have been looking for some operator that could bring them to surface - also overriding their sizing and alignment. I have thought Select COMP might help me with this, but it doesn’t seem to do this sort of trick.

Please is there some recommended approach to achieve this functionality? I am not sure how exactly should Overlay COMP work (once finished), maybe it could solve this organization problem? Thanks.

You are on the right way.
The general consensus is that UI and functionality (and later data) should be completly seperate enteties. You want to create your systems in a way that your functionality of your component can work on its own without relying on the UI at all. In that regard to data, your data should always be seperate enough that you could change, reload etc your component without having to worry about the state of your data being lost.

For that I make heavy use of Custom-Parameters and Extensions. I then create a UI-component as a container, and put it in my component. They key par now is to use a Parameter in your UI that is pointing to your functionality. Inside of your UI you then never ever use an absolute path, but instead use the parameter that is pointing to your component. This is important, because you can now, for example, work on your component without having to worry about the UI. You can also simply move the UI somewhere else (see where I’m getting at?) and adjust the refference in your parameter.

This will feel a little unintuitive at first as this will slow you down a little bit as simply drag and drop for refferences does no longer work, but for larger projects, this helps imensly (esp if you start to work with git and other developers).
An example is my presetSystem. The UI for example is inside, but you can easily move the UI component inside and redo the refference again.
Another + point is that you can have one UI for several targets.

@alphamoonbase thank you very much for detailed explanation.

I would like to ask how do you approach situations where core component needs to influence its UI (lets say you need to change colors based on some CHOP)? If I understood this correctly, only your UI component knows about the core component (not the other way around).

This sounds like a good system, the problem in my opinion is the complexity it can add in certain situations. For example if one has 30 tox components, with this approach doubles them to 60 (which could significantly increase maintenance).

Sometimes I feel like the cleanest approach is to have both UI and core in a single component - having it all under one roof is kinda nice. If you are working on core logic, you still have a good overview of UI as it is sitting right there - giving you ability to use this UI right away when you want to control stuff (without having to go many levels up to place where it is located). Therefore I was thinking about something like Select COMP that could be placed anywhere, pointing to your component and just “displaying” it (overriding its sizing, layout, etc). But I know this doesn’t work this way at the moment. :roll_eyes:

Nevertheless your approach sounds good, thank you very much for writing it down. :slightly_smiling_face:

A lot of UIs I make do not hold the value that they are displaying, but instead are displaying the value. This got easiert with two-way-databinding.

Also, I like to either just use a parameterCOMP for UI-purposes or to create a UI based on custom-parameters or based on a description. So instead of having to build a UI every time you build a component (which starts to get completly of the rails you need to do skinning) you build a UI-Generator once and have it generate the UIs once on initialisation or something like this.

This is correct and a good idea to keep in mind for general system architecture too. Not knowing about other components can be extremly good for larger systems.

I did a full workshop at the summit where I’m talking about many of there concepts:

I work pretty similarly to @alphamoonbase in this regard; make everything fully controllable via extensions and customPars, then create a UI that can bind to that component. This way UI elements can live anywhere in your project. Check out @Jarrett’s SceneChanger in the palette; it has a good example of how one can generate a UI from a template that lives inside of the component, but can then be placed anywhere in your project at the right size and scale that is desired, or further customized. This UI is a controller that references a target component, and can either use binding, or a par exec looking at the target to get bi-directional communicatino

Thanks guys, I will try to approach it the way you described. :slight_smile:

@alphamoonbase & @drmbt I want to thank for your ideas and tips. I really like the concepts you mentioned in this thread and I try to follow them when building UIs.

One thing that is bugging me a bit are quite long expressions needed on UI side. Therefore I wanted to ask whether you might have some recommendation on how to make them shorter, or more readable? I haven’t managed to figure out some cleaner way of writing these. It isn’t a huge deal, but when writing them more and more, I felt a bit lost in their length… :smiley:

parent().par.Maincomp.eval().par.Somepar1 or parent().par.Maincomp.eval().par.Somepar2

I like to move some of these in to extensions as properties.

@property
def Maincomp(self):
    return self.ownerComp.par.Maincomp.eval()

and then you can write

parent().Maincomp.par.Somepar1 or parent().Maincomp.par.Somepar2

But it is better to be considerate about this properties because it can get harder to follow where your values for your properties come from when you start mixing them with non-parametervalues.

1 Like

I usually have these controls also reference custom parameters of the UI container, and then bind those to the main comp as a reference

@alphamoonbase thank you very much for example, it looks nice, but I have noticed this causes my expressions to be unoptimized, which isn’t ideal when having lots of them…

Even though the concept of decoupled functionality and UI is great and I enjoy using it, I have just stumbled upon solution for the original question (which is actually very simple).

Select COMP is perfectly suited for this kind of stuff, but the piece I was missing was having enabled Size from Window on COMP, which is being selected (lets say target COMP). With this enabled, sizing of the Select COMP will be transferred to target COMP (once some window displays Select COMP). This means target COMP will be rendered exactly the way as it would be, if it was placed in position of Select COMP - which is great. :slight_smile:

1 Like