кратко: эта наработка и сам урок помогает отследить наведение мыши на дефолтные кнопки.
Стоит еще проверять выскакивает ли вариковская подсказка ORIGIN_FRAME_UBERTOOLTIP , когда вы наводите на элементы интерфейса: коммандные кнопки, итемы-кнопки, кнопка рабочих, полоса героев, часы, иконки и пр. Обычно эта подсказка невидима, но как только курсором навести на что-то, то всплывает подсказка
Но нам нужно узнать конкретную информацию. например, какая это кнопка. И все это можно сделать вот таким способом.
Иногда хочется узнать, когда локальный игрок указывает мышью на командную кнопку. Поскольку GetMouse on Screen X / Y, способных вычислить координаты экрана, не существует, есть два возможных способа использования:
Первый способ (не рабочий)
первый способ - создать настраиваемую КНОПКУ без текстуры, перекрывающую нужные кнопки.
Недостаток такого способа: многие фреймы становятся невыделяемые для мыши, объекты на карте тоже могут стать не выделяемыми мышью. Вы не сможете кликнуть по кнопке мышью или по чему-то еще. Это происходит из-за того, что ваша самодельная кнопка может находится выше уровнем. Все определяется уровнем, реакция события курсора мыши реагируют на тот фрейм, уровень которого находится выше. Тут очень много сложностей. Ну даже, если опустить ниже, то сложно понять находится ли внутри фрейма, мб у нас и существуют события фреймов - входа, выхода мыши в фрейм. И можно было опустить фрейм ниже, и многое другое. Но работает неидеально
Пример, необходимо определить, находится ли курсор в поле интерфейса. Тут я разбил нижнюю часть интерфейса на 3 фрейма,
Рассчитывал ловить вход событиями мыши MOUSE_ENTER, MOUSE_LEAVE и фиксировать заходы. Столкнулся с многими проблемами. Находясь внутри нижнего интерфейса, я мог навести на мини-карту, навести мышью на любые кнопки, иконки, портрет, и у меня курсор фиксировал покидание поле интерфейса, хотя у меня все еще находился внутри. Нужно тогда было еще и на дефолтные фреймы проверять на вхождение/покидание курсора мыши <= еще больше работы. Это не рабочий вариант, тк фреймы друг на друга наслаиваются, и курсор может покидать один фрейм, переходить в другой, хотя сам находится внутри первоначального. Реакция реагирует только на фрейм, который находится выше всех. Тут ничего не поделаешь. Так реализован движок в варкрафте. Вторая причина - это фрейм-пустышка, на которую рассчитывали проверки делать, занимает места на экране, и если она находится выше остальных фреймов, то вы не сможете кликать по кнопкам в этих местах экрана, клик идет по нашему фрейму. Реакция клика тоже идет по фрейму, что находится выше Третья причина - события немного опаздывают.
update: на самом деле есть решение, но это нужно создать больше проверяющих фреймов. когда входите в игровое поле, то сразу прячем проверяющие вхождение в игровое поле фреймы, и показываем проверяющие фреймы на вход в поле интерфейса. Как только курсор окажется в поле интерфейса, то прячем фреймы поля интерфейса и показываем фреймы игрового поля. Так вы будете знать, где находятся фреймы. Но использовать для проверки события MOUSE ENTER, MOUSE LEAVE плохое решение. Во первых, события медленные, и могут не зафиксировать входы/выходы мыши, как стоит курсор быстро прокрутить. а во-вторых, они фиксируют только заход и выход, если быстро прокрутить, то курсор может не зафиксировать заход, но ваш курсор находится внутри фрейма, значит события на такое не рассчитаны. Рекомендовал проверять с помощью tooltips, вешаем на наши фреймы пустышки-tooltip и радуемся. Об этом подробнее расписано во 2 варианте
update: на самом деле есть решение, но это нужно создать больше проверяющих фреймов. когда входите в игровое поле, то сразу прячем проверяющие вхождение в игровое поле фреймы, и показываем проверяющие фреймы на вход в поле интерфейса. Как только курсор окажется в поле интерфейса, то прячем фреймы поля интерфейса и показываем фреймы игрового поля. Так вы будете знать, где находятся фреймы. Но использовать для проверки события MOUSE ENTER, MOUSE LEAVE плохое решение. Во первых, события медленные, и могут не зафиксировать входы/выходы мыши, как стоит курсор быстро прокрутить. а во-вторых, они фиксируют только заход и выход, если быстро прокрутить, то курсор может не зафиксировать заход, но ваш курсор находится внутри фрейма, значит события на такое не рассчитаны. Рекомендовал проверять с помощью tooltips, вешаем на наши фреймы пустышки-tooltip и радуемся. Об этом подробнее расписано во 2 варианте
Второй способ - использовать подсказки (не очень хороший материал)
Внимание: этот материал не очень хороший. Для проверки наведение на фрейм используется таймером видимость подсказки BlzFrameIsVisible(tooltip), таймер периодически чекает. функция BlzFrameIsVisible может вызвать десинхи в мультиплеере. Поэтому не рекомендуется. Даже с хайва удалили материал. Удалить статью я не могу. Но наверное могу оставить как пример
другой способ - создание всплывающих подсказок для кнопок (что делается только при использовании SIMPLEFRAME для SimpleFrames, а для обычных фреймов используйте FRAME). С помощью BlzFrameSetTooltip можно узнать, что местный игрок наводит курсор на элемент или командную кнопку.
Кратко: как работает система? Вы создаете фреймы на экране, и в добавок к ним подсказки. Обычно, когда наводит игрок на фрейм, у вас всплывает подсказка. То есть эта подсказка становится видимой. Можно вместо подсказки создать невидимый фрейм, и чекать таймером виден ли невидимый для нас фрейм. Когда вы наводите на фрейм, у вас всплывет подсказка.
Плюсы:
- Используется таймер, который периодически проверяет видима ли в данный момент фейковая подсказка. Этот способ быстрее чем использовать события мыши MOUSE ENTER/MOUSE LEAVE MOUSE MOVE и пр.
- Обладает теми же минусами, что и в первой варианте. Вы должны разместить фрейм в какой части экрана, чтобы потом навести мышь, и вас появилась подсказка. Так вы зафиксируете, что мышь там. Однако, объекты на карте станут невыдыляемыми. Короче, можно использовать этот метод только как Drag-and-drop перетаскивание объекта с зажимом кнопки. Нам будет не важно, что на карте.
- Частота обновления подсказок. Можно сказать, что с виду эти подсказки сразу появляются. Но это для человеческого восприятия. Если командой отобразить спрятанный фрейм, нужно время, чтобы подсказка отобразилась. Поэтому нужен таймер с 0.00-0.02 сек.
Создаем SIMPLEFRAME с помощью BlzCreateFrameByType, этот frame у нас будет задействован как всплывающая подсказка. затем таймером проверяем каждые 0.xx секунд на видимость всплывающей подсказки. Похоже, это не имеет никакого побочного эффекта, даже не останавливает обычную всплывающую подсказку.
Поскольку набор всплывающих подсказок работает так хорошо, я не рекомендую перекрывающиеся КНОПКИ. КНОПКИ требуют гораздо большей настройки, и единственное преимущество заключается в том, что событие синхронизируется по сети без дополнительной работы, хотя это, вероятно, является недостатком, потому что всплывающие подсказки, естественно, являются только локальными, и другие игроки не заботятся о тексте, отображаемом в вашем Tooltipbox.
Поскольку набор всплывающих подсказок работает так хорошо, я не рекомендую перекрывающиеся КНОПКИ. КНОПКИ требуют гораздо большей настройки, и единственное преимущество заключается в том, что событие синхронизируется по сети без дополнительной работы, хотя это, вероятно, является недостатком, потому что всплывающие подсказки, естественно, являются только локальными, и другие игроки не заботятся о тексте, отображаемом в вашем Tooltipbox.
lua код
-- creates tooltip frames (for command buttons) which are checked 32 times a second when a different tooltip is visible function HoversCommandButton is called with the new index, beaware this is async
do
local real = MarkGameStarted
function MarkGameStarted()
real()
local commandButtonTooltip = {}
local frame
local button
-- saves the last selected Button, async
CurrentSelectedButtonIndex = nil
--create one tooltip frame for each command button
for int = 0, 11 do
button = BlzGetOriginFrame(ORIGIN_FRAME_COMMAND_BUTTON, int)
frame = BlzCreateFrameByType("SIMPLEFRAME", "", button, "", 0)
BlzFrameSetTooltip(button, frame)
BlzFrameSetVisible(frame, false)
commandButtonTooltip[int] = frame
end
TimerStart(CreateTimer(), 1.0/32, true, function()
local selectedAnything = false
-- loop all tooltips and check for the visible one
for int = 0, 11 do
if BlzFrameIsVisible(commandButtonTooltip[int]) then
selectedAnything = true
-- the new selected is not the same as the current one?
if CurrentSelectedButtonIndex ~= int then
HoversCommandButton(int)
end
CurrentSelectedButtonIndex = int
end
end
-- now selects nothing?
if not selectedAnything and CurrentSelectedButtonIndex then
HoversCommandButton(nil)
CurrentSelectedButtonIndex = nil
end
end)
print("done")
end
end
function HoversCommandButton(commandButtonindex)
if not commandButtonindex then
print("Now points at nothing")
else
print("Now points at Button:", commandButtonindex)
end
end
очно таким способом можно приложить к любому фрейму. Примеру к мини-карте, портрету и прочее.
кратко: Что тут происходит? когда мышь наводится на любую кнопку Item или кнопку CommandBar у вас отмечается игрой, что курсор мыши лежит на одной из этих кнопок. И даже номер показывают.
На самом деле, при наведении выскакивает невидимая подсказка SIMPLEFRAME. почему SIMPLEFRAME, а не FRAME? да потому что кнопки Items, CommandBar - SimpleButton. На них нельзя вешать FRAME, FRAME как подсказка работать не будет. Помните, что многие игровые дефолтные кнопки в варике - SimpleButton
отмечу, что существуют события входа в фрейм курсора/выхода из фрейма курсора мыши - это тоже можно использовать. но во-первых, дефолтным системным кнопкам варкрафта нельзя накинуть никакое событие, поэтому автор хайва предложил такое чудесное решение с подсказками. во-вторых, события работают намного медленнее, чем подсказка. Подсказка появляется быстрее, чем сработает событие.
Ред. Берги