While the cC skin format may seem daunting, it's actually quite efficient. We just need to format it better so that it's more readable to the human eye.
Additionally, we need a simple (global) variable to "check" prior to adding data to the skin table. One that's verified, we can call a predefined function that takes an array to add the new skin to the table. Though if you do it the way I think you'll do it, it'll be an "if not this = skin(new) return" type of deal, which makes my prior statement irrelevant. >.<
Finally, all "layers"/elements, etc. should have anchor points of CENTER/CENTER to the icon (to make alignment easier) then allow for size adjustments and offsets (for tweaking per element/skin).
Are you referring to the default UI from your tests? Because I know that cyCircled doesn't hide the border texture on any state. It's a static "background" with the other states overlaid. The only caveat to the hide/show method is whether or not interactive state textures are already loaded into memory. The last thing we want is to mouse over a button, have the border disappear for a split second before the new state shows up.
Honestly, whether or not the border texture, etc, get hidden on state changes is completely up to the code. I think it should be optional (per skin) as some skins only require some slight enhancements to the default border for the various states. To see what I mean, check out the images in my Onyx skin.
Actually, no. Button Frames have four special textures, and CheckButton Frames have a fifth in addition. These textures are the NormalTexture, HighlightTexture, PushedTexture, DisabledTexture, and CheckedTexture. They are set using special code. When the button is pushed, the PushedTexture is used instead of the NormalTexture. This change is instant. Likewise, switching from Enabled to Disabled (and back) causes the change instantly. The HighlightTexture is shown anytime the mouse is in the button, without any additional code. It does not hide the Normal/Pushed/Disabled Textures (the "Border" Textures). The CheckedTexture is shown whenever the :SetChecked(1) function is called on the button. It, also, does not interfere with the "Border" textures.
All of this happens automatically, without any additional code, and is a side benefit of using the Button and CheckedButton Frame types. I am merely stating that these special textures will be used correctly in ButtonFacade, because it makes programming an action button that much easier. The skinning side of things, however, will be quite the same. Skinners will only need to know that the Border, Pushed, and Disabled layers are never shown at the same time, and should be designed to account for this fact.
Quote from StormFX »
While the cC skin format may seem daunting, it's actually quite efficient. We just need to format it better to that it's more readable to the human eye. Though some of the attributes will vary.
That's about all I'm doing.
Additionally, we need a simple (global) variable assigned to the library and/or the skins tables for skin files to "check" prior to adding data to the skin table. One that's verified, we can call a predefined function that takes an array to add the new skin to the table.
The lib:AddSkin(...) function will have an option to replace a pre-existing skin. If the option is true, it will silently replace it. If false, it will silently NOT replace it.
Finally, all "layers", etc. should have anchor points of CENTER/CENTER to the icon (to make alignment easier) then allow for size adjustments and offsets (for tweaking per skin).
If you're suggesting that all layers be anchored from CENTER to CENTER no matter what, then I like the idea, and will implement it.
One thing though and this might be out of the scope for the addon but what about making this work for all sorts of icons, like in EBB, parrot etc? That'd be pretty hawt.
One thing though and this might be out of the scope for the addon but what about making this work for all sorts of icons, like in EBB, parrot etc? That'd be pretty hawt.
This is outside the scope of our goals. Skinning an Icon, which was never meant to be used as a button, is an entirely different concept from skinning a Button.
If you're suggesting that all layers be anchored from CENTER to CENTER no matter what, then I like the idea, and will implement it.
That's exactly what I'm suggesting >.<
One thing though and this might be out of the scope for the addon but what about making this work for all sorts of icons, like in EBB, parrot etc? That'd be pretty hawt.
Button skinning mods only work on buttons. If the icon or buff mod has created them by using button frames (Like buffalo is - I think), then it's feasible. Otherwise, it's not.
This is outside the scope of our goals. Skinning an Icon, which was never meant to be used as a button, is an entirely different concept from skinning a Button.
Yes, I thought that might be the case. Anyways, this seems awesome, will definantly be using it!
I have the Library at near complete status (barring bugs/improvements/etc.) and am working on the GUI tomorrow, along with some of my IB2 stuff. Tomorrow I will definitely set up the Google Code page so developers and skinners can at least see how it's progressing.
:AddSkin(SkinID,overwrite,skindata) Registers a new skin. If overwrite is true, it will silently replace an existing skin. If false, it will silently fail.
skindata takes the following form:
{
Backdrop = { -- If a layer is unused, it should only have the Hide attribute set to true.
Hide = true
},
Icon = {
Width = 36,
Height = 36,
},
Cooldown = {
Width = 36,
Height = 36,
},
AutoCast = {
Width = 36,
Height = 36,
},
AutoCastable = {
Width = 58,
Height = 58,
Texture = [[Interface\Buttons\UI-AutoCastableOverlay]],
-- For ease of use, use the [[ ]] string delimiters, no need to use \\ in them.
},
Border = {
Width = 66,
Height = 66,
Texture = [[Interface\Buttons\UI-Quickslot2]],
OffsetY = -1,
},
Pushed = {
Width = 36,
Height = 36,
Texture = [[Interface\Buttons\UI-Quickslot-Depress]],
},
Disabled = {
Width = 66,
Height = 66,
Texture = [[Interface\Buttons\UI-Quickslot2]],
-- OffsetX defaults to 0, so it is unnecessary here.
OffsetY = -1,
},
Highlight = {
Width = 36,
Height = 36,
Texture = [[Interface\Buttons\ButtonHilight-Square]],
BlendMode = "ADD",
},
Checked = {
Width = 36,
Height = 36,
Texture = [[Interface\Buttons\CheckButtonHilight]],
BlendMode = "ADD",
},
Gloss = {
Hide = true
},
HotKey = {
Width = 36,
Height = 10,
OffsetX = -2,
OffsetY = 11,
},
Count = {
Width = 36,
Height = 10,
OffsetX = -2,
OffsetY = -11,
},
Name = {
Width = 36,
Height = 10,
OffsetY = -11,
},
}
API for Actionbar Addons:
:Group(Addon,Group,Button) Retrieves the specified group. Group and Button can be nil. Button must be nil if Group is nil. Creates the group, and higher level groups, if it does not exist. Returns an LBFGroup object. The default skin for a new group is "Blizzard", with no gloss or backdrop.
:DeleteGroup(Addon,Group,Button) Deletes the specified group, and all sub groups. Sets the skin of all associated buttons to "Blizzard" when this happens.
:RegisterSkinCallback(Addon,callback,arg) Registers a callback to be executed whenever the skin is changed on any group with Addon. Callback is called as: callback(arg,SkinID,Gloss,Backdrop,Group,Button)
LBFGroup:AddButton(btndata) Adds the button specified in btndata to the group. btndata must not be reused for other buttons. Automatically skins the button according to the group's settings. Will automatically remove the button from other groups if necessary. Does nothing if the button is already in the group.
LBFGroup:RemoveButton(btndata,noReskin) Removes the button from the group. Unless noReskin is true, this will reskin the button to "Blizzard" without gloss and backdrop.
LBFGroup.SkinID Contains the group's current SkinID. Setting this will not reskin the group.
LBFGroup.Gloss Contains the group's current Gloss. Setting this will not reskin the group.
LBFGroup.Backdrop Contains the group's current Backdrop. Setting this will not reskin the group.
btndata takes the following form:
{
Button = <Button or CheckButton frame>,
-- any of the following can be omitted or set to nil to have LBF find it from the name of Button.
-- set any of the following to false to force LBF to not skin that layer.
Icon = <defaults to _G[Button:GetName().."Icon"]>,
Cooldown = <defaults to _G[Button:GetName().."Cooldown"]>,
AutoCast = <defaults to _G[Button:GetName().."Autocast"]>,
AutoCastable = <defaults to _G[Button:GetName().."AutoCastable"]>,
HotKey = <defaults to _G[Button:GetName().."HotKey"]>,
Count = <defaults to _G[Button:GetName().."Count"]>,
Name = <defaults to _G[Button:GetName().."Name"]>,
}
API for Skin Choosing:
:ListSkins() Returns a list of skins suitable for use in a LibRockConfig choice control or a LibAceConfig select option.
:ElementListCallback(callback,arg) Registers a callback fired when a group's contents change. called like: callback(arg,Addon,Group). Use this to refresh the list of groups.
:ListAddons() Returns the list of current Addons in a table. The keys are unique registration strings. The values are the name of the Addon.
:ListGroups(Addon) Returns the list of Groups from the given Addon in a table. The keys are unique registration strings. The values are the name of the Group.
:ListButtons(Addon,Group) Returns the list of Buttons from the specified Group in a table. This only returns buttons specifically added to a group registered with the Buttons arg. The keys are unique registration strings. The values are the name of the Button.
At this time, I'll be researching if there's anything I've missed (Maybe a layer or two?). Comments on the system are welcome.
Also, the ButtonFacade addon is almost completely written. It currently lacks profile support (for FuBar positioning), and lacks any code for modules.
that way if btndata isn't passed it will default to the defaults as well as making it easier to remove buttons as you are storing the reference to the button and not the btndata.
At this time, I'll be researching if there's anything I've missed (Maybe a layer or two?). Comments on the system are welcome.
Seems like most of it's there. Though we're missing "Equipped" and possibly "Flash" (for things like auto-attack, etc), unless that's an existing layer?
Also, the ButtonFacade addon is almost completely written. It currently lacks profile support (for FuBar positioning), and lacks any code for modules.
As far as profiles go (when you get to that part), please, PLEASE use the default profile by default with the option to choose the other methods. Nothing is more frustrating than having to configure a mod for every character by default.
Edit: JJ: Can you PM me a list of all available attributes for each layer? Obviously some attributes won't be available for certain layers. I'll write up a "template" skin with complete details on usages, etc, and attach it.
that way if btndata isn't passed it will default to the defaults as well as making it easier to remove buttons as you are storing the reference to the button and not the btndata.
Good idea. Done.
Quote from StormFX »
Seems like most of it's there. Though we're missing "Equipped" and possibly "Flash" (for things like auto-attack, etc), unless that's an existing layer?
I need to check out all of the Blizzard button code to be sure. (Been busy playing... :D )
As far as profiles go (when you get to that part), please, PLEASE use the default profile by default with the option to choose the other methods. Nothing is more frustrating than having to configure a mod for every character by default.
Note that the profile will likely only control the FuBar placement, and the profiles chosen by modules. I'm likely to let the modules decide their own Profiles, if possible. This keeps control of what buttons are skinned and what skins are used completely out of the lib and the chooser, and puts it in the hands of the actionbar addon/module. That said, all modules to be included with ButtonFacade should use the default profile by... default.
Edit: JJ: Can you PM me a list of all available attributes for each layer? Obviously some attributes won't be available for certain layers. I'll write up a "template" skin with complete details on usages, etc, and attach it.
Seems like most of it's there. Though we're missing "Equipped" and possibly "Flash" (for things like auto-attack, etc), unless that's an existing layer?
Okay, went and took a look at the Blizzard code. Flash is now added in. It is an ARTWORK level texture, used by Blizzard to flash on and off when attacking.
One of the largest bits of confusion for me was what the Border layer (not the NormalTexture) was used for in Blizzard code. Turns out, it's the Equip layer, and it is an OVERLAY level texture, typically set to BlendMode of ADD, and colored green when a given item is equipped. It too is added in. The NormalTexture (The real border), is now renamed Normal.
I will be sending an updated PM to StormFX with the revised info.
Note that the profile will likely only control the FuBar placement, and the profiles chosen by modules. I'm likely to let the modules decide their own Profiles, if possible. This keeps control of what buttons are skinned and what skins are used completely out of the lib and the chooser, and puts it in the hands of the actionbar addon/module. That said, all modules to be included with ButtonFacade should use the default profile by... default.
Will the GUI at least include a method to globally change settings?
In the standard UI for action buttons, the normal texture is actually two textures: one for an empty slot, and one for a nonempty. I suggest an borderEmpty with a fallback to border.
Is there a safe way to hide the textures created by ButtonFacade? I cannot "hide" my buttons due to them being secure, but i dont want them visible when there is no action on them for example, so right now i just hide all the textures. Doing that i always ran into issues with cyC :(
Will the GUI at least include a method to globally change settings?
Yes. You will be able to set the skin settings for all skinned buttons, all skinned buttons in an Addon, all in an Addon/Group, and finally all registered to a specific Addon/Group/Button.
Quote from Tuller »
In the standard UI for action buttons, the normal texture is actually two textures: one for an empty slot, and one for a nonempty. I suggest an borderEmpty with a fallback to border.
Just researched this and you're correct. With any luck I'll be able to intercept when Blizzard changes this and do this. Though, due to my re-working of the layer names they'll be Normal and NormalEmpty.
Quote from Nevcairiel »
Is there a safe way to hide the textures created by ButtonFacade? I cannot "hide" my buttons due to them being secure, but i dont want them visible when there is no action on them for example, so right now i just hide all the textures. Doing that i always ran into issues with cyC :(
I could work on a method for this. You may instead want to use an unprotected Proxy Button frmae for graphics. The technique uses a graphic-less secure button, with a non-secure CheckButton with all of your graphics in it. See InfiniBar-2.0/IB_Button.lua for an example.
Just researched this and you're correct. With any luck I'll be able to intercept when Blizzard changes this and do this. Though, due to my re-working of the layer names they'll be Normal and NormalEmpty.
Actually decided to simply use the Normal Layer. The Texture attribute on this layer is used by default. The EmptyTexture attribute is used whenever the Normal Texture is set by Blizzard to the empty image, including when initially skinned. The example Normal Layer definition from the Blizzard skin is as follows:
The Proxy idea is nice, with one flaw, your button doesnt react on mous events like highlight or "Pushed" effect anymore, unless i missed something critical in my quick implementation here.
The Proxy idea is nice, with one flaw, your button doesnt react on mous events like highlight or "Pushed" effect anymore, unless i missed something critical in my quick implementation here.
You're right. A possible solution is to hook when the real button's Pushed, highligh, checked, etc. textures are shown and hidden, and replicate it on the graphic proxy. I haven't tried this, so I'm not certain it will work. Blizzard might be directly showing and hiding these textures.
While the cC skin format may seem daunting, it's actually quite efficient. We just need to format it better so that it's more readable to the human eye.
Additionally, we need a simple (global) variable to "check" prior to adding data to the skin table. One that's verified, we can call a predefined function that takes an array to add the new skin to the table. Though if you do it the way I think you'll do it, it'll be an "if not this = skin(new) return" type of deal, which makes my prior statement irrelevant. >.<
Finally, all "layers"/elements, etc. should have anchor points of CENTER/CENTER to the icon (to make alignment easier) then allow for size adjustments and offsets (for tweaking per element/skin).
Actually, no. Button Frames have four special textures, and CheckButton Frames have a fifth in addition. These textures are the NormalTexture, HighlightTexture, PushedTexture, DisabledTexture, and CheckedTexture. They are set using special code. When the button is pushed, the PushedTexture is used instead of the NormalTexture. This change is instant. Likewise, switching from Enabled to Disabled (and back) causes the change instantly. The HighlightTexture is shown anytime the mouse is in the button, without any additional code. It does not hide the Normal/Pushed/Disabled Textures (the "Border" Textures). The CheckedTexture is shown whenever the :SetChecked(1) function is called on the button. It, also, does not interfere with the "Border" textures.
All of this happens automatically, without any additional code, and is a side benefit of using the Button and CheckedButton Frame types. I am merely stating that these special textures will be used correctly in ButtonFacade, because it makes programming an action button that much easier. The skinning side of things, however, will be quite the same. Skinners will only need to know that the Border, Pushed, and Disabled layers are never shown at the same time, and should be designed to account for this fact.
That's about all I'm doing.
The lib:AddSkin(...) function will have an option to replace a pre-existing skin. If the option is true, it will silently replace it. If false, it will silently NOT replace it.
If you're suggesting that all layers be anchored from CENTER to CENTER no matter what, then I like the idea, and will implement it.
One thing though and this might be out of the scope for the addon but what about making this work for all sorts of icons, like in EBB, parrot etc? That'd be pretty hawt.
This is outside the scope of our goals. Skinning an Icon, which was never meant to be used as a button, is an entirely different concept from skinning a Button.
That's exactly what I'm suggesting >.<
Button skinning mods only work on buttons. If the icon or buff mod has created them by using button frames (Like buffalo is - I think), then it's feasible. Otherwise, it's not.
Yes, I thought that might be the case. Anyways, this seems awesome, will definantly be using it!
API for Skinners:
API for Actionbar Addons:
btndata takes the following form:
API for Skin Choosing:
At this time, I'll be researching if there's anything I've missed (Maybe a layer or two?). Comments on the system are welcome.
Also, the ButtonFacade addon is almost completely written. It currently lacks profile support (for FuBar positioning), and lacks any code for modules.
that way if btndata isn't passed it will default to the defaults as well as making it easier to remove buttons as you are storing the reference to the button and not the btndata.
Seems like most of it's there. Though we're missing "Equipped" and possibly "Flash" (for things like auto-attack, etc), unless that's an existing layer?
As far as profiles go (when you get to that part), please, PLEASE use the default profile by default with the option to choose the other methods. Nothing is more frustrating than having to configure a mod for every character by default.
Edit: JJ: Can you PM me a list of all available attributes for each layer? Obviously some attributes won't be available for certain layers. I'll write up a "template" skin with complete details on usages, etc, and attach it.
Can't wait to try it out. :D
Good idea. Done.
I need to check out all of the Blizzard button code to be sure. (Been busy playing... :D )
Note that the profile will likely only control the FuBar placement, and the profiles chosen by modules. I'm likely to let the modules decide their own Profiles, if possible. This keeps control of what buttons are skinned and what skins are used completely out of the lib and the chooser, and puts it in the hands of the actionbar addon/module. That said, all modules to be included with ButtonFacade should use the default profile by... default.
Will do.
Okay, went and took a look at the Blizzard code. Flash is now added in. It is an ARTWORK level texture, used by Blizzard to flash on and off when attacking.
One of the largest bits of confusion for me was what the Border layer (not the NormalTexture) was used for in Blizzard code. Turns out, it's the Equip layer, and it is an OVERLAY level texture, typically set to BlendMode of ADD, and colored green when a given item is equipped. It too is added in. The NormalTexture (The real border), is now renamed Normal.
I will be sending an updated PM to StormFX with the revised info.
Will the GUI at least include a method to globally change settings?
Yes. You will be able to set the skin settings for all skinned buttons, all skinned buttons in an Addon, all in an Addon/Group, and finally all registered to a specific Addon/Group/Button.
Just researched this and you're correct. With any luck I'll be able to intercept when Blizzard changes this and do this. Though, due to my re-working of the layer names they'll be Normal and NormalEmpty.
I could work on a method for this. You may instead want to use an unprotected Proxy Button frmae for graphics. The technique uses a graphic-less secure button, with a non-secure CheckButton with all of your graphics in it. See InfiniBar-2.0/IB_Button.lua for an example.
Actually decided to simply use the Normal Layer. The Texture attribute on this layer is used by default. The EmptyTexture attribute is used whenever the Normal Texture is set by Blizzard to the empty image, including when initially skinned. The example Normal Layer definition from the Blizzard skin is as follows:
You're right. A possible solution is to hook when the real button's Pushed, highligh, checked, etc. textures are shown and hidden, and replicate it on the graphic proxy. I haven't tried this, so I'm not certain it will work. Blizzard might be directly showing and hiding these textures.