Jump to content
Alloder.pro: about Allods with love
Search In
  • More options...
Find results that contain...
Find results in...

New program for writers

We turn from quantity to quality and tell you how we will supplement the Allods Team program with rewards in rubles.

More

The new Updater

Let us to introduce the new addon updater software and to share the details

Read more

Alloder 2.0

We have started the process of project evolve, and this relates not only, and not even primarily of the site's view

Read more

MoveExample - Перетаскивание панели


Guest WShad
 Share

Recommended Posts

В данном примере я демонстрирую как реализовать простое перетаскивание панели виджета по рабочему пространству. Прошу обратить внимание на опцию align в разделе расположения панели (файл MainPanel.(WidgetPanel).xdb), данный код рассчитан на то, что она проставлена в WIDGET_ALIGN_LOW (то есть координаты ориентированы от левого верхнего угла). Если ориентацию ставить в другое значение, то правильное расположение нужно вычислять вручную.

Link to comment
Share on other sites

Пожалуйста. Этот код, мне кажется, нужен и большинству стандартных игровых окон/панелей. Странно, что он там не реализован, если для этого все подготовлено.

Да, кстати, можно поставить WIDGET_ALIGN_LOW_ABS - это немного меняет координацию перемещения. В зависимости от размера панели это может быть значительно или не заметно вообще.

Link to comment
Share on other sites

само окошко перетаскивается на ура, но вот проблема, если перетаскивать что угодно, например скилл с панельки или из книги, то вышеупомянутое окно движется вместе с выбранным объектом

не порядок

проблема возникает из-за того, что на событие EVENT_DND_DRAG_TO окошко(wtMainPanel) откликается вместе с любым объектом

Link to comment
Share on other sites

Молодец! Соображаешь! )

Я привел всего лишь простейший пример, а по хорошему надо проверять какое окно начали тащить(чего я в своем аддоне не сделал). Идентификатор передается в пикаттемпт.

Спасибо FINTERу за найденный баг. Исправил у себя в аддоне. Можете посмотреть. Только просьба идентификатор 700 не использовать, а то мой аддон будет вместе с вашим бегать. )

Бронирую себе диапазон идентификаторов 700-720. Думаю никто не против? )

Link to comment
Share on other sites

Из темы Исправляйте косяк с перемещением панелей!

Quote:
Есть ещё одна особенность перемещения фреймов, у меня разрешение окна игры нестандартноене 4x3, а 3x4, и особенно заметно на аддонах DarkDPSMeter и DmgMeMetre как фрейм тянется не за указателем мыши, а как бы ближе к верхнему левому углу окна.

Для исправления этого эффекта можно попробовать использовать WIDGET_ALIGN_LOW_ABS, должно помочь. Я об этом уже писал.

Link to comment
Share on other sites

Да, тут еще немаловажный фактор всплыл... про ID

просто то что должно быть у каждого(Скрытие по ALT+Z и перетаскивание панелей):

Code:
Global( "Drag", false )

Code:
function GetDNDId( container, item )

return container * DND_CONTAINER_STEP + item

end

function GetDNDItem( id )

return math.mod( id, DND_CONTAINER_STEP )

end

function OnToggleUI( params )

панель:Show( params.visible )

if params.visible then

mission.DNDRegister( панель, GetDNDId( DND_WIDGET_MOVE, ваш_id ), false )

end

end

function OnEventDNDPickAttempt( params )

if GetDNDItem(params.srcId) == ваш_id then

Drag = true

end

end

function OnEventDNDDropAttempt( params )

mission.DNDConfirmDropAttempt()

Drag = false

end

function OnEventDNDDragTo( params )

if Drag == true then

local place = панель:GetPlacementPlain()

place.posX = params.posX

place.posY = params.posY

панель:SetPlacementPlain( place )

end

end

Code:
function Init()

common.RegisterEventHandler( OnEventDNDPickAttempt, "EVENT_DND_PICK_ATTEMPT" )

common.RegisterEventHandler( OnEventDNDDragTo, "EVENT_DND_DRAG_TO" )

common.RegisterEventHandler( OnEventDNDDropAttempt, "EVENT_DND_DROP_ATTEMPT" )

common.RegisterEventHandler( OnToggleUI, "SCRIPT_TOGGLE_UI")

mission.DNDRegister( панелька , GetDNDId( DND_WIDGET_MOVE, ваш_id ), false )

end

Так вот, во избежании недоразумений и привязки элементов к нужным панелям, сейчас напишу какие панели имеют ID =)

