Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Groups: Allow dynamic groups to resize auras #4057

Open
InfusOnWoW opened this issue Nov 23, 2022 · 3 comments
Open

Dynamic Groups: Allow dynamic groups to resize auras #4057

InfusOnWoW opened this issue Nov 23, 2022 · 3 comments
Labels
🎨 Feature Request This is a request for a new feature, or an expansion of an existing feature.

Comments

@InfusOnWoW
Copy link
Contributor

Currently dynamic groups take over the positioning of auras.

With dragonflight users have been experimenting/requesting functionality that allows for resizing auras.

One very common layout has a resource bar (Or in the case of rogue combo points) in a row, and below that a number of icons and the width of these should be synced by either resizing the resource row or resizing the icons.

Sometimes there are additional rows of icons, sometimes the aspect ratio of the icons should be kept.

Additional things to consider

  • How do Luxthos/Afenar(?) layout their class auras dynamically
  • There's a very similar request for resizing that comes from attaching e.g. a number of progress bars to an unit frame, where the width of the auras should depend on the unit frame's width. Or sometimes a singular aura is attached to a unit frame, and should resize to the unit frame's size.
  • How does resizing interact with size-changing conditons and animations that scale auras
  • Currently dynamic groups don't relayout auras if the size is changed via conditions/animations. How does that fit in, if dgs do relayout if they are the ones changing the size.

Potential approaches are:

  • Multiple dynamic groups, e.g. for the progress bar adjusts to icons beneath:
    ** DG1 contains icons
    ** DG2 contains progress bar and is attached to DG1. DG2 is set to "adjust width to DG1"

  • More powerful grow functions
    ** [...]

@InfusOnWoW InfusOnWoW added the 🎨 Feature Request This is a request for a new feature, or an expansion of an existing feature. label Nov 23, 2022
@github-actions github-actions bot added the ⏱ Awaiting Response This ticket hasn't been triaged yet. label Nov 23, 2022
@mrbuds
Copy link
Contributor

mrbuds commented Nov 24, 2022

Link to an experimental implementation mrbuds@29c82b5

Idea was to have ability to set a minimum and/or maximum width & height
With choices:

  • not change
  • user defined size
  • parent's size

This approach resize each children, all grow functions needs to be slightly rewritten to handle it.

An other approach i have in mind to simplify implementation is to make it change group scale instead of children's size.

Handling of parent resizing is not handled on this implementation

image

image

@psyquest

This comment was marked as off-topic.

@InfusOnWoW
Copy link
Contributor Author

I guess I should post what I posted on your commit also to this ticket, so that it's all in one place:

think this goes in the right direction.

A few conceptual comments:
Fundamentally dynamic groups use ther children sizes to calculate their own size. If you consider nested dynamic groups, that would work the same way. The parent's dynamic group calculates its size based on the dynamic group one level below. And we should imho always consider nested dynamic groups as something we want eventually add.

Adding a fixed/parent size mode to dynamic groups changes that.

For fixed mode, the DG now applies a size to its children.
And to make the discussions a bit easier to follow let's define a few concepts:

static size => whatever is in data.width/data.height
region size => whatever was last set via setRegionWidth/setRegionHeight
layout size => whatever the dg wants the aura size to be, this is the result of the grow function
effective size => the actual size that the aura is set too.
dg own size => the size of a dg based on its children/fixed/parent mode
Where size is obviously height(width. I frequently talk about e.g. setRegionSize, when I mean both SetRegionWidth and SetRegionHeight

This creates problems in three cases:

Text Auras
Nested DGs
Condition sizes
Animations
Layouting with region size

** Text Auras **
Text Auras are a bit different from the other auras, in that we layout them based on their region size not based on their static size. Now, this results in a circular dependency, where we layout based on the region size, calculate a layout size and then set it on the text as its region size. It's imagine a scenario where this would lead to counter-intuitive results.
=> I see two ways around that problem:

Don't allow seting a fixed/parent mode if the dynamic group contains text auras
Distinguish between layout size, region size and effective size. So that is for grow functions the static size/region size is the input and layout size is the output.
** Layout size overrrides region size, effective size is basically whatever the layout says it is
** Region size overrids layout size, so the for text auras whatever the dg thinks is the right size is ignored.

** Nested DGs **
Obviously we don't have these yet, but imho anything we add needs to be conceptually compatible with them. As I think we'll eventually add them.
So let's consider this (contrived) setup:

GP (grand parent dynamic group)
** C (child dynamic group)
*** A (Auras contained in C)

For dynamic groups, they obviously don't have a static size. So if we don't have any fixed mode settings, I think it's obvious how it should work. The auras A get shown/hidden, C layouts A determines its size. GP is informed that C size change and uses C's dg own size to layout. If C has a fixed size, then that's taken into account in the layout, and its own size should respect the fixed size.

But what if GP has a fixed size set and wants to set a size on C. That obviously can't work, as now the size of C is both controlled by itself via its children and GP.
=>I think the answer is similar to text auras.
If a DG contains a DG (or a group for similar reasons), then it can't be set into fixed mode.

** Data Size Condition Sizes **
You are currently calling SetRegionWidth/SetRegionHeight, which are also set via conditions. Thus there an obvious conflict here.
=> There are a few ways to solve that

Don't allow setting a size via conditions if the aura is in a group with fixed/parent mode.
Again introduce the concept of a effectice size
** Layout size overrrides region size, effective size is basically whatever the layout says it is
** Region size overrides layout size, that is the region is layed out according to what the DG assigned as a size to it. But if a condtion makes the aura bigger, than it's simply made bigger in place without affecting others around it. This is somewhat similar to how conditions and DGs work now.

** Animations **
Animations currently affect something called the "scale". Which can also annoyingly flip auras. How does that fit into it?
=> Potential behaviours

Scale is applied at the end, but does not affect layout. It applied to the "effective" size.
Scale applies to the region size, and is overwritten by layout size.

** Layouting with region size **
This does come up from time to time, and while we don't need to include it here, we should at least think about how this fit into it.

I think this can be worked out for fixed sizes. I'm more sceptical about "parent" size, because it has all the same problems but also issues on its own:

What if the parent is a dynamic group?
If the dynamic group is attached somewhere, we probably should adjust to the size if the target frame changes.
=> I'd leave this out, to be figure out at a later date.

WIth that said conceptually I think my preferred solution looks like this:

Each region has 3 properties:

static size
** this is simply what data.size is
region size
** intially nil
** is set via condtions
** there are changes needed so that deactivating a size changing condition sets it to nil again. I think the width/height properies need renaming
scale
** initially 1
** is set via animation
** layout size
** is intially nil
** set via dynamic group's layout funtion

Setting any of them calls a function updateEffectiveSize(), which based on our logic sets the actual frame size to the effective size. Currently that is directly done in SetRegionSize, that basically inserts an additional indirection in between. The old code in SetRegionSize is moved to updateEffectiveSize, and SetRegionSize now calls updateEffectiveSize.

I think the logic in updateEffectiveSize should be:

If region size is set, then use that,
else if layout size is set, then use that,
else use static size
Multiply it with scale to get the final size

For Dynamic Groups

If a dynamic group contains a text/group/dynamic group, there's no fixed mode setting at all
We don't introduce a parent mode setting. I'm think there are too many edge cases there that I don't want to figure out
The grow functions input is the static size (with the exception for text region type)
The grow functions output is a layout size, which is also used for positioning
The effect of that is, that size changes via conditions, or scaling via animations does not affect dynamic group layouts, essentially behaving like they do now.
But I can see how an optional flag for that behaviour would work. The region would need to inform the DG in its setRegionSize function that it needs to layout. And the dynamic group needs to take that flag into account so that it fetches the region size and not the static size. There's no circular dependency, so it should all work and not even require any changes to updateEffectiveSize

Now to your implementation, it's obvious a first take. I think instead of doing the size adjustments directly in getMinMax size, the size should be an output of the grow. Also some of the calculations are done per aura that never changes.
The function should not directly call the regions setters. That should be the job of the dynamic group, similar to how the grow function merely returns the position. Currently the grow function returns per frame/position an array, {x, y, show}. I think we can in a backwards compatible way adaopt a change that rivers did and name them. So {x = x, y = y, show = true, width = w, height = h }. And on reading simply do x = newPositions[..].x or newPositions[..][1]

As to your implementations, the most complex will certainly be grid. then centered and lastly the simple horizontal/vertical.

For grid, let's talk through a complex example:

Grid in right, then down layout. With a row limit of 3
All icons, but different sizes, e.g. first row has 3 big icons 60x60, next row is 3 small icons 30x30
Keep aspect ratio is enabled
The grid exceeds both the max width 120 and max height 60 setting. It is 180 wide and 90 high

So first question if the grid exceeds the sizes, should everything be scaled by the same ratio?

To make the big icons fit, their width needs to be reduced from 180 total, to 120. Should the small icons be also reduced in size?
If yes, then they are reduced from 30 to 20, the ratio of 2/3 works for both.
If not, then the height will be 70, meaning to high with a 2/3 scaling factor.

My conclusion
=> There's one scaling factor and it's applied to everything.
So layouting works in 2 phases. First phase lays out everything without any regard to max/min widht/height setting, calculating a scaling factor as we lay out. I think for the example above of right, then down, we would need for each row check against min/max size and want to remember the smallest scaling factor. And at the end use the height to check against min/max height and again use the smallest scaling factor.

Then we essentially rerun the layouting algorithm with the scaling factor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🎨 Feature Request This is a request for a new feature, or an expansion of an existing feature.
Projects
None yet
Development

No branches or pull requests

4 participants