随笔 - 505  文章 - 1034  trackbacks - 0
<2007年9月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456


子曾经曰过:编程无他,唯手熟尔!

常用链接

留言簿(94)

随笔分类(649)

随笔档案(505)

相册

BCB

Crytek

  • crymod
  • Crytek's Offical Modding Portal

Game Industry

OGRE

other

Programmers

Qt

WOW Stuff

搜索

  •  

积分与排名

  • 积分 - 905232
  • 排名 - 14

最新随笔

最新评论

阅读排行榜

评论排行榜

http://blog.csdn.net/tcxxs/category/148474.aspx


1、这是我分析WOW原始UI代码后,对一些比较关键的部分,记录下来的
2、文章里面如果有什么纰漏,希望大家毫不客气的提出来,我一定查究!
3、关于基础问题可以参考
   WOW UI
《UI制作入门》http://www.pcgames.com.cn/netgames/zhuanti/wow/expert/Ui.htm
《WOW UI定制入门》http://202.113.13.169/site/mybbs/read.php?tid=33
《WOW插件制作指南》http://www.cnblogs.com/bluefee/archive/2005/04/14/137217.html
《ADDONS编写普及》http://wowbbs.game.mop.com/viewthread.php?tid=216755&extra=page%3D1
《动手写个属于自己的UI》http://wowbbs.game.mop.com/viewthread.php?tid=149814&fpage=1&highlight=
   XML
《XML初学进阶》http://www.chinausd.com/code/code.asp?id=173/5058
《XMLSpy 2005 Enterprise Edition》http://www.altova.com/download_spy_enterprise.html
   Lua
《Lua5.0参考手册中文版》http://www.cnblogs.com/bluefee/archive/2005/04/15/138576.html
《Lua 程序设计初步》http://bbs.battlecn.net/read.php?tid=541871&fpage=1
《通过例子学习Lua》http://www.wowtc.com/bbs/read.php?tid=4999&fpage=2
《Programming in LUA中文版》http://www.wowtc.com/bbs/read.php?tid=4998&fpage=2
《LuaEdit v2.5》http://luaforge.net/projects/luaedit/
4、关于如何提取MPQ文件,如何查看BLP图像,可以参考
《WoW Working Link》http://www.fukt.bth.se/%7Ek/wow/stuff/howto-extract-interface-files.txt
《Win MPQ》http://wow.duowan.com/2005-05-16/007R/26857843.html
《Win BLP Viewer》http://gamedown.yesky.com/game/108/108805.html
5、关于查询资料可以参考
《WoW Wiki》http://www.wowwiki.com/Interface_Customization/
《WOW APIs》http://www.cnblogs.com/bluefee/archive/2005/04/12/136270.html
《UI&Macro Forum》http://forums.worldofwarcraft.com/board.aspx?fn=wow-interface-customization
6、如果该问题是可以类推,或是从上下文能马上理解,或是从字面就知道含义的我就不罗嗦了
7、对于相同的问题我一般只分析一次,或是简要的提示一下,具体内容可以参考我以前的分析
8、如果你对自己查找资料的能力感到抱歉,可以E-mail向我询问,我会努力帮助你
9、联系方式E-mail: asdic.xxs@gmail.com    Blog: blog.csdn.net/tcxxs     QQ: 35548917
10、做人要厚道,转载请注明出处!


--------------------------------------------------


正式开始:
1、版本:1.7.1 (4659)
2、这次我写的是ActionbuttonTemplate.xml,ActionBarFrame.xml和ActionButton.lua
   他们是动作按钮的基础UI,也是大家比较关心的一部分,在Interface/FrameXML里面
3、这次分析用到的名词解释:
【模板】学过C++语言的人都知道虚函数,实际上是一个道理,只是作为子代继承的规范,不可创建实例
【栅格】一个用来放置图标的格子,默认为无图标时隐藏,当然你也可以显示它
【额外栅格】包括了战士姿态,德鲁依外形,盗贼潜行的栅格
【栅格ID】每个栅格都有对应的ID,是该栅格的唯一标示
【图标】每个技能和物品,包括交易技能,食物,宏等都有一个可以拖动的图标
【动作键】当把图标放置到栅格上时,这个整体就叫动作键
【额外动作键】当把图标放置到额外栅格上时,这个整体就叫额外动作键
【动作条】一般12个栅格组成一排或者一列,称这个为动作条
【额外动作条】由12个额外栅格组成一排或者一列,称这个为额外动作条
【动作条ID】在默认动作条中每个动作条都有页码,是这个动作条的唯一标示
  这里解释一下各个动作条的位置,主动作条包括1,2页
  然后右边1,右边2,右下,左下依次为3到6页,栅格ID排列如图
  61-72(左下)49-60(右下)37    25
        (右边2) I     I (右边1)
  1-12(主AB)13-24(2页)  48    36
  这里注意一个问题,为什么有的UI可以实现96个(FB,DUF等)或者更多呢
  这是因为额外栅格的存在,这些UI把空闲的额外栅格加以利用罢了
  调用这些额外栅格的动作键应该用其对应的函数
【闪动】当执行自动攻击或者自动射击技能时,改动作键就处于闪动状态
【CD】CoolDown的简写
【信息提示】即GameTooltip,当鼠标指向某个东西时显示的提示信息
【光环】包括buff,debuff,物品附加属性等
【arg1..N】arg为事件触发是传入的参数,可以为0到多个


--------------------------------------------

源代码及注释

-----------------------ActionButtonTemplate.xml


