dota2rpg panorama ui的可拖動(dòng)控件的實(shí)現(xiàn)

本文通過(guò)解析 dota_addons/ui_example里面的inventory_item控件來(lái)說(shuō)明如何在dota2rpg的UI中制作一個(gè)可拖動(dòng)的控件。

一众弓、可拖動(dòng)控件的注冊(cè)和回調(diào)的聲明

在dota2中蒲跨,任何的panel都可以變?yōu)榭赏蟿?dòng)的元素剩彬,需要在定義這個(gè)panel的時(shí)候,將這個(gè)panel的draggabletag設(shè)置為true句灌。即:

<Panel draggable="true" />

這個(gè)panel就可以變?yōu)榭赏蟿?dòng)的panel揍堕。

他們就可以通過(guò)$.RegisterEventHandler( 'DragEnter', panel, OnDragEnter );這類語(yǔ)句來(lái)綁定他們的拖動(dòng)回調(diào)函數(shù)料身。
這些的事件包括:

$.RegisterEventHandler( 'DragEnter', panel, OnDragEnter );
$.RegisterEventHandler( 'DragDrop', panel, OnDragDrop );
$.RegisterEventHandler( 'DragLeave', panel, OnDragLeave );
$.RegisterEventHandler( 'DragStart', panel, OnDragStart );
$.RegisterEventHandler( 'DragEnd', panel, OnDragEnd);

當(dāng)然,這也不代表你一定需要定義這么多東西衩茸,如果你只需要響應(yīng)DragStart和DragEnd芹血,那么根據(jù)你的實(shí)際需要去寫(xiě)即可。

二、拖動(dòng)回調(diào)函數(shù)

拖動(dòng)具體需要哪些函數(shù)需要根據(jù)制作的實(shí)際需要去寫(xiě)祟牲。在dota2的可拖動(dòng)的物品中隙畜,需要的函數(shù)包括:

OnDragStart:當(dāng)拖動(dòng)開(kāi)始的時(shí)候->需要隱藏物品的提示,創(chuàng)建拖動(dòng)的圖像说贝,然后給拖動(dòng)開(kāi)始的格子添加一個(gè)是從這里開(kāi)始拖動(dòng)的顯示效果议惰。
OnDragLeave:當(dāng)拖動(dòng)著panel的鼠標(biāo)移動(dòng)離開(kāi)panel的時(shí)候(這個(gè)離開(kāi)可能是初始格子也可以是中途某個(gè)經(jīng)過(guò)的格子)->取消這個(gè)格子的高亮狀態(tài)
DragEnter: 當(dāng)拖動(dòng)著的panel鼠標(biāo)移動(dòng)到panel上方的時(shí)候->高亮這個(gè)格子來(lái)表示你想要拖動(dòng)?xùn)|西到這個(gè)格子里;
OnDragDrop:當(dāng)拖動(dòng)著panel的鼠標(biāo)移動(dòng)到panel上方并松開(kāi)的時(shí)候->你想要交換拖動(dòng)的原始格子和目標(biāo)格子中的物品(目標(biāo)格子可能為空)乡恕;
OnDragEnd:當(dāng)拖動(dòng)著panel的鼠標(biāo)松開(kāi)的時(shí)候-> 無(wú)論是拖動(dòng)到另一個(gè)格子上還是拖動(dòng)到地上了言询,都會(huì)調(diào)用這個(gè)回調(diào),因此需要在OnDragDrop里面對(duì)拖動(dòng)到另一個(gè)格子里的事件做出響應(yīng)傲宜。

具體的回調(diào)函數(shù)如下:

function OnDragStart( panelId, dragCallbacks )
{
    // m_Item是在全局里保存的當(dāng)前物品的id运杭,如果不存在則不開(kāi)始拖動(dòng)
    if ( m_Item == -1 )
    {
        return true;
    }

    // 獲取物品名稱
    var itemName = Abilities.GetAbilityName( m_Item );

    // 隱藏正在顯示的物品提示
    ItemHideTooltip();

    // 創(chuàng)建用來(lái)拖動(dòng)的那個(gè)panel,也就是被拖動(dòng)的圖像函卒,他并不是原來(lái)顯示在那里的那個(gè)物品圖標(biāo)辆憔,而是新建的
    var displayPanel = $.CreatePanel( "DOTAItemImage", $.GetContextPanel(), "dragImage" );
    // 在創(chuàng)建的那個(gè)panel里面保存一些數(shù)據(jù),在其他的回調(diào)中可以用
    displayPanel.itemname = itemName; // 物品名稱
    displayPanel.contextEntityIndex = m_Item; // 物品序列號(hào)ID
    displayPanel.data().m_DragItem = m_Item; // 拖動(dòng)的物品ID报嵌,其實(shí)這個(gè)data()并不是必要的虱咧,甚至這一步指令也不是必要的
    displayPanel.data().m_DragCompleted = false; // 拖動(dòng)到底是拖動(dòng)到另一個(gè)格子還是拖動(dòng)到地上的標(biāo)志位

    // 將用來(lái)顯示的panel賦值給dragCallbacks.displayPanel就可以開(kāi)始跟隨鼠標(biāo)移動(dòng)了
    // 這兩個(gè)offset定義了這個(gè)panel到底要在粘上去的位置產(chǎn)生多少偏移
    // 因?yàn)閐isplayPanel的創(chuàng)建時(shí)在$.GetContextPanel,也就是inventory_item的xml里面創(chuàng)建的锚国,因此也就不需要偏移了
    dragCallbacks.displayPanel = displayPanel;
    dragCallbacks.offsetX = 0; 
    dragCallbacks.offsetY = 0; 
    
    // 這個(gè)class會(huì)隱藏當(dāng)前格子的物品圖標(biāo)腕巡,就給玩家感覺(jué)像是當(dāng)前的格子里的物品被拖走了
    // 其實(shí)他還在原來(lái)的位置,只不過(guò)被隱藏了
    // 被拖動(dòng)的是上面創(chuàng)建的那個(gè)displayPanel
    $.GetContextPanel().AddClass( "dragging_from" );
    return true;
}

function OnDragLeave( panelId, draggedPanel )
{
    // 獲取正在拖動(dòng)的物品的ID
    var draggedItem = draggedPanel.data().m_DragItem;
    // 如果正在拖動(dòng)的就是當(dāng)前的物品(也就是第一次離開(kāi)原始的格子血筑,那么不做響應(yīng))
    if ( draggedItem === null || draggedItem == m_Item )
        return false;

    // 如果是拖動(dòng)經(jīng)過(guò)了這個(gè)格子绘沉,因?yàn)镺nDragEnter添加了這個(gè)class
    // 用來(lái)指示這個(gè)是當(dāng)前的目標(biāo),離開(kāi)的時(shí)候需要移除這個(gè)class
    $.GetContextPanel().RemoveClass( "potential_drop_target" );
    return true;
}


function OnDragEnter( a, draggedPanel )
{
    // 獲取正在拖動(dòng)的物品ID
    var draggedItem = draggedPanel.data().m_DragItem;

    // 如果正在拖動(dòng)的就是當(dāng)前的物品(也就是第一次離開(kāi)原始的格子豺总,那么不做響應(yīng))
    if ( draggedItem === null || draggedItem == m_Item )
        return true;

    // 拖動(dòng)經(jīng)過(guò)這個(gè)格子了车伞,高亮他,用來(lái)指示玩家想要拖動(dòng)物品到這個(gè)格子
    $.GetContextPanel().AddClass( "potential_drop_target" );
    return true;
}

// 這個(gè)是關(guān)鍵的回調(diào)喻喳,因?yàn)檫@個(gè)回調(diào)里有發(fā)送給服務(wù)器的交換物品的API
function OnDragDrop( panelId, draggedPanel )
{
    // 獲取拖動(dòng)的物品ID
    var draggedItem = draggedPanel.data().m_DragItem;
    
    // 如果正在拖動(dòng)的就是當(dāng)前的物品(也就是第一次離開(kāi)原始的格子另玖,那么不做響應(yīng))
    // 只需要標(biāo)志一下m_DragCompleted給OnDragEnd使用一下,讓他不要
    // 丟物品到地上
    if ( draggedItem === null )
        return true;
    draggedPanel.data().m_DragCompleted = true;
    if ( draggedItem == m_Item ) // 拿起來(lái)又放到同一個(gè)格子里面
        return true; // 返回沸枯,不做交換物品的操作

    // 告知服務(wù)器玩家想要交換物品
    var moveItemOrder =
    {
        OrderType: dotaunitorder_t.DOTA_UNIT_ORDER_MOVE_ITEM,
        TargetIndex: m_ItemSlot,
        AbilityIndex: draggedItem
    };
    Game.PrepareUnitOrders( moveItemOrder );

    return true;
}

