Scaling child frames with parent frame

Is there a simple way to scale all child frames with a parent frame via mousedrag? It seems as if it would be a common requirement, and yet the API doesn’t have anything (that I can find) that accommodates it out of the box like StartSizing() (which doesn’t scale the child frames).

Failing that, has anyone written a general purpose Lua function that handles this?

child frames scale off the parent. sort of like nesting.

eg if the children have a scale of 100% and you set the parent scale to 200% then all the children become 100% of 200% (they also double) without changing anything in them.

note - dont confuse window scale with window dimensions. changing the dimensions of the parent window doesnt do anything to the child frames.

Yeah, I was hoping I’d be able to handle it all via an inbuilt function like StartSize, but it only affects the parent frame. What I’m trying to do is be able to resize all elements of an XP bar (boxes, background XP texture etc.) with a leftclick mousedrag. I figured that should be such a common requirement that there was something in the API like StartSize that would take care of it, but apparently no. Surely the community has written a generic function that handles it (or could be trivially tweaked to handle it), but I haven’t been able to find anything.

you could still use startsizing, just when its complete dont change the dimensions, recalculate a new scale value and set it instead (dont foget to take into account any parent and current frame scale difference on the dimensions)

1 Like

This is a real interesting problem that I fear I don’t have time to work on any more tonight and probably not next couple nights, but if OP or anyone is interested, here’s a potential starting point:

<Ui>
    <Frame name="RescaleGripTemplate" setAllPoints="true" virtual="true">
        <!-- outer frame is setAllPoints and has debug text -->
        <Layers>
            <Layer level="ARTWORK">
                <FontString parentKey="Text" inherits="GameFontHighlight"/>
            </Layer>
        </Layers>
        <Frames>
            <Frame>
                <!-- inner frame is the "rescale grip" in the lower right corner -->
                <Size x="16" y="16"/>
                <Anchors>
                    <Anchor point="BOTTOMRIGHT"/>
                </Anchors>
                <Layers>
                    <Layer level="OVERLAY">
                        <Texture setAllPoints="true">
                            <Color r="1" g="1" b="1"/>
                        </Texture>
                    </Layer>
                </Layers>
                <Scripts>
                    <!-- when mouse goes down, note where mouse started and initial scale, then start
                         an OnUpdate to rescale depending on the cursor's current x position-->
                    <OnMouseDown>
                        self.rightEdge = GetCursorPosition()/UIParent:GetEffectiveScale()
                        self.startScale = self:GetScale()
                        self:SetScript("OnUpdate",function(self,elapsed)
                            local width = self.rightEdge-self:GetParent():GetLeft()
                            local right = self.rightEdge
                            local left = self:GetParent():GetLeft()
                            local cursor = GetCursorPosition()/UIParent:GetEffectiveScale()
                            self:GetParent().Text:SetText(format("left=%d right=%d width=%d cursor=%d p=%.2f",left,right,width,cursor,(cursor-left)/width))
                            local rescale = (cursor-left)/width
                            if rescale>=0 then
                                self:GetParent():GetParent():SetScale(rescale)
                            end
                        end)
                    </OnMouseDown>
                    <OnMouseUp>
                        self:SetScript("OnUpdate",nil)
                    </OnMouseUp>
                </Scripts>
            </Frame>
        </Frames>
    </Frame>

    <Frame name="RescaleGripTest" parent="UIParent" inherits="BasicFrameTemplate">
        <Size x="400" y="400"/>
        <Anchors>
            <Anchor point="CENTER"/>
        </Anchors>
        <Frames>
            <Frame parentKey="Grip" inherits="RescaleGripTemplate"/>
        </Frames>
    </Frame>
</Ui>

It adds a frame to receive mousedown/up events (could use drags to start the rescaling) and when the mouse goes down it notes where the cursor was and the parent frame’s starting scale and then starts an OnUpdate to adjust the scale depending on where the cursor is in relation to its starting position.

The cursor position is only using x, the first return of GetCursorPosition().

It’s buggy but as I said it’s a potential starting point. Another thing you can do is do a SetPoint of the frame after the scale changes so one corner (TOPLEFT?) remains fixed on the screen while the rest scales.

1 Like