Guest WShad Posted February 24, 2010 Share Posted February 24, 2010 В данном примере я демонстрирую как реализовать простое перетаскивание панели виджета по рабочему пространству. Прошу обратить внимание на опцию align в разделе расположения панели (файл MainPanel.(WidgetPanel).xdb), данный код рассчитан на то, что она проставлена в WIDGET_ALIGN_LOW (то есть координаты ориентированы от левого верхнего угла). Если ориентацию ставить в другое значение, то правильное расположение нужно вычислять вручную. File: MoveExample.zip Quote Link to comment Share on other sites More sharing options...
SLA Posted February 24, 2010 Share Posted February 24, 2010 Спасибо! Наконец-то! Этот код нужен практически всем аддонам, у которых есть GUI. Quote Link to comment Share on other sites More sharing options...
Guest WShad Posted February 24, 2010 Share Posted February 24, 2010 Пожалуйста. Этот код, мне кажется, нужен и большинству стандартных игровых окон/панелей. Странно, что он там не реализован, если для этого все подготовлено. Да, кстати, можно поставить WIDGET_ALIGN_LOW_ABS - это немного меняет координацию перемещения. В зависимости от размера панели это может быть значительно или не заметно вообще. Quote Link to comment Share on other sites More sharing options...
Mankubus Posted February 24, 2010 Share Posted February 24, 2010 Спасибо! Нужная вещь! Quote Link to comment Share on other sites More sharing options...
Guest mckozz Posted February 25, 2010 Share Posted February 25, 2010 А как сделать так, чтобы стандарт окна перетаскивались? Куда его вставить? Quote Link to comment Share on other sites More sharing options...
Guest FINTER Posted February 25, 2010 Share Posted February 25, 2010 само окошко перетаскивается на ура, но вот проблема, если перетаскивать что угодно, например скилл с панельки или из книги, то вышеупомянутое окно движется вместе с выбранным объектом не порядок проблема возникает из-за того, что на событие EVENT_DND_DRAG_TO окошко(wtMainPanel) откликается вместе с любым объектом Quote Link to comment Share on other sites More sharing options...
Guest WShad Posted February 25, 2010 Share Posted February 25, 2010 Молодец! Соображаешь! ) Я привел всего лишь простейший пример, а по хорошему надо проверять какое окно начали тащить(чего я в своем аддоне не сделал). Идентификатор передается в пикаттемпт. Спасибо FINTERу за найденный баг. Исправил у себя в аддоне. Можете посмотреть. Только просьба идентификатор 700 не использовать, а то мой аддон будет вместе с вашим бегать. ) Бронирую себе диапазон идентификаторов 700-720. Думаю никто не против? ) Quote Link to comment Share on other sites More sharing options...
Guest WShad Posted February 25, 2010 Share Posted February 25, 2010 Из темы Исправляйте косяк с перемещением панелей! Quote: Есть ещё одна особенность перемещения фреймов, у меня разрешение окна игры нестандартноене 4x3, а 3x4, и особенно заметно на аддонах DarkDPSMeter и DmgMeMetre как фрейм тянется не за указателем мыши, а как бы ближе к верхнему левому углу окна. Для исправления этого эффекта можно попробовать использовать WIDGET_ALIGN_LOW_ABS, должно помочь. Я об этом уже писал. Quote Link to comment Share on other sites More sharing options...
Guest dcrm Posted February 27, 2010 Share Posted February 27, 2010 Да, тут еще немаловажный фактор всплыл... про 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 пока перетаскиваемых больше не нашел вещей... Quote Link to comment Share on other sites More sharing options...
Guest WShad Posted February 27, 2010 Share Posted February 27, 2010 Дополню: 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.: Приятно видеть что моим кодом активно пользуются. ) Quote Link to comment Share on other sites More sharing options...
Guest dcrm Posted February 28, 2010 Share Posted February 28, 2010 Code: это не ID спеллов знаю знаю, просто так чуть более чем понятно Quote Link to comment Share on other sites More sharing options...
merlok Posted March 7, 2010 Share Posted March 7, 2010 есть такой баг в оконном режиме мыша убегает в крайний правый угол - а панель тока до середины скорее всего там берется за базу DC.Width вместо Window.Width Quote Link to comment Share on other sites More sharing options...
SLA Posted March 8, 2010 Share Posted March 8, 2010 В полноэкранном режиме, на широкоформатном экране (16:10), аналогично, но наоборот Если двигать форму из крайнего левого края экрана вправо, то когда курсор проходит ~ 2/3 экрана по оси X, а форма уже у САМОГО правого края экрана. Если двигать дальше вправо, то форма улетает ЗА ПРЕДЕЛЫ экрана. Если её не вернуть, а там "отпустить", то она там и останется, out of radio coverage Такой код как бы предпологает, что либо экран всегда 4:3, либо ширина экрана всегда 1280. Попробую ка я разобраться, что тут можно сделать. Quote Link to comment Share on other sites More sharing options...
SLA Posted March 11, 2010 Share Posted March 11, 2010 Разобрался. Важное дополнение к скрипту перетаскивания окна Нужно срочно исправить во всех аддонах одну функцию: 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 файлах. Отдельной темой. Quote Link to comment Share on other sites More sharing options...
duvo Posted March 11, 2010 Share Posted March 11, 2010 Большое спасибо за полезную информацию =) SLA, а нет ли опечатки? ( WidgetsSystemSafe вместо widgetsSystem ) Quote Link to comment Share on other sites More sharing options...
SLA Posted March 11, 2010 Share Posted March 11, 2010 Да, я исправил =) В документации написано, что класс называется "WidgetsSystemSafe", но: API wrote: WidgetsSystemSafe доступна в каждом аддоне через переменную widgetsSystem. Quote Link to comment Share on other sites More sharing options...
kosh Posted March 12, 2010 Share Posted March 12, 2010 а вынесем ка эту функцию в библиотечку?... Quote Link to comment Share on other sites More sharing options...
SLA Posted March 14, 2010 Share Posted March 14, 2010 Да, можно Вот, кстати, как раз для библиотеки, вылизанные до почти идеального состояния функции. Что новенького: Панель теперь НЕ отрывается от курсора мыши. Панель теперь цепляется к мышке тем местом, где ухватили(а НЕ левым-верхним углом) Код стал гораздо проще в обращении, никакой возни с 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", и завтра я стырю у него ещё один наворот -- чтобы виджет невозможно было утащить за пределы окна, когда игра в оконном режиме. Я сам оконным режимом не пользуюсь, поэтому, даже не подумал об этом. Quote Link to comment Share on other sites More sharing options...
DarkMaster Posted March 15, 2010 Share Posted March 15, 2010 SLA давай оберенм в класс, да запихнем в AOClassLibrary.lua - можно в тотже класс WidgetContainerClass - и там сделать методы типа - SetMobvable( true\false, WidgetName ), и он кстати сам будет DNDReg()\DNDUnreg() делать при скрытие и показе фрейма. Как думаешь ? Quote Link to comment Share on other sites More sharing options...
DarkMaster Posted March 15, 2010 Share Posted March 15, 2010 Еше момент : DragNDrop.Screen = widgetsSystem:GetPosConverterParams() Ты берешь данные об экране 1 раз при инициализации..... это не верно, так как пользователь может изменить разрешение экрана в ходе работы. Мне кажеться правелнее всеже брать инфц о скрине каждый раз когда пытаешься потащить..... Quote Link to comment Share on other sites More sharing options...
Guest Valltron Posted March 16, 2010 Share Posted March 16, 2010 Как сказал SLA - он перепишет и доработает функцию, взяв доработки из LootInfo там реализовано что при любом изменении размера окна, даже при окне в четверть экрана, будет нормально панель бегать за курсором. И плюс панель не утаскивается за края экрана. ps: пока я тут над одним аддоном, да програмкой парюсь, учась у АН делась все через Ж, мои наброски уже на библиотеки растащили Quote Link to comment Share on other sites More sharing options...
DarkMaster Posted March 16, 2010 Share Posted March 16, 2010 Не только твои. Мы посути маленькое комьюнити. Активных кодеров по пальцам сосчитать, аддон - opensource. И ессно все друг у друга "тырят" ( в хорошем смысле слова ) идеи по реализации. Это гут - ибо это наиболее быстрый способ - обмена опытом. Просто хорошии идеи нужно - обизательно нужно собрать в 1ой библиотеки. Это поможет нам всем и новым кодерам кторые будут приходить писать аддоны для АО. Quote Link to comment Share on other sites More sharing options...
Guest Valltron Posted March 16, 2010 Share Posted March 16, 2010 Я и не имел в виду что это плохо, я хотел сказать что у меня не остается времени чтобы активно помогать. А только раздавать на доработку. хотя по сути сейчас занят только аддоном, да Апдейтером, но на них уходит все время. А либа нужна, но чтобы не получилось так, что мы напишем lua внутри lua... Quote Link to comment Share on other sites More sharing options...
DarkMaster Posted March 16, 2010 Share Posted March 16, 2010 Вот по этому и нада ее делать уже сейчас. Просто я так погляжу все усилено чегото пишут *)))) И ессно времени не остаеться на "доведение до ума". Я сам также начал писать ДПС метер. Начал писать топорно - либы работало, разбирайся с АПИ и устройством виджетов. Когда почуствовал что, более менее разобрался и уперся в тот факт что начинаю "тонуть" в куче глобальных переменных, и код при просмотре похож на "монстра" - решил отвлечся притормозить разработку аддона и привести код в порядок, так сказать "причесать". Стал отталкиваться от идеи обернуть всю внутреннию возню с виджетами в КлассКонтейнер который бы этим всем управлял, да и не только работу с виджетами нада обернуть в класс. Нада стараться все обернуть в класс. Просто "Чем дальще в лес - тем толще портизаны" *))) Я ктому что чем крупнее аддон ( чем больше в нем окошек, кнопок, панелей, текстов и т.д. ), тем больше код засаряеться всякими глобалами, повторяющимися кусками кода, и все меннее код такого аддона читабелен. Вообщем я за "эстетичность" и "прозрачность" кода. Нада работать в этом направлении Quote Link to comment Share on other sites More sharing options...
SLA Posted April 1, 2010 Share Posted April 1, 2010 Quote: Ты берешь данные об экране 1 раз при инициализации..... Исправил. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.