在《魔兽世界》中使用界面选项插件时出现代码问题

发布于 2024-08-20 19:23:12 字数 4507 浏览 13 评论 0原文

我正在为预先存在的插件编写用户界面。或者,更具体地说,添加配置选项并尝试利用 Interface Options Addons (IOA) 面板。我一直在参考 wowwiki,特别是 讨论使用该面板的页面,但更一般的是一堆页数。

我遇到了一个问题,我确信这只是我编写插件经验不足的结果(我写了一些,但每次都是一次学习经历)。基本概念是:

  • 创建主面板 - 使用 XML 为主
  • 面板上应可见的内容创建子项目(即全局选项) - 使用 XML
  • 为每个子项目(配置类别)创建子面板 - 使用Lua(子面板的数量和名称是动态的)
  • 为每个子面板创建子项 - 使用 Lua

有效的方法是:

  • 主面板显示在 IOA 面板中
  • 子面板显示在 IOA 面板中,作为主面板的子项目
  • 我放在子面板上的纹理显示在它们上面

我遇到的问题是:

  • 如果我将子面板创建为主面板的子项,它们会显示在子面板的顶部主面板
  • 如果我创建的子面板是 UIParent 的子面板,它们会显示在主屏幕上(当 IOA 窗口未打开时可见)
  • 我在 XML 文件中创建的任何内容都不会作为主面板的子框架显示在到目前为止

,我的代码(为了简洁而被剪掉)位于消息的底部。我知道代码部分有很多内容,但我希望尽可能清楚。关于我在做什么。

请注意,我确实在魔兽争霸 UI 官方论坛上发布了有关此问题的文章,但无法在那里获得任何帮助。

embeds.xml

...snip...
<Frame name="MyAddonFrame" parent="UIParent" hidden="false">
  <Scripts>
    <OnLoad>
      self:RegisterEvent("UNIT_TARGET");
      self:RegisterEvent("PLAYER_ENTERING_WORLD");
      MyAddon_OnLoad(self);
    </OnLoad>
    <OnEvent function="MyAddon_OnEvent" />
    </Scripts>

    <Frames>
      <Frame parent="MyAddonFrame" inherits="UIDropDownMenuTemplate">
        <Frames>
          <Button name="MyAddon_MacroSelectDropdownButton">
            <Anchors>
              <Anchor point="CENTER"/>
            </Anchors>

            <Scripts>
              <OnLoad>
                UIDropDownMenu_Initialize(this,
                MyAddon_MacroSelectDropdown_OnLoad);
              </OnLoad>
              <OnClick>
                MyAddon_MacroSelectDropdownButton_OnClick();
              </OnClick>
            </Scripts>
          </Button>
          <MessageFrame>
            <Anchors>
              <Anchor point="CENTER"/>
            </Anchors>
          <FontString text="Message Frame"/>
        </MessageFrame>
      </Frames>
    </Frame>
  </Frames>
</Frame>
...snip...

Lua代码

...snip...
function MyAddon_OnLoad(panel)
    MyAddon_CreateOptionsPanel(panel);
    MyAddon_ConsoleMessage("Loaded MyAddon: " .. tostring(panel));
end

function MyAddon_CreateOptionsPanel(panel)
    panel.name = "MyAddon " .. GetAddOnMetadata("MyAddon", "Version");  -- Set the name for the Category for the Panel
    panel.okay = function (self) MyAddonFrame_Close(); end;                 -- When the player clicks okay, run this function.
    panel.cancel = function (self)  MyAddonFrame_CancelOrLoad();  end;  -- When the player clicks cancel, run this function.
    InterfaceOptions_AddCategory(panel);                                    -- Add the panel to the Interface Options

    for name,text in pairs(ConfigData) do
        MyAddon_CreateMacroPanel(name, panel, panel.name);
    end
end

function MyAddon_CreateMacroPanel(macroName, parent, parentName)
    MyAddon_ConsoleMessage("Added macro option pane: " .. macroName);
    panel = CreateFrame( "Frame", "MyAddon_MacroPanel_" .. macroName, parent);
    panel.name = macroName;
    panel.parent = parentName;
    InterfaceOptions_AddCategory(panel);

    -- create a backdrop so we can see that the panel is created
    panel:SetFrameStrata("BACKGROUND");
    panel:SetWidth(128); -- Set these to whatever height/width is needed 
    panel:SetHeight(64); -- for your Texture

    local t = panel:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Factions.blp");
    t:SetAllPoints(panel);
    panel.texture = t;

    panel:SetPoint("CENTER",0,0);
end