<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<CheckButton name="ActionButtonTemplate" virtual="true">
【动作键】【模板】
  <Size>
   <AbsDimension x="36" y="36"/>
  </Size>
  <Layers>
   <Layer level="BACKGROUND">
    <Texture name="$parentIcon"/>
    背景层放置【图标】
   </Layer>
   <Layer level="ARTWORK">
   层的从下到上为:BackGround,ArtWork,OverLay
    <Texture name="$parentFlash" file="Interface\Buttons\UI-QuickslotRed" hidden="true"/>
    【闪动】效果的纹理
    <FontString name="$parentHotKey" inherits="NumberFontNormalSmallGray" justifyH="RIGHT">
    该【动作键】的快捷键信息
     <Size>
      <AbsDimension x="32" y="10"/>
     </Size>
     <Anchors>
      <Anchor point="TOPLEFT">
       <Offset>
        <AbsDimension x="2" y="-2"/>
       </Offset>
      </Anchor>
     </Anchors>
    </FontString>
    <FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
    该【动作键】数量信息
     <Anchors>
     注意,这里没有Size标签,所以它为自动大小
      <Anchor point="BOTTOMRIGHT">
       <Offset>
        <AbsDimension x="-2" y="2"/>
       </Offset>
      </Anchor>
     </Anchors>
    </FontString>
   </Layer>
   <Layer level="OVERLAY">
    <FontString name="$parentName" inherits="GameFontHighlightSmallOutline">
    该【动作键】名字,例如:宏的名字
     <Size>
      <AbsDimension x="36" y="10"/>
     </Size>
     <Anchors>
      <Anchor point="BOTTOM">
       <Offset>
        <AbsDimension x="0" y="2"/>
       </Offset>
      </Anchor>
     </Anchors>
    </FontString>
   </Layer>
  </Layers>
  <Frames>
   <Model name="$parentCooldown" inherits="CooldownFrameTemplate"/>
   直接应用【CD】模板,没有测试过,还望高人赐教,或者等我以后试
  </Frames>
  <NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2">
  【图标】边框纹理,如果该【栅格】已放置【图标】,则显示这个纹理
  若没有放置,则显示UI-Quickslot,它比UI-Quickslot2稍微小点
   <Size>
    <AbsDimension x="64" y="64"/>
   </Size>
   <Anchors>
    <Anchor point="CENTER">
     <Offset>
      <AbsDimension x="0" y="-1"/>
      立体效果,而且UI-Quickslot的显示位置也依赖UI-Quickslot2
      但是【图标】的实际放置位置却并不依赖这个位置,由BackGround层决定
     </Offset>
    </Anchor>
   </Anchors>
  </NormalTexture>
  <PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
  点击【动作键】时的纹理
  <HighlightTexture alphaMode="ADD" file="Interface\Buttons\ButtonHilight-Square"/>
  鼠标经过【栅格】时的纹理
  <CheckedTexture alphaMode="ADD" file="Interface\Buttons\CheckButtonHilight"/>
  等待施法时【栅格】的纹理,例如:你点击加血法术到选择目标那段时间显示
</CheckButton>
</Ui>


------------------------ActionBarFrame.xml


<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="ActionButton.lua"/>
<CheckButton name="ActionBarButtonTemplate" inherits="ActionButtonTemplate" virtual="true">
  <Scripts>
   <OnLoad>
    ActionButton_OnLoad();
   </OnLoad>
   <OnEvent>
    ActionButton_OnEvent(event);
   </OnEvent>
   <OnClick>
    if ( IsShiftKeyDown() ) then
    安住shift再点【动作键】,即拖拉【图标】
     PickupAction(ActionButton_GetPagedID(this));
     鼠标吸附该【图标】
    else
    否则执行该【动作键】命令
     MacroFrame_EditMacro();
     UseAction(ActionButton_GetPagedID(this), 1);
     UseAction(slot [,checkCursor] [,onSelf])函数
     slot参数为该【动作键】ID号
     checkCursor参数为是否在其他事件中返回是鼠标点击,0或者1
     onSelf参数为是否对自己施法,0或者1
    end
    ActionButton_UpdateState();
    点击后应该更新【动作键】状态
   </OnClick>
   <OnDragStart>
    if ( LOCK_ACTIONBAR ~= "1" ) then
    如果【动作键】并未设定为锁定
     PickupAction(ActionButton_GetPagedID(this));
     ActionButton_UpdateState();
    end
   </OnDragStart>
   <OnReceiveDrag>
    if ( LOCK_ACTIONBAR ~= "1" ) then
     PlaceAction(ActionButton_GetPagedID(this));
     PlaceAction,放下鼠标上吸附的【动作键】
     注意,这里并不要求一定要放在栅格上,因为你可以摧毁一个【动作键】
     ActionButton_UpdateState();
    end
   </OnReceiveDrag>
   <OnEnter>
    ActionButton_SetTooltip();
    经过【动作键】时,显示【信息提示】
   </OnEnter>
   <OnLeave>
    this.updateTooltip = nil;
    GameTooltip:Hide();
   </OnLeave>
   <OnUpdate>
    ActionButton_OnUpdate(arg1);
    更新【闪动】效果
   </OnUpdate>
  </Scripts>
