WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   How to add a thin border to a frame? (https://www.wowinterface.com/forums/showthread.php?t=58441)

Zax 12-07-20 01:55 AM

How to add a thin border to a frame?
 
Hello,

Is there a simple way to draw/add a thin border to a frame, without any .tga file?
Something like CSS attribute border: 1px solid #00ff00

I tried with Backdrop's edgeFile with some built-in texture files but the result is not accurate (the border is not well drawn), at least with small frames like buttons.

My final goal is to write a function like .addBorder(frame, borderWidth, borderColor)

Xrystal 12-07-20 12:03 PM

Look at one of the preset backdrop examples that are used with the built in frames.
https://www.townlong-yak.com/framexml/live/Backdrop.lua

You may have to look at the inset value as well.

Find a blizzard frame that does something similar to what you want to do and see which of the backdrops they have set up for it. And then go from there.

Zax 12-08-20 06:17 AM

Very interesting link, Xrystal.
Thank you.

Walkerbo 12-12-20 02:11 AM

Just to piggyback onto Xrystal; here is a small sample of frame templates.

Options box template has the finest line, so that may be a great place to start..

Zax 12-12-20 12:35 PM

Nice :)
Thank you.

Kanegasi 12-12-20 02:27 PM

1 Attachment(s)
If you want something simple and direct, this is what I use to add a 1pixel black border around my chat frame with a single pixel missing at the corners:

Lua Code:
  1. local frame = frameYouWantToAddBordersTo
  2.  
  3. local frameborder=CreateFrame("frame",nil,frame)
  4. frameborder:SetAllPoints(frame)
  5. frameborder:SetFrameStrata("BACKGROUND")
  6. frameborder:SetFrameLevel(1)
  7. frameborder.left=frameborder:CreateTexture(nil,"BORDER")
  8. frameborder.left:SetPoint("BOTTOMLEFT",frameborder,"BOTTOMLEFT",-2,-1)
  9. frameborder.left:SetPoint("TOPRIGHT",frameborder,"TOPLEFT",-1,1)
  10. frameborder.left:SetColorTexture(0,0,0,1)
  11. frameborder.right=frameborder:CreateTexture(nil,"BORDER")
  12. frameborder.right:SetPoint("BOTTOMLEFT",frameborder,"BOTTOMRIGHT",1,-1)
  13. frameborder.right:SetPoint("TOPRIGHT",frameborder,"TOPRIGHT",2,1)
  14. frameborder.right:SetColorTexture(0,0,0,1)
  15. frameborder.top=frameborder:CreateTexture(nil,"BORDER")
  16. frameborder.top:SetPoint("BOTTOMLEFT",frameborder,"TOPLEFT",-1,1)
  17. frameborder.top:SetPoint("TOPRIGHT",frameborder,"TOPRIGHT",1,2)
  18. frameborder.top:SetColorTexture(0,0,0,1)
  19. frameborder.bottom=frameborder:CreateTexture(nil,"BORDER")
  20. frameborder.bottom:SetPoint("BOTTOMLEFT",frameborder,"BOTTOMLEFT",-1,-1)
  21. frameborder.bottom:SetPoint("TOPRIGHT",frameborder,"BOTTOMRIGHT",1,-2)
  22. frameborder.bottom:SetColorTexture(0,0,0,1)

A blank "background" container with four black textures anchored to the four corners. With the way this lays out, these lines rest right on the edges of the parent frame, leaving the blank corners clear from the parent frame's own background. Attached is a screenshot of my chatframes. I repeat this code for each chatframe separately.

Zax 12-14-20 02:22 AM

Interesting trick! Thank you Kanegasi.

I tried this, but the result is sometime not very accurate:
Code:

-- params
local borderColor = {1, 1, 1}
local borderWidth = 1
--
if (not frame.SetBackdrop) then Mixin(frame, BackdropTemplateMixin) end
frame.backdrop = {
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        tileEdge = false,
        edgeSize = borderWidth,
        insets = {left = borderWidth, right = borderWidth, top = borderWidth, bottom = borderWidth},
}
frame:SetBackdrop(frame.backdrop)
frame:SetBackdropBorderColor(borderColor[1], borderColor[2], borderColor[3], 1)


runamonk 12-14-20 03:52 AM

The code you tested is correct; I'm guessing you've run into what I've run into and sometimes it's a pixel bigger or smaller than it should be in some places while in others it's perfect?

Zax 12-14-20 07:45 AM

Quote:

Originally Posted by runamonk (Post 337908)
sometimes it's a pixel bigger or smaller than it should be in some places while in others it's perfect?

Yes, that's what happen with a 1px border width: some borders are sometimes drawn with 2px.

runamonk 12-14-20 09:40 AM

I have the same issue. I draw lots of boxes (bags/items in the bags) and even with changing the scaling I could never get it draw everything perfect. Super annoying.

jeffy162 12-14-20 03:54 PM

DISCLAIMERB: I might not use the correct terms, but, this has happened to me also.