-- MyAddon_MacroSelectDropdown
function MyAddon_MacroSelectDropdown_OnLoad()
    info            = {};
    info.text       = "Auto";
    info.value      = "Auto";
    -- FunctionCalledWhenOptionIsClicked 
    info.func       = function (self) MyAddon_SetMacroAuto(); end;
    UIDropDownMenu_AddButton(info);
    for index,macro in pairs(ConfigData) do
        info.text       = name;
        info.value      = name;
        -- FunctionCalledWhenOptionIsClicked 
        info.func       = function (self) MyAddon_SetMacroByName(name); end;
        UIDropDownMenu_AddButton(info);
    end
    -- can also be done as function() FunctionCalledWhenOptionIsClicked() end;
end
...snip...

I am writing a UI to a pre-existing addon. Or, more specifically, adding configuration options and trying to take advantage of the Interface Options Addons (IOA) panel. I've been referencing wowwiki, specifically the page that talks about using that panel, but more generally a bunch of pages.

I'm running into a problem that I'm sure is just a result of my inexperience writing addons (I've written a few, but it's a learning experience every time). The basic concept is:

  • Create the main panel - using XML
  • Create sub-items for things that should be visible on the main panel (is, global options) - using XML
  • Create a sub-panel for each child item (configuration category) - using Lua (the number and names of the sub-panels is dynamic)
  • Create sub-items for each sub-panel - using Lua

The things that work are:

  • The main panel shows up in the IOA panel
  • The sub panels show up in the IOA panel, as sub-items of the main panel
  • The textures I put on the sub panels show up on them