ВАШ ID=14+ [id_панельки]

ID[чата] = 14007

ID[панелей(где спеллы)] = (1..6)2000..2005 (7..=)2006..2011 (ALT(7..9))2018..2023 CTRL(1..=)2024..2035

ID[chatbarao] = 14666

ID[honorinfo] = 14700

пока перетаскиваемых больше не нашел вещей...

Link to comment
Share on other sites

Дополню:

DND_EQUIPMENT = 0

DND_INVENTORY = 1

DND_ACTIONBAR = 2

DND_SPELLBOOK = 3

DND_VENDOR = 4

DND_DEPOSITE = 5

DND_WORLD = 6

DND_ALCHEMY = 7

DND_ARMOR_CRAFT = 8

DND_CHARACTER_CONTROL3D = 9

DND_MAIL = 10

DND_AUCTION = 11

DND_LOOTBAG = 12

DND_PLAYER_TRADE = 13

DND_WIDGET_MOVE = 14

DND_WIDGET_RESIZE = 15

Так что 2*** - это не ID спеллов! Это ID элементов панелей быстрого доступа!

P.S.: Приятно видеть что моим кодом активно пользуются. )

Link to comment
Share on other sites

есть такой баг

в оконном режиме мыша убегает в крайний правый угол - а панель тока до середины

скорее всего там берется за базу DC.Width вместо Window.Width

Link to comment
Share on other sites

В полноэкранном режиме, на широкоформатном экране (16:10), аналогично, но наоборот :)

Если двигать форму из крайнего левого края экрана вправо, то когда курсор проходит ~ 2/3 экрана по оси X, а форма уже у САМОГО правого края экрана. Если двигать дальше вправо, то форма улетает ЗА ПРЕДЕЛЫ экрана. Если её не вернуть, а там "отпустить", то она там и останется, out of radio coverage :)

Такой код как бы предпологает, что либо экран всегда 4:3, либо ширина экрана всегда 1280. Попробую ка я разобраться, что тут можно сделать.

Link to comment
Share on other sites

Разобрался.

Важное дополнение к скрипту перетаскивания окна

Нужно срочно исправить во всех аддонах одну функцию:

Code:
function OnEventDNDDragTo( params )

if Drag == true then

local screen = widgetsSystem:GetPosConverterParams()

local place = панель:GetPlacementPlain()

place.posX = params.posX * screen.fullVirtualSizeX / screen.realSizeX

place.posY = params.posY * screen.fullVirtualSizeY / screen.realSizeY

панель:SetPlacementPlain( place )

end

end

Оказывается, в игре есть 2 системы координат экрана! Это всё объясняет, и сильно упрощает нам жизнь. widgetsSystem:GetPosConverterParams() возвращает структуру, в которой они описаны:

referenceVirtualSizeX: number( float ) - базовый виртуальный размер окна по X

referenceVirtualSizeY: number( float ) - базовый виртуальный размер окна по X

realSizeX: number( float ) - реальный размер окна по X

realSizeY: number( float ) - реальный размер окна по Y

fullVirtualSizeX: number( float ) - текущий виртуальный размер окна по X

fullVirtualSizeY: number( float ) - текущий виртуальный размер окна по Y

На самом деле, всё очень просто. В игре, например, при разрешении экрана 1920x1200, они будут иметь такие значения:

referenceVirtualSizeX = 1280

referenceVirtualSizeY = 1024

realSizeX = 1920

realSizeY = 1200

fullVirtualSizeX = 1638.4001464844

fullVirtualSizeY = 1024

Здесь, referenceVirtualSizeX и referenceVirtualSizeY - константы, по ним вычисляется "виртуальная" резолюция окна, таким образом, что fullVirtualSizeY тоже константа, всегда равна 1024, а fullVirtualSizeX рассчитывается относительно fullVirtualSizeY, но с учётом пропорций экрана (будь то 4:3, 5:4, 16:9, 16:10, или даже НЕполноэкранное окно ЛЮБЫХ пропорций). Это очень важно! Именно этой виртуальной (fullVirtualSize) системой координат пользуются все оригинальные ниваловские виджеты! Поэтому, этой же системой должны пользоваться и мы, если мы хотим, чтобы расположение аддонов всегда совпадало с расположением встроенных виджетов. Т.е. чтобы наши аддоны рисовались ВСЕГДА там где нужно, и не вылетали за границы экрана при перетаскивании.

При этом есть ещё одно ВАЖНОЕ условие:

НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ WIDGET_ALIGN_LOW_ABS !!!

Многие раньше рекомендовали именно этот параметр, для того, чтобы при перетаскивании, виджет не "улетал" от курсора мыши. Так вот. WIDGET_ALIGN_LOW_ABS, на самом деле, указывает, что координаты виджета в XDB указаны РЕАЛЬНЫЕ ("_ABS" = АБСолютные) координаты, а этого делать просто никогда нельзя! Никогда не используйте реальные координаты, т.к. они у всех людей разные, на разных резолюциях мониторов. А "глюк" с перетаскиванием нужно чинить НЕ этим параметром, а исправленной функцией, которую я привёл выше. В ней, координаты виджета рассчитываются так: КоординатаУказателяМыши * screen.fullVirtualSizeX / screen.realSizeX.

Чуть позже напишу гораздо гораздо подробнее о XDB файлах. Отдельной темой.

Link to comment
Share on other sites

Да, я исправил =) В документации написано, что класс называется "WidgetsSystemSafe", но:

API wrote:
WidgetsSystemSafe доступна в каждом аддоне через переменную widgetsSystem.
Link to comment
Share on other sites

Да, можно :)

Вот, кстати, как раз для библиотеки, вылизанные до почти идеального состояния функции. Что новенького:

  • Панель теперь НЕ отрывается от курсора мыши.
  • Панель теперь цепляется к мышке тем местом, где ухватили(а НЕ левым-верхним углом)

Код стал гораздо проще в обращении, никакой возни с event'ами и Global'ами!

Этот код работает в аддоне "TargetOfTarget", можете посмотреть его в деле. А вот и сам код:

Code:
-- Drag&Drop by SLA, version 2010-08-28.

function DNDInit( wtReacting, wtMovable, ID )

Global( "DragNDrop", {} )

DragNDrop.ID = ID

DragNDrop.wtReacting = wtReacting

DragNDrop.wtMovable = wtMovable

DragNDrop.IsPicked = false

common.RegisterEventHandler( OnEventDNDPickAttempt, "EVENT_DND_PICK_ATTEMPT" )

common.RegisterEventHandler( OnEventDNDDragTo, "EVENT_DND_DRAG_TO" )

common.RegisterEventHandler( OnEventDNDDropAttempt, "EVENT_DND_DROP_ATTEMPT" )

end

function DNDReg()

mission.DNDRegister( DragNDrop.wtReacting , DND_WIDGET_MOVE * DND_CONTAINER_STEP + DragNDrop.ID, true )

end

function DNDUnreg()

OnEventDNDDropAttempt()

mission.DNDUnregister( DragNDrop.wtReacting )

end

function OnEventDNDPickAttempt( params )

if math.mod( params.srcId, DND_CONTAINER_STEP ) == DragNDrop.ID then

DragNDrop.Screen = widgetsSystem:GetPosConverterParams()

DragNDrop.Place = DragNDrop.wtMovable:GetPlacementPlain()

DragNDrop.DeltaX = math.ceil( params.posX * DragNDrop.Screen.fullVirtualSizeX / DragNDrop.Screen.realSizeX - DragNDrop.Place.posX )

DragNDrop.DeltaY = math.ceil( params.posY * DragNDrop.Screen.fullVirtualSizeY / DragNDrop.Screen.realSizeY - DragNDrop.Place.posY )

common.SetCursor( "drag" )

DragNDrop.IsPicked = true

end

end

function OnEventDNDDragTo( params )

if DragNDrop.IsPicked then

DragNDrop.Place.posX = math.ceil( params.posX * DragNDrop.Screen.fullVirtualSizeX / DragNDrop.Screen.realSizeX - DragNDrop.DeltaX )

DragNDrop.Place.posY = math.ceil( params.posY * DragNDrop.Screen.fullVirtualSizeY / DragNDrop.Screen.realSizeY - DragNDrop.DeltaY )

DragNDrop.wtMovable:SetPlacementPlain( DragNDrop.Place )

common.SetCursor( "drag" )

end

end

function OnEventDNDDropAttempt()

if DragNDrop.IsPicked then

mission.DNDConfirmDropAttempt()

common.SetCursor( "default" )

DragNDrop.IsPicked = false

end

end

Как с этим обращаться:

Инициализация всего этого добра делается очень просто:

Code:
DNDInit( wtReacting, wtMovable, ID )

DNDReg() -- Это только в том случае, если панель видима (не скрыта).