</CheckButton>
下面定义了主【动作条】
<CheckButton name="ActionButton1" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="1">
MainMenuBarArtFrame,即默认最下面的一条工具栏,包括了主【动作条】,人物工具条,背包
但是注意,并不包括两旁的2只鹰的纹理
  <Anchors>
   <Anchor point="BOTTOMLEFT">
    <Offset>
     <AbsDimension x="8" y="4"/>
     左下和右下的【动作条】都依据主【动作条】的位置
     【信息提示】和【额外栅格】并不依据这个偏移,但是它会根据左下和右下【动作条】的出现而更改高度
     若仅改变该偏移,则如果该人物有【额外栅格】,则人物的主【动作条】将会在原位又出现一个
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton2" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="2">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton1" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton3" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="3">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton2" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton4" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="4">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton3" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton5" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="5">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton4" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton6" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="6">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton5" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton7" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="7">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton6" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton8" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="8">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton7" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton9" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="9">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton8" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton10" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="10">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton9" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton11" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="11">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton10" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<CheckButton name="ActionButton12" inherits="ActionBarButtonTemplate" parent="MainMenuBarArtFrame" id="12">
  <Anchors>
   <Anchor point="LEFT" relativeTo="ActionButton11" relativePoint="RIGHT">
    <Offset>
     <AbsDimension x="6" y="0"/>
    </Offset>
   </Anchor>
  </Anchors>
</CheckButton>
<Button name="ActionBarUpButton" parent="MainMenuBarArtFrame">
主【动作条】位置上的上翻页按钮
  <Size>
   <AbsDimension x="32" y="32"/>
  </Size>
  <Anchors>
   <Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT">
    <Offset>
     <AbsDimension x="522" y="-22"/>
    </Offset>
   </Anchor>
  </Anchors>
  <HitRectInsets>
   <AbsInset left="6" right="6" top="7" bottom="7"/>
   这个一直没有测试成功,还望高人指点迷津
  </HitRectInsets>
  <Scripts>
   <OnLoad>
    MainMenuBarPageNumber:SetText(CURRENT_ACTIONBAR_PAGE);
    CURRENT_ACTIONBAR_PAGE,当前【动作条ID】
    当你显示了其他【动作条】如:左下【动作条】,那么它将不会在翻页中重复出现
    this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
    当主【动作条】的页码改变时触发
   </OnLoad>
   <OnEvent>
    if ( event == "ACTIONBAR_PAGE_CHANGED" ) then
     MainMenuBarPageNumber:SetText(CURRENT_ACTIONBAR_PAGE);
    end
   </OnEvent>
   <OnClick>
    ActionBar_PageUp();
    PlaySound("UChatScrollButton");
    PlaySound(SoundName),播放一个WOW内置的声音
    SoundName为内置参数的名字,可以参考下面地址
    http://www.wowwiki.com/API_PlaySound
    注意,你不要试图在MPQ文件中找到这个名字
   </OnClick>
  </Scripts>
  <NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Up"/>
  <PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Down"/>
  <DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollUpButton-Disabled"/>
  被锁定时的纹理,未测试成功,望高人指点一二
  <HighlightTexture alphaMode="ADD" file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Highlight"/>
</Button>
<Button name="ActionBarDownButton" parent="MainMenuBarArtFrame">
  <Size>
   <AbsDimension x="32" y="32"/>
  </Size>
  <Anchors>
   <Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT">
    <Offset>
     <AbsDimension x="522" y="-42"/>
    </Offset>
   </Anchor>
  </Anchors>
  <HitRectInsets>
   <AbsInset left="6" right="6" top="7" bottom="7"/>
  </HitRectInsets>
  <Scripts>
  上翻中已经注册并处理了事件,这里不重复
   <OnClick>
    ActionBar_PageDown();
    PlaySound("UChatScrollButton");
   </OnClick>
  </Scripts>
  <NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Up"/>
  <PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Down"/>
  <DisabledTexture file="Interface\Buttons\UI-ScrollBar-ScrollDownButton-Disabled"/>
  <HighlightTexture alphaMode="ADD" file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Highlight"/>
</Button>
</Ui>


------------------------ActionButton.lua

CURRENT_ACTIONBAR_PAGE = 1;
当前【动作条ID】
NUM_ACTIONBAR_PAGES = 6;
【动作条ID】总数
NUM_ACTIONBAR_BUTTONS = 12;
每个【动作条】的【动作键】数
ATTACK_BUTTON_FLASH_TIME = 0.4;
【闪动】效果时间间隔,为0.4S

BOTTOMLEFT_ACTIONBAR_PAGE = 6;
初始左下【动作条ID】
BOTTOMRIGHT_ACTIONBAR_PAGE = 5;
初始右下【动作条ID】
LEFT_ACTIONBAR_PAGE = 4;
初始右边2【动作条ID】
RIGHT_ACTIONBAR_PAGE = 3;
初始右边1【动作条ID】

-- Table of actionbar pages and whether they're viewable or not
VIEWABLE_ACTION_BAR_PAGES = {1, 1, 1, 1, 1, 1};
初始化为每页【动作条】都能够显示,0为隐藏

function ActionButtonDown(id)
实现按下【动作键】
if ( BonusActionBarFrame:IsVisible() ) then
如果是【额外动作键】
  local button = getglobal("BonusActionButton"..id);
  if ( button:GetButtonState() == "NORMAL" ) then
  若未按下
   button:SetButtonState("PUSHED");
  end
  return;
  该函数用if-else是同样的
end

local button = getglobal("ActionButton"..id);
if ( button:GetButtonState() == "NORMAL" ) then
  button:SetButtonState("PUSHED");
end
end

由上下2个函数可以看出,暴雪对【动作键】和【额外动作键】同样对待
这个也是其他UI可以利用【额外栅格】的基础

function ActionButtonUp(id, onSelf)
if ( BonusActionBarFrame:IsVisible() ) then
  local button = getglobal("BonusActionButton"..id);
  if ( button:GetButtonState() == "PUSHED" ) then
   button:SetButtonState("NORMAL");
   -- Used to save a macro
   MacroFrame_EditMacro();
   UseAction(ActionButton_GetPagedID(button), 0);
   if ( IsCurrentAction(ActionButton_GetPagedID(button)) ) then
   IsCurrentAction,等待施法,并不是正在吟唱
    button:SetChecked(1);
    设定该【动作键】正处于等待状态
   else
    button:SetChecked(0);
   end
  end
  return;