I had this issue with one of my laptops - turned out that it was just not "pixel perfect", only I didn't know that until I got a new laptop and everything (all of the borders and such) were perfect. I don't think that is your problem, though. It's my understanding that WoW's parent company has fixed that particular problem. But, I could always be wrong. :o

In my defense I must tell you that I'm 67 years of age and live in an assisted living facility, and I haven't played WoW in four and a half years and I don't believe I ever will again.

Fizzlemizz 12-14-20 04:06 PM

Something else to try:
Lua Code:
  1. local function CreateBorder(self)
  2.     if not self.borders then
  3.         self.borders = {}
  4.         for i=1, 4 do
  5.             self.borders[i] = self:CreateLine(nil, "BACKGROUND", nil, 0)
  6.             local l = self.borders[i]
  7.             l:SetThickness(1)
  8.             l:SetColorTexture(1, 1, 0, 1)
  9.             if i==1 then
  10.                 l:SetStartPoint("TOPLEFT")
  11.                 l:SetEndPoint("TOPRIGHT")
  12.             elseif i==2 then
  13.                 l:SetStartPoint("TOPRIGHT")
  14.                 l:SetEndPoint("BOTTOMRIGHT")
  15.             elseif i==3 then
  16.                 l:SetStartPoint("BOTTOMRIGHT")
  17.                 l:SetEndPoint("BOTTOMLEFT")
  18.             else
  19.                 l:SetStartPoint("BOTTOMLEFT")
  20.                 l:SetEndPoint("TOPLEFT")
  21.             end
  22.         end
  23.     end
  24. end
  25.  
  26. local f = CreateFrame("Frame")
  27. f:SetSize(40, 40)
  28. f:SetPoint("CENTER")
  29. f.bg = f:CreateTexture()
  30. f.bg:SetAllPoints()
  31. f.bg:SetTexture("Interface/BUTTONS/WHITE8X8")
  32. f.bg:SetVertexColor(0, 0, 0)
  33. f:SetResizable(true)
  34. f:EnableMouse(true)
  35. f:RegisterForDrag("LeftButton")
  36. f:SetScript("OnDragStart", function(self)
  37.     self:StartSizing("BOTTOMRIGHT")
  38. end)
  39. f:SetScript("OnDragStop", function(self)
  40.     self:StopMovingOrSizing()
  41. end)
  42.  
  43. CreateBorder(f)

It's along the same lines as Kanegasi's solution.

Zax 12-15-20 02:32 AM

Maybe it should be intensively tested but Fizzlemizz's solution seems perfect :)

Though, I don't understand why corners are rounded (it's obvious with thickness > 1)

Kanegasi 12-15-20 02:10 PM

If you're using the backdrop method, the API behind that is called "NineSlice". This is a method of creating resizeable textured frames of nine pieces, consisting of four static corners, four repeatable edge textures, and a repeatable background. The corners are rounded because they are separate textures, the roundness not noticeable at really tiny sizes.

Zax 12-16-20 03:03 AM

Considring Fizzlemizz's script, is there a way to modify border color of an existing border, previously created with his script?

Lua Code:
  1. local function CreateBorder(self)
  2.     if not self.borders then
  3.         self.borders = {}
  4.         for i=1, 4 do
  5.             self.borders[i] = self:CreateLine(nil, "BACKGROUND", nil, 0)
  6.             local l = self.borders[i]
  7.             l:SetThickness(1)
  8.             l:SetColorTexture(1, 1, 0, 1)
  9.             if i==1 then
  10.                 l:SetStartPoint("TOPLEFT")
  11.                 l:SetEndPoint("TOPRIGHT")
  12.             elseif i==2 then
  13.                 l:SetStartPoint("TOPRIGHT")
  14.                 l:SetEndPoint("BOTTOMRIGHT")
  15.             elseif i==3 then
  16.                 l:SetStartPoint("BOTTOMRIGHT")
  17.                 l:SetEndPoint("BOTTOMLEFT")
  18.             else
  19.                 l:SetStartPoint("BOTTOMLEFT")
  20.                 l:SetEndPoint("TOPLEFT")
  21.             end
  22.         end
  23.     end
  24. end
  25.  
  26. local f = CreateFrame("Frame")
  27. f:SetSize(40, 40)
  28. f:SetPoint("CENTER")
  29. f.bg = f:CreateTexture()
  30. f.bg:SetAllPoints()
  31. f.bg:SetTexture("Interface/BUTTONS/WHITE8X8")
  32. f.bg:SetVertexColor(0, 0, 0)
  33. f:SetResizable(true)
  34. f:EnableMouse(true)
  35. f:RegisterForDrag("LeftButton")
  36. f:SetScript("OnDragStart", function(self)
  37.     self:StartSizing("BOTTOMRIGHT")
  38. end)
  39. f:SetScript("OnDragStop", function(self)
  40.     self:StopMovingOrSizing()
  41. end)
  42.  
  43. CreateBorder(f)

Kanegasi 12-16-20 07:51 AM

The textures are stored as indexes in the borders key of the parent frame. If you were to do ZaxBorders=CreateFrame("frame") instead of local f=CreateFrame("frame"), you can change the colors like so:

Lua Code:
  1. for i=1,4 do
  2.     ZaxBorders.borders[i]:SetColorTexture(r,g,b,a)
  3. end

Also, the way the code is currently ordered, 1 is top, 2 is right, 3 is bottom, and 4 is left. You can change the color of, say, just the bottom with this:

ZaxBorders.borders[3]:SetColorTexture(r,g,b,a)

Fizzlemizz 12-16-20 09:52 AM

Again, the same as Kanegasi but slightly different in order to bake the border colouring into your created frames:

Lua Code:
  1. local function ColorBorders(self, r, g, b, a)
  2.     for i=1, 4 do
  3.         self.borders[i]:SetColorTexture(r, g, b, a and a or 1)
  4.     end    
  5. end
  6.  
  7. local function CreateBorderFrame(name, thickness)
  8.     local f = CreateFrame("Frame", name)
  9.     f:SetSize(40, 40)
  10.     f.bg = f:CreateTexture()
  11.     f.bg:SetAllPoints()
  12.     f.bg:SetTexture("Interface/BUTTONS/WHITE8X8")
  13.     f.bg:SetVertexColor(0, 0, 0)
  14.     f:SetResizable(true)
  15.     f:EnableMouse(true)
  16.     f:RegisterForDrag("LeftButton")
  17.     f:SetScript("OnDragStart", function(self)
  18.         self:StartSizing("BOTTOMRIGHT")
  19.     end)
  20.     f:SetScript("OnDragStop", function(self)
  21.         self:StopMovingOrSizing()
  22.     end)
  23.     f.SetBorderColor = ColorBorders
  24.     f.borders = {}
  25.     local offset = (thickness/2)
  26.     for i=1, 4 do
  27.         f.borders[i] = f:CreateLine(nil, "BACKGROUND", nil, 0)
  28.         local l = f.borders[i]
  29.         l:SetThickness(thickness)
  30.         l:SetColorTexture(1, 1, 0, 1)
  31.         if i==1 then
  32.             l:SetStartPoint("TOPLEFT", -offset, 0)
  33.             l:SetEndPoint("TOPRIGHT", offset, 0)
  34.         elseif i==2 then
  35.             l:SetStartPoint("TOPRIGHT", 0, offset)
  36.             l:SetEndPoint("BOTTOMRIGHT", 0, -offset)
  37.         elseif i==3 then
  38.             l:SetStartPoint("BOTTOMRIGHT", offset, 0)
  39.             l:SetEndPoint("BOTTOMLEFT", -offset, 0)
  40.         else
  41.             l:SetStartPoint("BOTTOMLEFT", 0, -offset)
  42.             l:SetEndPoint("TOPLEFT", 0, offset)
  43.         end
  44.     end
  45.     return f
  46. end
  47.  
  48. local f = CreateBorderFrame("ZaxFrame1", 1)
  49. f:SetPoint("RIGHT", UIParent, "CENTER", -20, 0)
  50. f = CreateBorderFrame("ZaxFrame2", 18)
  51. f:SetPoint("LEFT", UIParent, "CENTER", 20, 0)
  52. ZaxFrame2:SetBorderColor(0.2, 0.5, 0.8)

Zax 12-16-20 10:17 AM

Great :)
Thank you very much Fizzlemizz and Kanegasi for your scripts, and also for your time and patience.

Spyro 12-19-20 02:19 AM

Quote:

Originally Posted by Kanegasi (Post 337936)
If you're using the backdrop method, the API behind that is called "NineSlice". This is a method of creating resizeable textured frames of nine pieces, consisting of four static corners, four repeatable edge textures, and a repeatable background. The corners are rounded because they are separate textures, the roundness not noticeable at really tiny sizes.

Didn't know the backdrop borders have parentkeys. :eek:

Do the corners have parentkeys too?

Currently I'm accesing them with GetRegions() lol.

Vrul 12-19-20 07:26 AM

Quote:

Originally Posted by Spyro (Post 337977)
Didn't know the backdrop borders have parentkeys. :eek:

Do the corners have parentkeys too?

Currently I'm accesing them with GetRegions() lol.

These are the default names:
TopLeftCorner
TopRightCorner
BottomLeftCorner
BottomRightCorner
TopEdge
BottomEdge
LeftEdge
RightEdge
Center

However, the pieces are accessed via:
Lua Code:
  1. local function GetNineSlicePiece(container, pieceName)
  2.     if container.GetNineSlicePiece then
  3.         local piece = container:GetNineSlicePiece(pieceName);
  4.         if piece then
  5.             return piece, true;
  6.         end
  7.     end
  8.  
  9.     local piece = container[pieceName];
  10.     if piece then
  11.         return piece, true;
  12.     else
  13.         piece = container:CreateTexture()
  14.         container[pieceName] = piece;
  15.         return piece, false;
  16.     end
  17. end

The only two places I found using GetNineSlicePiece were for Blizzard_BFAMissionUI and Blizzard_CovenantMissionUI which had keys:
TopLeftCorner
TopRightCorner
BotLeftCorner
BotRightCorner
TopBorder
BottomBorder
LeftBorder
RightBorder


All times are GMT -6. The time now is 06:11 AM.

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