WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Overlapping NineSlice textures with ButtonFrameTemplate (https://www.wowinterface.com/forums/showthread.php?t=57891)

LudiusMaximus 03-28-20 10:05 AM

Overlapping NineSlice textures with ButtonFrameTemplate
 
I am using ButtonFrameTemplate for a frame.
But as my frame has a low height I get overlapping NineSlice textures resulting in the frame shaddows adding up.



Lua Code:
  1. local myFrame = CreateFrame("Frame", "myFrame", UIparent, "ButtonFrameTemplate")
  2. myFrame:SetPoint("TOPLEFT")
  3. ButtonFrameTemplate_HidePortrait(myFrame)
  4. myFrame:SetFrameStrata("HIGH")
  5. myFrame:SetWidth(430)
  6. myFrame:SetHeight(220)
  7.  
  8. myFrame.NineSlice.LeftEdge:Hide()
  9. myFrame.NineSlice.RightEdge:Hide()

As you can see, I already removed NineSlice.LeftEdge and NineSlice.RightEdge but is it possible to crop the NineSlice corner textures somehow?

Or is there another solution like using the templates differently?

Vrul 03-28-20 02:26 PM

I would resize the bottom corners and not hide the edges:
Code:

local myFrame = CreateFrame("Frame", "myFrame", UIparent, "ButtonFrameTemplate")
myFrame:SetPoint("TOPLEFT")
ButtonFrameTemplate_HidePortrait(myFrame)
myFrame:SetFrameStrata("HIGH")
myFrame:SetWidth(430)
myFrame:SetHeight(220)
 
local function ResizeCorner(parent, cornerName, newX, newY)
        local corner = parent[cornerName]
        local oldX, oldY = corner:GetSize()
        local L, R, T, B = 0, newX / oldX, 0, newY / oldY
        if cornerName:match("Right") then
                L, R = 1 - R, 1
        end
        if cornerName:match("Bottom") then
                T, B = 1 - B, 1
        end
        corner:SetSize(newX, newY)
        corner:SetTexCoord(L, R, T, B)
end

ResizeCorner(myFrame.NineSlice, "BottomLeftCorner", 36, 36)
ResizeCorner(myFrame.NineSlice, "BottomRightCorner", 36, 36)


LudiusMaximus 03-28-20 05:05 PM

Thanks so much (again)! :-)
So it comes down to SetTexCoord() once more.


Can I ask a general question regarding this?

If I have a texture file
e.g. Interface/FrameGeneral/UIFrameMetal:



How would I go about to find the correct SetTexCoord() arguments for, say, the texture with the two topright buttom slots?

In this particular case I know that there is the Atlas name UI-Frame-Metal-CornerTopRightDouble, which I found out using Texture Atlas Viewer.

But for any texture in general, how do you find out your desired SetTexCoord() arguments?
Is there a tool for this as well?

Fizzlemizz 03-28-20 05:16 PM

For the most part, find the Blizzard XML file the frame/texture is defined in and check for its TexCoords tag.
Code:

<TexCoords left="0" right="0.675" top="0" bottom="0.675"/>
Exporting the Blizzard UI

Vrul 03-28-20 05:38 PM

Or you would open it in an image editor and count pixels to calculate the coords as they are in percentages of the image's dimensions.

LudiusMaximus 03-28-20 05:39 PM

Quote:

Originally Posted by Fizzlemizz (Post 335440)
For the most part, find the Blizzard XML file the frame/texture is defined in and check for its TexCoords tag.

Ah, thanks! I see that this is used quite a lot.

But when I try to find the textures and coordinates used by ButtonFrameTemplate, I seem to run into a dead end...

In BlizzardInterfaceCode\Interface\SharedXML\SharedUIPanelTemplates.xml I find the definition of ButtonFrameTemplate. But when I trace back the inheritances I end up here without any mention of Interface/FrameGeneral/UIFrameMetal or any of its Atlas equivalents:

Code:

  <Frame name="NineSlicePanelTemplate" mixin="NineSlicePanelMixin" frameLevel="500" setAllPoints="true" virtual="true">
    <Scripts>
      <OnLoad method="OnLoad"/>
    </Scripts>
  </Frame>

Is this a non-"for the most part" case, then?

Vrul 03-28-20 06:26 PM

For your example you would use:
Code:

myFrame.NineSlice.TopRightCorner:SetTexture("Interface\\FrameGeneral\\UIFrameMetal")
myFrame.NineSlice.TopRightCorner:SetTexCoord(0/512, 133/512, 269/512, 401/512)

I found the coords to be (0/512, 133/512, 282/512, 401/512) based on pixels but they seem to use a bit of extra white space at the top so I just kept tweaking the third argument (which is the top) until I arrived at a good fit.

Note that I left all arguments in the form pixelPos/dimensionSize to make it easier to understand (I hope).

LudiusMaximus 03-28-20 06:29 PM

Quote:

Originally Posted by Vrul (Post 335443)
I found the coords to be (0/512, 133/512, 282/512, 401/512) based on pixels

Thanks for your reply! So it is a lot of tweaking after all, unless you find the Atlas name or the TexCoords anywhere. I learned a lot today! Thanks again! :-D

Fizzlemizz 03-28-20 07:42 PM

Maybe something like Discord Art (or probably KgPanels) where you can create a texture with the artwork and click some buttons and/or enter coords so you don't have to do continous /reload. Possibly quicker for getting started at least.

LudiusMaximus 03-31-20 03:51 AM

May I ask a related follow-up question?

I would like to place a button divider texture in my frame:

Code:

local myFrame = CreateFrame("Frame", "cosFix_SetFactorFrame", UIparent, "ButtonFrameTemplate")
myFrame:SetPoint("TOPLEFT")
ButtonFrameTemplate_HidePortrait(myFrame)
myFrame:SetFrameStrata("HIGH")
myFrame:SetWidth(430)
myFrame:SetHeight(220)

myFrame.exportButton = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
myFrame.exportButton:SetPoint("TOPRIGHT", -20, 0)
myFrame.exportButton:SetText("Export")
myFrame.exportButton:SetWidth(70)

myFrame.exportButton.btnDivLeft = f.NineSlice:CreateTexture("cosFix_btnDivLeft", "BORDER")
myFrame.exportButton.btnDivLeft:SetPoint("RIGHT", f.exportButton, "LEFT", -10, 0)
myFrame.exportButton.btnDivLeft:SetAtlas("UI-Frame-BtnDivLeft", true)

It should look like this:



But what I get is:



(The -10 offset is there on purpose for testing.)
But how can I get on top of the NineSlice border texture??

Vrul 03-31-20 06:59 AM

The region method SetDrawLayer is what you want to use.

LudiusMaximus 03-31-20 07:27 AM

Quote:

Originally Posted by Vrul (Post 335489)
The region method SetDrawLayer is what you want to use.

Hm thanks, but could you please be a little more specific?

Which is the LayeredRegion I should call SetDrawLayer() for?

The only texture I could think of was myFrame.NineSlice.TopRightCorner.

So I tried
Code:

myFrame.NineSlice.TopRightCorner:SetDrawLayer("BORDER")
but how do I continue from here?

LudiusMaximus 03-31-20 07:44 AM

Actually, I am getting very indeterministic results...

As I am trying to find the right offset and size it is sometimes drawn on top and sometimes drawn below the NineSlice border... :confused:

Code:

myFrame.NineSlice.TopRightCorner:SetDrawLayer("BORDER")
myFrame.exportButton.btnDivLeft = myFrame.NineSlice:CreateTexture("cosFix_btnDivLeft", "BORDER")
myFrame.exportButton.btnDivLeft:SetPoint("RIGHT", myFrame.exportButton, "LEFT", 5, 0)
myFrame.exportButton.btnDivLeft:SetAtlas("UI-Frame-BtnDivLeft", true)
local oldX, oldY = myFrame.exportButton.btnDivLeft:GetSize()
local shrinkFactor = 0.854
myFrame.exportButton.btnDivLeft:SetSize(oldX*shrinkFactor, oldY*shrinkFactor)


LudiusMaximus 03-31-20 08:20 AM

Quote:

Originally Posted by Vrul (Post 335489)
The region method SetDrawLayer is what you want to use.

Sorry, but I have absolutely no idea what I am supposed to do with SetDrawLayer! :(

All I could come up with was this work around.

Code:

local oldX, oldY = 12, 24
local shrinkFactor = 0.83
myFrame.exportButton.btnDivLeft = CreateFrame("Frame", nil, f.exportButton)
myFrame.exportButton.btnDivLeft:SetPoint("RIGHT", f.exportButton, "LEFT", 6, 0)
myFrame.exportButton.btnDivLeft:SetSize(oldX*shrinkFactor, oldY*shrinkFactor)
myFrame.exportButton.btnDivLeft:SetFrameStrata("DIALOG")
local texture = myFrame.exportButton.btnDivLeft:CreateTexture()
texture:SetAllPoints()
texture:SetAtlas("UI-Frame-BtnDivLeft")

But I would still be very interested in learning the mysteries of SetDrawLayer()...

Vrul 03-31-20 08:21 AM

Both regions are sharing a layer so you need to make sure the subLevel of your new texture is greater than the other:
Code:

local layer, subLevel = myFrame.NineSlice.TopRightCorner:GetDrawLayer()
myFrame.exportButton.btnDivLeft = myFrame.NineSlice:CreateTexture("cosFix_btnDivLeft")
myFrame.exportButton.btnDivLeft:SetDrawLayer(layer, subLevel + 1)
myFrame.exportButton.btnDivLeft:SetPoint("RIGHT", myFrame.exportButton, "LEFT", 5, 0)
myFrame.exportButton.btnDivLeft:SetAtlas("UI-Frame-BtnDivLeft", true)
local oldX, oldY = myFrame.exportButton.btnDivLeft:GetSize()
local shrinkFactor = 0.854
myFrame.exportButton.btnDivLeft:SetSize(oldX*shrinkFactor, oldY*shrinkFactor)

Edit: Or you could have used different layers:
Code:

myFrame.NineSlice.TopRightCorner:SetDrawLayer("BORDER")
myFrame.exportButton.btnDivLeft = myFrame.NineSlice:CreateTexture("cosFix_btnDivLeft", "OVERLAY")
myFrame.exportButton.btnDivLeft:SetPoint("RIGHT", myFrame.exportButton, "LEFT", 5, 0)
myFrame.exportButton.btnDivLeft:SetAtlas("UI-Frame-BtnDivLeft", true)
local oldX, oldY = myFrame.exportButton.btnDivLeft:GetSize()
local shrinkFactor = 0.854
myFrame.exportButton.btnDivLeft:SetSize(oldX*shrinkFactor, oldY*shrinkFactor)


LudiusMaximus 03-31-20 08:27 AM

Ahhhh! Thank you so much!

It turns out the layer of NineSlice.TopRightCorner is "OVERLAY", not "BORDER"!!
This is why I never had a chance! :D


All times are GMT -6. The time now is 07:42 AM.

vBulletin © 2020, Jelsoft Enterprises Ltd
© 2004 - 2020 MMOUI