end

local button = getglobal("ActionButton"..id);
if ( button:GetButtonState() == "PUSHED" ) then
  button:SetButtonState("NORMAL");
  -- Used to save a macro
  MacroFrame_EditMacro();
  UseAction(ActionButton_GetPagedID(button), 0, onSelf);
  if ( IsCurrentAction(ActionButton_GetPagedID(button)) ) then
   button:SetChecked(1);
  else
   button:SetChecked(0);
  end
end
end

function ActionBar_PageUp()
CURRENT_ACTIONBAR_PAGE = CURRENT_ACTIONBAR_PAGE + 1;
local nextPage;
for i=CURRENT_ACTIONBAR_PAGE, NUM_ACTIONBAR_PAGES do
  if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
  如果该页能显示
   nextPage = i;
   break;
  end
end

if ( not nextPage ) then
如果没有找到能够显示的下一页
  CURRENT_ACTIONBAR_PAGE = 1;
else
  CURRENT_ACTIONBAR_PAGE = nextPage;
end
ChangeActionBarPage();
这个函数变换将当主【动作条】变换到CURRENT_ACTIONBAR_PAGE指向的【动作条】
end

function ActionBar_PageDown()
CURRENT_ACTIONBAR_PAGE = CURRENT_ACTIONBAR_PAGE - 1;
local prevPage;
for i=CURRENT_ACTIONBAR_PAGE, 1, -1 do
  if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
   prevPage = i;
   break;
  end
end

if ( not prevPage ) then
  for i=NUM_ACTIONBAR_PAGES, 1, -1 do
  把“1”换成“CURRENT_ACTIONBAR_PAGE+1”也是可以的
  把这个for循环对比ActionBar_PageUp的同一地方
  可见,暴雪员工相当的肯定在上翻的时候第1页是可以显示的
  而在下翻的时候显得信心不足,还重复检查了一次NUM_ACTIONBAR_PAGES到CURRENT_ACTIONBAR_PAGE
  这是因为左下、右下AB的出现只是修改5,6页的可见性,并不影响1页的可见性
  所以在下翻的时候需要对1到6页均做可见性检查
  但是,重复检查的区间的确是多余的,估计是暴雪员工偷懒
  因为“1”比“CURRENT_ACTIONBAR_PAGE+1”要好写得多
   if ( VIEWABLE_ACTION_BAR_PAGES[i] ) then
    prevPage = i;
    break;
   end
  end
end
CURRENT_ACTIONBAR_PAGE = prevPage;
ChangeActionBarPage();
end

function ActionButton_OnLoad()
this.showgrid = 0;
显示空【栅格】的标志
this.flashing = 0;
处于【闪动】的标志
this.flashtime = 0;
【闪动】时间间隔计算的中间量
ActionButton_Update();
this:RegisterForDrag("LeftButton", "RightButton");
对this所指向的窗体注册鼠标拖拉行为,参数至少一个,也可以注册多个
参数为LeftButton,RightButton,表示使用某个鼠标键执行
this:RegisterForClicks("LeftButtonUp", "RightButtonUp");
对this所指向的窗体注册鼠标点击行为,参数至少一个,也可以注册多个
参数为LeftButtonDown,LeftButtonUp,RightButtonDown,RightButtonUp
注意,在OnClick标签中传入的arg1参数只返回LeftButton或者RightButton
this:RegisterEvent("PLAYER_ENTERING_WORLD");
this:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
当【额外栅格】更新时触发
this:RegisterEvent("ACTIONBAR_SHOWGRID");
当拖拉【图标】时触发,arg1为LeftButton或者RightButton
this:RegisterEvent("ACTIONBAR_HIDEGRID");
当停止拖拉【图标】时触发
this:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
this:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
当【栅格】内容变更时触发,arg1为变更【栅格ID】
this:RegisterEvent("ACTIONBAR_UPDATE_STATE");
当【栅格】状态更新时触发,包括了【CD】和可用性鉴定
但是不包括自动攻击和自动射击事件
arg1为鼠标LeftButton,RightButton,也可能为nil
this:RegisterEvent("ACTIONBAR_UPDATE_USABLE");
当更新【图标】可用性后触发
this:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
当更新【CD】后触发
当【CD】开始的时候,arg1返回使用的鼠标按钮LeftButton或者RightButton
当【CD】结束的时候,arg1返回nil
this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
当变更装备时或者经过一定时间后触发
this:RegisterEvent("PLAYER_AURAS_CHANGED");
当玩家【光环】改变时触发,包括了【光环】的消失和出现
注意,属性完全相同【光环】重复释放并不能触发该事件
this:RegisterEvent("PLAYER_TARGET_CHANGED");
当玩家的目标变更时触发,包括取消和选定目标
arg1为该目标持续时间,单位分钟,小数保留3位
this:RegisterEvent("UNIT_AURASTATE");
当某单位短时间【光环】改变时触发,需进一步测试
this:RegisterEvent("UNIT_INVENTORY_CHANGED");
当玩家装备变更时或者当观察玩家装备并发生装备变更时触发
this:RegisterEvent("CRAFT_SHOW");
this:RegisterEvent("CRAFT_CLOSE");
工艺窗口的显示与关闭,arg1为鼠标点击键
this:RegisterEvent("TRADE_SKILL_SHOW");
this:RegisterEvent("TRADE_SKILL_CLOSE");
交易技能制作物品窗口的显示与关闭,arg1为鼠标点击键
this:RegisterEvent("UNIT_HEALTH");
当任何一个单位的血量发生变化时触发,arg1参数为该单位ID
player,pet,target,mouseover,party1..4,partypet1..4,raid1..40,raidpet1..40,npc
注意,该事件拥有很高的优先级,特别当参数为player时
this:RegisterEvent("UNIT_MANA");
当任何一个单位的魔法量发生变化时触发,arg1参数为该单位ID
this:RegisterEvent("UNIT_RAGE");
当任何一个单位的怒气值发生变化时触发,arg1参数为该单位ID
this:RegisterEvent("UNIT_FOCUS");
当任何一个单位的焦距值发生变化时触发,arg1参数为该单位ID
注意,该事件实际上已经废除,因为现在猎人使用MANA,而不是FOCUS
this:RegisterEvent("UNIT_ENERGY");
当任何一个单位的能量发生变化时触发,arg1参数为该单位ID
this:RegisterEvent("PLAYER_ENTER_COMBAT");
当玩家进入自动攻击状态时触发,自动射击不包括在内
注意,仅当你使用自动攻击时触发该事件
使用其他任何技能或者攻击行为都不可触发
this:RegisterEvent("PLAYER_LEAVE_COMBAT");
离开自动攻击状态或者死亡时触发
this:RegisterEvent("PLAYER_COMBO_POINTS");
当连击点变更时触发,arg1总返回player,而并不时连击点数
this:RegisterEvent("UPDATE_BINDINGS");
当快捷键更改时触发
this:RegisterEvent("START_AUTOREPEAT_SPELL");
当自动射击开始时触发,而不是自动攻击
this:RegisterEvent("STOP_AUTOREPEAT_SPELL");
离开自动射击状态或者死亡时触发
ActionButton_UpdateHotkeys();
end