// 拖動(dòng)結(jié)束,這個(gè)里面有丟物品到地上的API
function OnDragEnd( panelId, draggedPanel )
{
    // 這個(gè)方法無(wú)論是拖動(dòng)到另一個(gè)格子里赂弓,還是拖動(dòng)到地上绑榴,都會(huì)響應(yīng)
    // 如果調(diào)用這個(gè)之前沒(méi)有先調(diào)用OnDragDrop的話,那么就告知
    // 服務(wù)器玩家想要丟東西到地上
    if ( !draggedPanel.data().m_DragCompleted )
    {
        Game.DropItemAtCursor( m_QueryUnit, m_Item );
    }

    // 移除被拖動(dòng)的面板
    draggedPanel.DeleteAsync( 0 );

    // 清除拖動(dòng)來(lái)源的格子盈魁,也就是調(diào)用這個(gè)的格子的dragging_from效果
    // UI里的交換物品圖標(biāo)翔怎,則會(huì)在服務(wù)器完成調(diào)換格子的操作之后
    // 通知客戶端更新
    $.GetContextPanel().RemoveClass( "dragging_from" );
    
    return true;
}

三、其他的拖動(dòng)需求分析

  1. 可拖動(dòng)的窗口,例如背包窗口等赤套,那么OnDragEnter飘痛、OnDragDrop和OnDragLeave是不需要的,應(yīng)該只需要OnDragStart和OnDragEnd,此外容握,由于沒(méi)有兄弟panel的問(wèn)題宣脉,因此displayPanel可以使用窗口本體,這樣你甚至連OnDragEnd都不需要寫(xiě)具體的內(nèi)容剔氏。
  2. 卡牌游戲的卡牌塑猖,卡牌游戲的卡牌,也只需要OnDragStart和OnDragEnd谈跛,此外羊苟,卡牌在拖動(dòng)過(guò)程中的響應(yīng),需要自己使用Schedule不斷更新感憾,比如更新卡牌的當(dāng)前狀態(tài)蜡励,指示當(dāng)前卡牌目標(biāo)位置等。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阻桅,一起剝皮案震驚了整個(gè)濱河市凉倚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鳍刷,老刑警劉巖占遥,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異输瓜,居然都是意外死亡瓦胎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)尤揣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)搔啊,“玉大人,你說(shuō)我怎么就攤上這事北戏「河螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵嗜愈,是天一觀的道長(zhǎng)旧蛾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蠕嫁,這世上最難降的妖魔是什么锨天? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮剃毒,結(jié)果婚禮上病袄,老公的妹妹穿的比我還像新娘搂赋。我一直安慰自己,他們只是感情好益缠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布脑奠。 她就那樣靜靜地躺著,像睡著了一般幅慌。 火紅的嫁衣襯著肌膚如雪宋欺。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天欠痴,我揣著相機(jī)與錄音迄靠,去河邊找鬼。 笑死喇辽,一個(gè)胖子當(dāng)著我的面吹牛掌挚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播菩咨,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吠式,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抽米?” 一聲冷哼從身側(cè)響起特占,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎云茸,沒(méi)想到半個(gè)月后是目,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡标捺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年懊纳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亡容。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗤疯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闺兢,到底是詐尸還是另有隱情茂缚,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布屋谭,位于F島的核電站脚囊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏桐磁。R本人自食惡果不足惜悔耘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望所意。 院中可真熱鬧淮逊,春花似錦、人聲如沸扶踊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)秧耗。三九已至备籽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間分井,已是汗流浹背车猬。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尺锚,地道東北人珠闰。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瘫辩,于是被迫代替她去往敵國(guó)和親伏嗜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,101評(píng)論 1 32
  • 本節(jié)介紹各種常見(jiàn)的瀏覽器事件伐厌。 鼠標(biāo)事件 鼠標(biāo)事件指與鼠標(biāo)相關(guān)的事件承绸,主要有以下一些。 click 事件挣轨,dblc...
    許先生__閱讀 2,437評(píng)論 0 4
  • Windows 常用消息大全 表A-1 Windows消息分布 消息范圍說(shuō) 明 0 ~ WM_USER – 1系統(tǒng)...
    北風(fēng)知我意閱讀 2,049評(píng)論 0 0
  • 【產(chǎn)品定位】:個(gè)性化定制和推薦的短視頻客戶端军熏。 【優(yōu)勢(shì)】 1、依托百度技術(shù)卷扮,提供更精確的內(nèi)容推薦荡澎。可以通用百度賬號(hào)...
    daidaiwang閱讀 2,458評(píng)論 0 1
  • 故事從秋天開(kāi)始 轉(zhuǎn)眼又是一個(gè)秋 是最初的倉(cāng)皇 是過(guò)程的迷惘 是點(diǎn)點(diǎn)滴滴 默然生長(zhǎng) 站在十字路口 我穿著舊時(shí)的衣裳 ...
    雪小凝閱讀 279評(píng)論 0 3