The problems I'm having are:

  • If I create the sub-panels as children of the main panel, they show up on top of the main panel
  • If I create the sub-panels are children of the UIParent, they show up on the main screen (visible when the IOA window isn't open
  • Nothing I create in the XML file as a child Frame of the main panel shows up on it

The code I have so far (clipped for brevity) is at the bottom of the message. Any help/suggestions would be more than appreciated. I know there's a lot in the code section, but I wanted to be as clear as I could about what I was doing.

Note that I did post about this on the official Warcraft UI forum, but was unable to get any help there.

embeds.xml

...snip...
<Frame name="MyAddonFrame" parent="UIParent" hidden="false">
  <Scripts>
    <OnLoad>
      self:RegisterEvent("UNIT_TARGET");
      self:RegisterEvent("PLAYER_ENTERING_WORLD");
      MyAddon_OnLoad(self);
    </OnLoad>
    <OnEvent function="MyAddon_OnEvent" />
    </Scripts>

    <Frames>
      <Frame parent="MyAddonFrame" inherits="UIDropDownMenuTemplate">
        <Frames>
          <Button name="MyAddon_MacroSelectDropdownButton">
            <Anchors>
              <Anchor point="CENTER"/>
            </Anchors>

            <Scripts>
              <OnLoad>
                UIDropDownMenu_Initialize(this,
                MyAddon_MacroSelectDropdown_OnLoad);
              </OnLoad>
              <OnClick>
                MyAddon_MacroSelectDropdownButton_OnClick();
              </OnClick>
            </Scripts>
          </Button>
          <MessageFrame>
            <Anchors>
              <Anchor point="CENTER"/>
            </Anchors>
          <FontString text="Message Frame"/>
        </MessageFrame>
      </Frames>
    </Frame>
  </Frames>
</Frame>
...snip...

Lua Code

...snip...
function MyAddon_OnLoad(panel)
    MyAddon_CreateOptionsPanel(panel);
    MyAddon_ConsoleMessage("Loaded MyAddon: " .. tostring(panel));
end

function MyAddon_CreateOptionsPanel(panel)
    panel.name = "MyAddon " .. GetAddOnMetadata("MyAddon", "Version");  -- Set the name for the Category for the Panel
    panel.okay = function (self) MyAddonFrame_Close(); end;                 -- When the player clicks okay, run this function.
    panel.cancel = function (self)  MyAddonFrame_CancelOrLoad();  end;  -- When the player clicks cancel, run this function.
    InterfaceOptions_AddCategory(panel);                                    -- Add the panel to the Interface Options

    for name,text in pairs(ConfigData) do
        MyAddon_CreateMacroPanel(name, panel, panel.name);
    end
end

function MyAddon_CreateMacroPanel(macroName, parent, parentName)
    MyAddon_ConsoleMessage("Added macro option pane: " .. macroName);
    panel = CreateFrame( "Frame", "MyAddon_MacroPanel_" .. macroName, parent);
    panel.name = macroName;
    panel.parent = parentName;
    InterfaceOptions_AddCategory(panel);

    -- create a backdrop so we can see that the panel is created
    panel:SetFrameStrata("BACKGROUND");
    panel:SetWidth(128); -- Set these to whatever height/width is needed 
    panel:SetHeight(64); -- for your Texture

    local t = panel:CreateTexture(nil,"BACKGROUND");
    t:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Factions.blp");
    t:SetAllPoints(panel);
    panel.texture = t;

    panel:SetPoint("CENTER",0,0);
end



-- MyAddon_MacroSelectDropdown
function MyAddon_MacroSelectDropdown_OnLoad()
    info            = {};
    info.text       = "Auto";
    info.value      = "Auto";
    -- FunctionCalledWhenOptionIsClicked 
    info.func       = function (self) MyAddon_SetMacroAuto(); end;
    UIDropDownMenu_AddButton(info);
    for index,macro in pairs(ConfigData) do
        info.text       = name;
        info.value      = name;
        -- FunctionCalledWhenOptionIsClicked 
        info.func       = function (self) MyAddon_SetMacroByName(name); end;
        UIDropDownMenu_AddButton(info);
    end
    -- can also be done as function() FunctionCalledWhenOptionIsClicked() end;
end
...snip...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

水波映月 2024-08-27 19:23:12

是的,默认情况下,子框架会绘制在其父框架之上。这是一个基本租户。

我认为这里的脱节部分在于您需要将所有元素添加为主框架的子元素。事实并非如此。

对于两个独立的“面板”,即框架,您可以拥有:

<frame>...</frame>
<frame>...</frame>

如果第一个是您的“主框架”,或者您打算接收插件主要事件的那个,如 ADDON_LOADED,第二个可以是其他东西,但它仍然你的。好吧,实际上两者都不是“你的”,它们位于所有插件共享的全局共享范围内。

因此,如果您想要跟随特定框架的可见元素,无论是位置还是可见性,它们都应该是其子元素。否则你应该创建另一个框架。如果您隐藏父级,那么它的子级也会被隐藏。如果您移动父级,则其子级也会移动,因为它们与父级具有相对位置。

这些是默认行为,但除非您确实需要做一些棘手的事情,例如真正变形的框架,否则遵循默认行为并创建单独的框架要容易得多。


<Frame name="MyAddonFrame" parent="UIParent" hidden="false">
  <Scripts>
    <OnLoad>
      self:RegisterEvent("UNIT_TARGET");
      self:RegisterEvent("PLAYER_ENTERING_WORLD");
      MyAddon_OnLoad(self);
    </OnLoad>
    <OnEvent function="MyAddon_OnEvent" />
    </Scripts>

    <Frames>
      <Frame parent="MyAddonFrame" inherits="UIDropDownMenuTemplate">

您不需要像上面那样设置父级,但是如果您打算直接在该框架中的事件外部从 lua 代码引用该框架,则应该给它一个名称:

    <Frames>
      <Frame name="$parentDropDownMenu" inherits="UIDropDownMenuTemplate">

如果这是在“embeds.xml”中,从技术上讲该文件旨在包含一组嵌入在插件中的库,而不是用于管理框架,但当然,WoW 不知道它会起作用。代码应该更像是 MyAddon.xml、MyAddon.lua 大多数情况下


,您需要制作大小合适的框架并将它们注册为显示为选项面板的一部分,这是对其的简单解释。

让我知道还剩下什么没有意义或不起作用。

Yes, frames that are childeren are drawn on top of their parents by default. This is a fundemental tenant.

I think the disconnect here is partly in the assumtion that you are needing to add all elements as children of your main frame. This isnt so.

For two independant "panels", i.e. Frames, you can have:

<frame>...</frame>
<frame>...</frame>

If the first is your "main frame", or the one that you intend to recive your addons main events, like ADDON_LOADED, the second can be someting else, but its still yours. Well both really arn't "yours" actually, they are in a global shared scope shared by all addons.

So if you want visible elements that follow a particular frame, both in position and visibility they should be its children. Else you should create another frame. If you make a parent hidden then its children will be hidden. If you move a parent, its children move, via the fact they have relative positions to the parent.

These are the default behaviours, but unless you really need to do something tricky, like a frame that truely morphs, its much easier to follow the default behaviour and create seperate frames.


<Frame name="MyAddonFrame" parent="UIParent" hidden="false">
  <Scripts>
    <OnLoad>
      self:RegisterEvent("UNIT_TARGET");
      self:RegisterEvent("PLAYER_ENTERING_WORLD");
      MyAddon_OnLoad(self);
    </OnLoad>
    <OnEvent function="MyAddon_OnEvent" />
    </Scripts>

    <Frames>
      <Frame parent="MyAddonFrame" inherits="UIDropDownMenuTemplate">

You dont need to set the parents as you did above, but if you intend to reference that frame from lua code outside of an event directly in that frame, you should give it a name:

    <Frames>
      <Frame name="$parentDropDownMenu" inherits="UIDropDownMenuTemplate">

If this is in "embeds.xml", techincally that file is meant for a set of includes for libs that are embedded in the addon, and not for managing frames, but of course WoW has no idea so it would work. The code should be in someting more like MyAddon.xml, MyAddon.lua


Mostly you need to make frames that are the right size and register them to show as part of the options panel, which is sort of the nutshell explanation of it.

Let me know whats left that doesnt make sense or work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文