function ActionButton_UpdateHotkeys(actionButtonType)
if ( not actionButtonType ) then
  actionButtonType = "ACTIONBUTTON";
end
local hotkey = getglobal(this:GetName().."HotKey");
该对象在模板中为Fontstring
local action = actionButtonType..this:GetID();
actionButtonType,为该类命令的名字
this:GetID,得到该命令在该类中的ID号
注意,这2个字符串组成了最终的命令的名字
如NUMPAD2,NUMPAD为类型,2为ID
但是有些类型就一个命令无ID,如LEFT
hotkey:SetText(KeyBindingFrame_GetLocalizedName(GetBindingKey(action), "KEY_"));
GetBindingKey得到命令的快捷键名字,后面加上KEY_是为了显示命令的字串
例如:KEY_NUMPAD2就显示为“数字键盘2”
KeyBindingFrame_GetLocalizedName,由这个函数在快捷键窗口中显示该命令的快捷键
end

function ActionButton_Update()
-- Special case code for bonus bar buttons
-- Prevents the button from updating if the bonusbar is still in an animation transition
if ( this.isBonus and this.inTransition ) then
  ActionButton_UpdateUsable();
  ActionButton_UpdateCooldown();
  return;
end

local icon = getglobal(this:GetName().."Icon");
local buttonCooldown = getglobal(this:GetName().."Cooldown");
local texture = GetActionTexture(ActionButton_GetPagedID(this));
if ( texture ) then
  icon:SetTexture(texture);
  icon:Show();
  如果该【栅格】有【图标】,即若为【动作键】则显示
  this.rangeTimer = TOOLTIP_UPDATE_TIME;
  每隔TOOLTIP_UPDATE_TIME事件间隔更新一次距离信息
  TOOLTIP_UPDATE_TIME为0.2S
  this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2");
  -- Save texture if the button is a bonus button, will be needed later
  if ( this.isBonus ) then
  判断自己是否为【额外栅格】
   this.texture = texture;
  end
else
  icon:Hide();
  buttonCooldown:Hide();
  this.rangeTimer = nil;
  this:SetNormalTexture("Interface\\Buttons\\UI-Quickslot");
  getglobal(this:GetName().."HotKey"):SetVertexColor(0.6, 0.6, 0.6);
end
ActionButton_UpdateCount();
if ( HasAction(ActionButton_GetPagedID(this)) ) then
判断该【栅格】是否有【图标】,即是否为【动作键】
  this:Show();
  ActionButton_UpdateState();
  ActionButton_UpdateUsable();
  ActionButton_UpdateCooldown();
  ActionButton_UpdateFlash();
elseif ( this.showgrid == 0 ) then
  this:Hide();
else
这里表示,当该【栅格】没有【图标】
但是显示空【栅格】选项开启时,不显示公共CD效果
  buttonCooldown:Hide();
end
if ( GameTooltip:IsOwned(this) ) then
判断该【动作键】是否拥有【信息提示】
  ActionButton_SetTooltip();
else
  this.updateTooltip = nil;
end

-- Update Macro Text
local macroName = getglobal(this:GetName().."Name");
macroName:SetText(GetActionText(ActionButton_GetPagedID(this)));
GetActionText返回宏的名字
end

function ActionButton_ShowGrid(button)
if ( not button ) then
  button = this;
end
button.showgrid = button.showgrid+1;
getglobal(button:GetName().."NormalTexture"):SetVertexColor(1.0, 1.0, 1.0, 0.5);
SetVertexColor(R,G,B)这个函数需要注意,可能学过3D的都知道,这个是顶点着色,取值0到1小数
顶点着色并不是直接设置RGB的数值,而是在原有的RGB数值上乘以顶点着色指定的RGB百分比修正值
例如:一个色块RGB为50,100,30,如果你写入SetVertexColor(0.5,0,1),结果RGB为25,0,30
button:Show();
end

function ActionButton_HideGrid(button)
if ( not button ) then
  button = this;