Параметры DNDInit() :

wtReacting -- виджет, на который привязывается реакция, т.е. виджет, ЗА КОТОРЫЙ будет перетаскиваться панель. Это может быть сама перетаскиваемая панель (например, wtMainPanel), но НЕ обязательно (!), это может быть что угодно, например, ЗАГОЛОВОК ОКНА.

wtMovable -- виджет, который нужно перемещать. Обычно, это "материнская" панель (например, wtMainPanel).

ID - уникальный ID перемещаемой панели. Число от 2 до 999 (может, можно и больше, я границу максимальных значений не искал).

Ну и, при каждом показе перемещаемой формы, нужно, соответственно, заново регистрировать её, и при сокрытии, соответственно, отрегистрировать:

Code:
Виджет:Show(true)

DNDReg()

Code:
DNDUnreg()

Виджет:Show(false)

P.S. Оказалось, я не один занимался доработкой этих функций. Valltron тоже хорошо потрудился над ними, в своём аддоне "LootInfo", и завтра я стырю у него ещё один наворот -- чтобы виджет невозможно было утащить за пределы окна, когда игра в оконном режиме. Я сам оконным режимом не пользуюсь, поэтому, даже не подумал об этом.

Link to comment
Share on other sites

SLA давай оберенм в класс, да запихнем в AOClassLibrary.lua - можно в тотже класс WidgetContainerClass - и там сделать методы типа - SetMobvable( true\false, WidgetName ), и он кстати сам будет DNDReg()\DNDUnreg() делать при скрытие и показе фрейма. Как думаешь ?

Link to comment
Share on other sites

Еше момент :

DragNDrop.Screen = widgetsSystem:GetPosConverterParams()

Ты берешь данные об экране 1 раз при инициализации..... это не верно, так как пользователь может изменить разрешение экрана в ходе работы. Мне кажеться правелнее всеже брать инфц о скрине каждый раз когда пытаешься потащить.....

Link to comment
Share on other sites

Guest Valltron

Как сказал SLA - он перепишет и доработает функцию, взяв доработки из LootInfo

там реализовано что при любом изменении размера окна, даже при окне в четверть экрана, будет нормально панель бегать за курсором. И плюс панель не утаскивается за края экрана.

ps: пока я тут над одним аддоном, да програмкой парюсь, учась у АН делась все через Ж, мои наброски уже на библиотеки растащили :)

Link to comment
Share on other sites

Не только твои. Мы посути маленькое комьюнити. Активных кодеров по пальцам сосчитать, аддон - opensource. И ессно все друг у друга "тырят" ( в хорошем смысле слова ) идеи по реализации. Это гут - ибо это наиболее быстрый способ - обмена опытом. Просто хорошии идеи нужно - обизательно нужно собрать в 1ой библиотеки. Это поможет нам всем и новым кодерам кторые будут приходить писать аддоны для АО.

Link to comment
Share on other sites

Guest Valltron

Я и не имел в виду что это плохо, я хотел сказать что у меня не остается времени чтобы активно помогать. А только раздавать на доработку. хотя по сути сейчас занят только аддоном, да Апдейтером, но на них уходит все время. А либа нужна, но чтобы не получилось так, что мы напишем lua внутри lua... %)

Link to comment
Share on other sites

Вот по этому и нада ее делать уже сейчас. Просто я так погляжу все усилено чегото пишут *)))) И ессно времени не остаеться на "доведение до ума". Я сам также начал писать ДПС метер. Начал писать топорно - либы работало, разбирайся с АПИ и устройством виджетов. Когда почуствовал что, более менее разобрался и уперся в тот факт что начинаю "тонуть" в куче глобальных переменных, и код при просмотре похож на "монстра" - решил отвлечся притормозить разработку аддона и привести код в порядок, так сказать "причесать". Стал отталкиваться от идеи обернуть всю внутреннию возню с виджетами в КлассКонтейнер который бы этим всем управлял, да и не только работу с виджетами нада обернуть в класс. Нада стараться все обернуть в класс. Просто "Чем дальще в лес - тем толще портизаны" *))) Я ктому что чем крупнее аддон ( чем больше в нем окошек, кнопок, панелей, текстов и т.д. ), тем больше код засаряеться всякими глобалами, повторяющимися кусками кода, и все меннее код такого аддона читабелен. Вообщем я за "эстетичность" и "прозрачность" кода. Нада работать в этом направлении

Link to comment
Share on other sites

  • 3 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using our site you agree to the Terms of Use