end
button.showgrid = button.showgrid-1;
if ( button.showgrid == 0 and not HasAction(ActionButton_GetPagedID(button)) ) then
把这里判断showgrid变量为0和这一对函数对showgrid的操作联系起来看
就像是用堆栈实现括号配对一样保证了显示和隐藏的规范
  button:Hide();
end
end

function ActionButton_UpdateState()
if ( IsCurrentAction(ActionButton_GetPagedID(this)) or IsAutoRepeatAction(ActionButton_GetPagedID(this)) ) then
IsAutoRepeatAction,自动射击
IsAttackAction,自动攻击
  this:SetChecked(1);
else
  this:SetChecked(0);
end
end

function ActionButton_UpdateUsable()
注意,这个函数的主体是个技能按钮模板,所以针对的是一个【动作键】
所以,当你拖动某个【图标】时,其他【图标】并不会跟着更新
local icon = getglobal(this:GetName().."Icon");
模板中定义
local normalTexture = getglobal(this:GetName().."NormalTexture");
local isUsable, notEnoughMana = IsUsableAction(ActionButton_GetPagedID(this));
得到当前技能栅格的ID,这个是所有栅格ID号,包括73~96的
if ( isUsable ) then
是否在射程,当前在其他游戏规则中是否可用,是否在CD等
  icon:SetVertexColor(1.0, 1.0, 1.0);

  normalTexture:SetVertexColor(1.0, 1.0, 1.0);
elseif ( notEnoughMana ) then
是否足够魔法、怒气、能量
  icon:SetVertexColor(0.5, 0.5, 1.0);
  normalTexture:SetVertexColor(0.5, 0.5, 1.0);
else
  icon:SetVertexColor(0.4, 0.4, 0.4);
  这个是灰色效果,当你拖拉【图标】时,原【栅格】则为这个效果
  normalTexture:SetVertexColor(1.0, 1.0, 1.0);
end
end

function ActionButton_UpdateCount()
local text = getglobal(this:GetName().."Count");
在模板中数量为Fontstring
if ( IsConsumableAction(ActionButton_GetPagedID(this)) ) then
判断是否改【栅格】的物品为消费品
  text:SetText(GetActionCount(ActionButton_GetPagedID(this)));
else
  text:SetText("");
end
end

function ActionButton_UpdateCooldown()
local cooldown = getglobal(this:GetName().."Cooldown");
在模板中该【CD】定义为一个Model
local start, duration, enable = GetActionCooldown(ActionButton_GetPagedID(this));
CooldownFrame_SetTimer(cooldown, start, duration, enable);
end

function ActionButton_OnEvent(event)
if ( event == "ACTIONBAR_SLOT_CHANGED" ) then
  if ( arg1 == -1 or arg1 == ActionButton_GetPagedID(this) ) then
  如果变更的【栅格】不明或者变更的【栅格】为自己则更新
   ActionButton_Update();
  end
  return;
end
if ( event == "PLAYER_ENTERING_WORLD" or event == "ACTIONBAR_PAGE_CHANGED" ) then
总结起来是,当游戏环境有大的变化时,更新自己
  ActionButton_Update();
  return;
end
if ( event == "UPDATE_BONUS_ACTIONBAR" ) then
  if ( this.isBonus ) then
   ActionButton_Update();
  end
  return;
end
if ( event == "ACTIONBAR_SHOWGRID" ) then
  ActionButton_ShowGrid();
  return;
end
if ( event == "ACTIONBAR_HIDEGRID" ) then
  ActionButton_HideGrid();
  return;
end
if ( event == "UPDATE_BINDINGS" ) then
  ActionButton_UpdateHotkeys();
  return;
end

-- All event handlers below this line MUST only be valid when the button is visible
if ( not this:IsVisible() ) then
如果该【图标】不可见,那么直接返回,即下面的所有事件均要求该【图标】可见,即应该为一个【动作键】
  return;
end

if ( event == "UNIT_HEALTH" or event == "UNIT_MANA" or event == "UNIT_RAGE" or event == "UNIT_FOCUS" or event == "UNIT_ENERGY" ) then
  if ( arg1 == "player" ) then
  如果发生在玩家身上,应该判断所有技能的可用性
   ActionButton_UpdateUsable();
  end
elseif ( event == "PLAYER_TARGET_CHANGED" or event == "PLAYER_AURAS_CHANGED" ) then
  ActionButton_UpdateUsable();
elseif ( event == "UNIT_AURASTATE" ) then
  if ( arg1 == "player" or arg1 == "target" ) then
   ActionButton_UpdateUsable();
  end
elseif ( event == "UNIT_INVENTORY_CHANGED" ) then
  if ( arg1 == "player" ) then
   ActionButton_Update();
  end
elseif ( event == "ACTIONBAR_UPDATE_STATE" ) then
  ActionButton_UpdateState();
elseif ( event == "ACTIONBAR_UPDATE_USABLE" or event == "UPDATE_INVENTORY_ALERTS" or event == "ACTIONBAR_UPDATE_COOLDOWN" ) then
  ActionButton_UpdateUsable();
  ActionButton_UpdateCooldown();
elseif ( event == "CRAFT_SHOW" or event == "CRAFT_CLOSE" or event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_CLOSE" ) then
  ActionButton_UpdateState();
elseif ( event == "PLAYER_ENTER_COMBAT" ) then
  if ( IsAttackAction(ActionButton_GetPagedID(this)) ) then
   ActionButton_StartFlash();
  end
elseif ( event == "PLAYER_LEAVE_COMBAT" ) then
  if ( IsAttackAction(ActionButton_GetPagedID(this)) ) then
   ActionButton_StopFlash();
  end
elseif ( event == "PLAYER_COMBO_POINTS" ) then
  ActionButton_UpdateUsable();
elseif ( event == "START_AUTOREPEAT_SPELL" ) then
  if ( IsAutoRepeatAction(ActionButton_GetPagedID(this)) ) then
   ActionButton_StartFlash();
  end
elseif ( event == "STOP_AUTOREPEAT_SPELL" ) then
  if ( ActionButton_IsFlashing() and not IsAttackAction(ActionButton_GetPagedID(this)) ) then
  如果该技能在【闪动】,并且不是自动攻击
   ActionButton_StopFlash();
  end
end
end

function ActionButton_SetTooltip()
if ( GetCVar("UberTooltips") == "1" ) then
Uber,乳房。。。。。
这句应该是判断是否属于一般类型,母类型
UberTooltips详细信息提示
  GameTooltip_SetDefaultAnchor(GameTooltip, this);
  一般位于屏幕右下角,会根据【动作条】的多少自动改变位置
else
如果这个【栅格】的【信息提示】不属于默认的形式则
  if ( this:GetParent() == MultiBarBottomRight or this:GetParent() == MultiBarRight or this:GetParent() == MultiBarLeft ) then
  【动作条】MultiBarBottomRight右下,MultiBarRight右方,MultiBarLeft左边下
   GameTooltip:SetOwner(this, "ANCHOR_LEFT");
   这里解释下SetOwner函数,GameTooltip:SetOwner(owner, anchor);
   其中owner是参照物,anchor是对齐方式,取值如下:
   ANCHOR_TOPRIGHT 相当于 SetPoint("BOTTOMRIGHT",object,"TOPRIGHT")
   ANCHOR_RIGHT 相当于 SetPoint("BOTTOMLEFT",object,"TOPRIGHT")
   ANCHOR_BOTTOMRIGHT 相当于 SetPoint("TOPLEFT",object,"BOTTOMRIGHT")
   ANCHOR_TOPLEFT 相当于 SetPoint("BOTTOMLEFT",object,"TOPLEFT")
   ANCHOR_LEFT 相当于 SetPoint("BOTTOMRIGHT",object,"TOPLEFT")
   ANCHOR_BOTTOMLEFT 相当于 SetPoint("TOPRIGHT",object,"BOTTOMLEFT")
  else
   GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
  end
end

if ( GameTooltip:SetAction(ActionButton_GetPagedID(this)) ) then
SetAction,返回值为该【信息提示】是否需要实时更新
  this.updateTooltip = TOOLTIP_UPDATE_TIME;
else
  this.updateTooltip = nil;
end
end

function ActionButton_OnUpdate(elapsed)
if ( ActionButton_IsFlashing() ) then
  this.flashtime = this.flashtime - elapsed;
  if ( this.flashtime <= 0 ) then
  flashtime初始为0,即第一次flash的时间并不为0.4,而是第一个elapsed决定
   local overtime = -this.flashtime;
   overtime,该函数的一个中间量,用语变化符号
   if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
   这个if为了下面给flashtime更新是不出现负数考虑
   注意,ERROR文本框的文本并不和这里的时间挂钩
    overtime = 0;
   end
   this.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime;
   更新flashtime,使得从第二次开始间隔一个ATTACK_BUTTON_FLASH_TIME

   local flashTexture = getglobal(this:GetName().."Flash");
   if ( flashTexture:IsVisible() ) then
   效果的实现即为反复显示这个flash纹理
    flashTexture:Hide();
   else
    flashTexture:Show();
   end
  end
end

-- Handle range indicator
if ( this.rangeTimer ) then
  if ( this.rangeTimer < 0 ) then
  
   local count = getglobal(this:GetName().."HotKey");
   if ( IsActionInRange( ActionButton_GetPagedID(this)) == 0 ) then
   IsActionInRange,返回指定【动作键】是否在距离之内
   返回nil表示该【栅格】无【图标】,或者没有选定目标
   返回0表示不在距离之内,返回1表示在距离之内
   注意,如果你没有试图释放这个【动作键】在目标身上,它可能总返回1
    count:SetVertexColor(1.0, 0.1, 0.1);
   else
    count:SetVertexColor(0.6, 0.6, 0.6);
   end
   this.rangeTimer = TOOLTIP_UPDATE_TIME;
  else
   this.rangeTimer = this.rangeTimer - elapsed;
  end
end

if ( not this.updateTooltip ) then
  return;
end

this.updateTooltip = this.updateTooltip - elapsed;
if ( this.updateTooltip > 0 ) then
  return;
end

if ( GameTooltip:IsOwned(this) ) then
  ActionButton_SetTooltip();
else
  this.updateTooltip = nil;
end
end

function ActionButton_GetPagedID(button)
if( button == nil ) then
  message("nil button passed into ActionButton_GetPagedID(), contact Jeff");
  严重错误需要弹出消息框
  return 0;
end
if ( button.isBonus and CURRENT_ACTIONBAR_PAGE == 1 ) then
如果是【额外动作条】并且当前【动作条ID】为1
  local offset = GetBonusBarOffset();
  GetBonusBarOffset,得到【额外动作条】的偏移量
  返回1到3,分别对应1到3号战士姿态,或者德鲁依外形,或者是盗贼状态
  if ( offset == 0 and BonusActionBarFrame and BonusActionBarFrame.lastBonusBar ) then
  应该是判断当意外失去【额外动作条】定位时,定位于最近一次改变的
  注意,如果该职业无【额外动作条】时,偏移量也为0
   offset = BonusActionBarFrame.lastBonusBar;
  end
  return (button:GetID() + ((NUM_ACTIONBAR_PAGES + offset - 1) * NUM_ACTIONBAR_BUTTONS));
  注意NUM_ACTIONBAR_PAGES + offset用的是加法,所以我们肯定暴雪偷偷藏了24个【额外栅格】
elseif ( button:GetParent():GetName() == "MultiBarBottomLeft" ) then
  return (button:GetID() + ((BOTTOMLEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarBottomRight" ) then
  return (button:GetID() + ((BOTTOMRIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarLeft" ) then
  return (button:GetID() + ((LEFT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
elseif ( button:GetParent():GetName() == "MultiBarRight" ) then
  return (button:GetID() + ((RIGHT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS));
else
  return (button:GetID() + ((CURRENT_ACTIONBAR_PAGE - 1) * NUM_ACTIONBAR_BUTTONS))
end
end

function ActionButton_UpdateFlash()
local pagedID = ActionButton_GetPagedID(this);
if ( (IsAttackAction(pagedID) and IsCurrentAction(pagedID)) or IsAutoRepeatAction(pagedID) ) then
  ActionButton_StartFlash();
else
  ActionButton_StopFlash();
end
end

function ActionButton_StartFlash()
this.flashing = 1;
this.flashtime = 0;
ActionButton_UpdateState();
end

function ActionButton_StopFlash()
this.flashing = 0;
getglobal(this:GetName().."Flash"):Hide();
ActionButton_UpdateState();
end

function ActionButton_IsFlashing()
if ( this.flashing == 1 ) then
  return 1;
else
  return nil;
end
end


---------------------总结一下


常量
TOOLTIP_UPDATE_TIME         【信息提示】更新间隔
CURRENT_ACTIONBAR_PAGE        当前【动作条ID】
NUM_ACTIONBAR_PAGES         总页码
NUM_ACTIONBAR_BUTTONS        一个【动作条】的【栅格】数
ATTACK_BUTTON_FLASH_TIME       【闪动】间隔
BOTTOMLEFT_ACTIONBAR_PAGE       左下【动作条ID】
BOTTOMRIGHT_ACTIONBAR_PAGE       右下【动作条ID】
LEFT_ACTIONBAR_PAGE         右边2【动作条ID】
RIGHT_ACTIONBAR_PAGE        右边1【动作条ID】

事件
ACTIONBAR_PAGE_CHANGED        【动作条】翻页
UPDATE_BONUS_ACTIONBAR        【额外动作条】更新
ACTIONBAR_SHOWGRID         显示【栅格】
ACTIONBAR_HIDEGRID         隐藏【栅格】
ACTIONBAR_SLOT_CHANGED        【栅格】内容变更
ACTIONBAR_UPDATE_STATE        【动作键】更新状态
ACTIONBAR_UPDATE_USABLE        【动作键】更新可用性
ACTIONBAR_UPDATE_COOLDOWN       【动作键】更新【CD】
UPDATE_INVENTORY_ALERTS        装备警告
PLAYER_AURAS_CHANGED        【光环】改变
PLAYER_TARGET_CHANGED        目标改变
UNIT_AURASTATE          单位【光环】改变
UNIT_INVENTORY_CHANGED        单位装备改变
CRAFT_SHOW           工艺窗口显示
CRAFT_CLOSE           工艺窗口隐藏
TRADE_SKILL_SHOW         交易技能窗口显示
TRADE_SKILL_CLOSE         交易技能窗口隐藏
UNIT_HEALTH           单位血量改变(优先级极高)
UNIT_MANA           单位魔法改变
UNIT_RAGE           单位怒气改变
UNIT_FOCUS           单位焦距改变(已废除)
UNIT_ENERGY           单位能量改变
PLAYER_ENTER_COMBAT         开始自动攻击
PLAYER_LEAVE_COMBAT         结束自动攻击
PLAYER_COMBO_POINTS         连击点改变
UPDATE_BINDINGS          快捷键更新
START_AUTOREPEAT_SPELL        开始自动射击
STOP_AUTOREPEAT_SPELL        结束自动射击

函数
IsShiftKeyDown          Shift键是否按下
PickupAction          吸附【图标】
PlaceAction           放置【图标】
UseAction           使用【动作键】
GetButtonState          得到【动作键】状态
SetButtonState          设置【动作键】状态
Frame:RegisterForDrag        注册拖拉行为
Frame:RegisterForClicks        注册点击行为
GetBindingKey          得到快捷键
HasAction           【栅格】是否放置了【图标】
Frame:SetVertexColor        顶点色彩修正
IsAutoRepeatAction         是否正在自动射击
IsAttackAction          是否正在自动攻击
IsUsableAction          【动作键】是否可用
IsConsumableAction         是否为消费品
GetActionCooldown         得到【CD】
GetCVar            有待测试
GameTooltip:SetAction        设置【信息提示】
Frame:IsVisible          是否可见
IsActionInRange          是否在距离之内
GetBonusBarOffset         得到【额外动作条】偏移量



累死了。。。。。。明天再贴图片和排版彩色

http://wowbbs.game.mop.com/forumdisplay.php?fid=138

这个帖子我已经贴了图片
posted on 2007-06-25 02:11 七星重剑 阅读(3330) 评论(2)  编辑 收藏 引用 所属分类: 乱七八糟

FeedBack:
# re: [转]WOW原始UI代码分析【ActionButton】 2008-11-20 17:09 小不点
XML 怎么到游戏中的界面的?难道是用FLASH,不是Texture嘛?请高手请教,谢谢~~
mail:amyvmiwei@126.com  回复  更多评论
  
# re: [转]WOW原始UI代码分析【ActionButton】 2008-11-21 14:16 七星重剑
@小不点
xml是界面的配置文件,c++代码根据配置来生成界面,看下cegui就知道了  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理