Добавлен , опубликован

Основы Интерфейса

Содержание:
Самый ранний вариант можно изучить - спрайты и модели. Именно в них можно задавать анимации.

Спрайт

пример создания спрайта

При создании спрайта MinimapWaypoint анимация проигрывает сама. При создании спрайт проигрывает анимацию stand
Frame "SPRITE" "MinimapWaypoint" {
    BackgroundArt "UI\Minimap\Minimap-Waypoint.mdx",
}

код создания спрайта

local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local sprite = BlzCreateFrameByType("SPRITE", "MinimapWaypoint", gameUI, "MinimapWaypoint", 0)
BlzFrameSetAbsPoint(sprite, FRAMEPOINT_CENTER, 0.4, 0.3)

Как проиграть анимацию триггером?

Разбираем функцию BlzFrameSetSpriteAnimate анимировать спрайт можно действием BlzFrameSetSpriteAnimate.
---@param frame framehandle
---@param primaryProp integer
---@param flags integer
---@return nothing
function BlzFrameSetSpriteAnimate(frame, primaryProp, flags) end	-- (native)
Где frame - фрейм;
primaryProp это не индекс анимации, но воспроизводит определённый спектр.
флаг анимация
0 birth
1 death
2 stand
3 morph
4 alternate
flags - последняя цифра в функции скорее всего зациклить ли анимацию, однако не тестировалось. Не знаю как воспроизвести. Другой источник сообщает, что модель должна быть зациклена, чтобы это включать. А это ещё в редакторе моделей работать над моделью.

Код анимирования спрайта

Периодический пинг через таймер.
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local sprite = BlzCreateFrameByType("SPRITE", "MinimapWaypoint", gameUI, "MinimapWaypoint", 0)
BlzFrameSetAbsPoint(sprite, FRAMEPOINT_CENTER, 0.4, 0.3)

local sss = 0 --счетчик
TimerStart(CreateTimer(), 1.00, true, function()
    print("SSS: "..sss)
    BlzFrameSetSpriteAnimate(sprite, sss, 0)
    sss = sss+1
    if sss>2 then
        sss = 1
    end
end)

function Test2()
    -- create a Sprite copy the button's positions
    local model =  BlzCreateFrameByType("SPRITE", "SpriteName", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
    BlzFrameSetAbsPoint(model, FRAMEPOINT_CENTER, 0.4, 0.3)
    BlzFrameSetSize(model, 0.01, 0.01)
    -- apply the model
    BlzFrameSetModel(model, "Abilities\\Weapons\\RockBoltMissile\\RockBoltMissile.mdl", 0)
    -- Models don't care about Frame Size, But world Object Models are huge . To use them in the UI one has to scale them down alot.
    BlzFrameSetScale(model, 0.00006)
    -- play death animation
	-- birth = 0
    -- death = 1
    -- stand = 2
    -- morph = 3
    -- alternate = 4
    BlzFrameSetSpriteAnimate(model, 1, 0)
end

Настройка размеров спрайта

Функцией BlzFrameSetSize трудно изменить размеры модели. По факту, нативка совсем не изменяет размер модели спрайта. Замечано, что задание размеров size фрейма изменяют только положение модели спрайта от текущего положения спрайта. Т.е. модель спрайта почему-то не всегда там, где спрайт. Советую не трогать BlzFrameSetSize.
Хотя я вам должен сказать, что дело не только в нативке BlzFrameSetSize. Сам спрайт багованный, и он не перемещается туда, куда указываешь (хотя не со всеми спрайтами такое происходит. но и может произойти и такое. Не знаю с чем связано, мб модель, или какая связь модели с изменением координат). А если и размеры указать BlzFrameSetSize, то отклонется модель спрайта еще дальше. Получается модель спрайта отклоняется два раза от зафикс точки спрайта: при указании новой позиции на экране x,y (не факт), и при изменении размеров size.
Поэтому проще спрайт привязать к точкам другого фрейма, чтобы не съезжал.
По идее у вас не будет съезжать, если указан дефолтный размер модели. Т.е. возьмем модель кулдауна, по факту размер кнопки равен w=0.039,h=0.039. Создается в нужном месте. а вот при изменении размера от дефолтного, модель съезжает.
BlzFrameSetSize(sprite, 0.35,0.35) --модель съезжает в правый верхний угол
настраивать размер спрайта можно через
BlzFrameSetScale(sprite, 0.15)

Задание модели фрейму

Прописывать нужно модель как обычно, двойными слешами и с путем как обычно в импорте
BlzFrameSetModel(new_Frame, "war3mapImported\\myModel.mdx", 0)

Специальная функция создания фрейма от Hate

Можно создать спрайт с помощью функции ниже. Дело в том, что многие спрайты недоработанные, багованные и могут съезжать от первоначальных координат. Поэтому проще спрайт привязать к точкам другого фрейма, чтобы не съезжал
Предложено новый фрейм крепить точками relative_point_from, relative_point_to к заданному relative_to_frame с оффсетами.
Hate советует привязывать левый низ FRAMEPOINT_BOTTOMLEFT, к левому низу FRAMEPOINT_BOTTOMLEFT
---@param model string
    ---@param scale real
    ---@param relative_to_frame framehandle
    ---@param relative_point_from framepointtype
    ---@param relative_point_to framepointtype
    ---@param offset_x real
    ---@param offset_y real
    ---@param parent framehandle
    ---@return framehandle
    function CreateSprite(model, scale, relative_to_frame, relative_point_from, relative_point_to, offset_x, offset_y, parent)
        local new_Frame = BlzCreateFrameByType("SPRITE", "justAName", parent, "WarCraftIIILogo", 0)
            BlzFrameSetPoint(new_Frame, relative_point_from, relative_to_frame, relative_point_to, offset_x, offset_y)
            BlzFrameSetSize(new_Frame, 1., 1.)
            BlzFrameSetScale(new_Frame, scale)
            BlzFrameSetModel(new_Frame, model, 0)
        return new_Frame
    end

Создание через fdf-file

Этот раздел для понимания работы:
Здесь я пробую создать MODEL (см. ниже про model), идентично это работает и со спрайтами. Просто когда спрайт создаешь, он запускает анимацию и исчезает. Если не подобрать нужную. Поэтому возня это вся. чтобы вы понимали: некоторые спрайты типа кулдауна имеют анимацию в 1 сек, при запуске спрайт очень быстро проигрывает анимацию, и все. Вы не успеваете ничего понять, и проверить зафиксирован ли спрайт. Пример в моем случае, нужно было посмотреть как сидит кулдаун на кнопке, и нужно было выровнять положение модели. Я решил использовать MODEL вместо SPRITE (внизу показаны спрайты, но я пробовал через MODEL для проверки), чтобы смотреть как расположены будут фреймы. Тип Model не может проигрывать анимации, это модель с статичным изображением. Некоторые модели по типу кулдауна помогают чекать тек положение, размеры. Но возможно этот способ может и не подойти вам, я еще не знаю всех нюансов моделей и frame-model/sprite. Зависит, что за модель используется. Некоторые модели могут не отображаться в Model (мб нет статичной анимации или чего еще, как с примером waypoint. некоторые говорят, что нужно в таких модели камеру настраивать, как у портретов)
Когда вы поймете, что Model создается правильно, и никуда не съезжает. Проверите размеры. Теперь уже можно переделать обратно на тип фрейм Sprite.

первый способ

Frame "FRAME" "parentCoold" {
Height 0.039,
Width 0.039,
	Frame "SPRITE" "Coold" {
		BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
		LayerStyle "NOSHADING",

		SetAllPoints,
	}
}

второй способ (от Hate)

Frame "FRAME" "parentCoold" {
Height 0.039,
Width 0.039,
Frame "SPRITE" "Coold" {
    BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
    LayerStyle "NOSHADING",

    SetPoint BOTTOMLEFT, "parentCoold", BOTTOMLEFT, 0, 0,
}

--перед тем как инициировать код, необходимо задержка для спрайтов. Когда в начале игры только-только прорисовывается экран, спрайт уже проиграл половину анимации, из-за чего мб не понятно. тк спрайт в 1 сек оч быстро проигрывает. На гифку не успеваю записать  
TimerStart(CreateTimer(), 2.00, false, function()
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local parent = BlzCreateFrameByType("FRAME", "parentCoold", gameUI, "parentCoold", 0)
BlzFrameSetSize(parent, 0.035, 0.035) --если указать размеры родителю (что указан в fdf), то модель спрайта-потомка меняет размеры следом. Обращаю внимвние на то, что дефолтный размер модели кулдауна 0.039×0.039. Но тут указываю родителю спрайта 0.035х0.035, и модель принимает точно такой размер.
BlzFrameSetAbsPoint(parent, FRAMEPOINT_CENTER, 0.4, 0.3)

local child = BlzGetFrameByName("Coold",0) --BlzFrameGetChild(parent, 0)
--BlzFrameSetScale(child, 0.15)

--далее пытаюсь создать иконку блейда, чтобы сравнить не съехала. Если не съехла, можно выключить, и запустить второй раз посмотреть лежит ли она внутри.
local blademaster = BlzCreateFrameByType("BACKDROP", "Blademaster", gameUI, "", 0)
BlzFrameSetSize(blademaster, 0.035, 0.035)
BlzFrameSetAbsPoint(blademaster, FRAMEPOINT_CENTER, 0.4, 0.3)
BlzFrameSetTexture(blademaster, "ReplaceableTextures\\CommandButtons\\BTNHeroBlademaster",0, true)

если нужно, чтобы спрайт был выше иконки блэйда
--BlzFrameSetLevel(parent, 2)
--BlzFrameSetLevel(blademaster, 1) 
end)
Они дают два идентичных результата. Нужно тогда вторым способом (способ Hate) в fdf-file подвинуть оффсетами в нижний левый угол, чтобы модель ровнее сиделось (незначительно действие, можно сказать незаметно для глаза. Особенно, когда анимация проигрывает).
Как видим теперь изображение стоит на месте. Поскольку модель кулдауна имеет размеры приблизительно 0.039 x 0.039 (на сам деле, чуть больше чем 0.039), но вы не можете изменить размер модели спрайта через BlzFrameSetSize. BlzFrameSetSize можно задавать только наводящему фрейму, точнее родителю parent. Изменяешь parent, изменяется и child.
Как мы видим выше, создана вторая картинка блэйда, чтобы сравнить расположение и размеры. Картинка блэйда имеет меньший размер 0.035 x 0.035 - специально задал такой же размер. Фрейм parent тоже задал 0.035 x 0.035 через BlzFrameSetSize. И фрейм child изменяет размеры также следом.
Вот спрайт анимированный
А вот чтобы изменить размеры модели необходимо задать скэйл BlzFrameSetScale(child, 2.00) - ВНИМАНИЕ: Scale можно задать только спрайту, MODEL никак не хочет изменять размеры
На gif файле показано как спрайт увеличен в 2 раза.
Так понимаю, смотря на рис выше:
Если размеры слишком большие > 1.00, то в правый верхний угол растягивается. И наоборот, если < 1.00. Размеры легко считать, если знать дефолтные размеры модель = 0.039 x 0.039. Этот множитель умножает на эти размеры, достаточно просто получается

Фрейм MODEL

Тип модель ни чем не отличается от спрайта. Правда, не знаю, может ли данный тип проигрывать анимацию. Может ли дело в анимации? Также в отличии от спрайта, я не смог изменять размеры, если привязать MODEL к какому-нибудь фрейму. Этот тип абсолютно бесполезен, либо я не знаю чего-то такого.

fdf-file model

В отличии от спрайта в model всегда почему-то прописывается
LayerStyle "NOSHADING",
Зато, как model получилось, но не получается никак анимацию запустить. На одном кадре модель заступорена, получилась статичная картинка кулдауна.
Frame "MODEL" "Coold" {
    BackgroundArt "UI\Feedback\Cooldown\UI-Cooldown-Indicator.mdx",
    LayerStyle "NOSHADING",
}
код создания фрейма
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
local fh = BlzCreateFrameByType("MODEL", "Coold", gameUI, "Coold", 0)
BlzFrameSetAbsPoint(fh, FRAMEPOINT_CENTER, 0.0, 0.3)

Вывод

MODEL - это тип фрейма, где модель задана статичным изображением. Размер модели никак не изменить, также не получается проиграть анимацию.
Frame "FRAME" "parentModel2" {
Height 0.039,
Width 0.039,
Frame "MODEL" "Model2" {
	BackgroundArt "UI\Glues\ScoreScreen\ScoreScreen-Background\ScoreScreen-Background.mdl",
	//SetAllPoints,
	SetPoint BOTTOMLEFT, "parentModel2", BOTTOMLEFT, 0, 0,
	LayerStyle "NOSHADING",
}
}

Анимированные рамки

Может кому пригодится, когда то тоже искал как анимировать рамку, образцы и примеры итд.

Альтернативный способ

Предлагается анимировать фреймы с помощью таймера:

STATUSBAR

Третий вариант предлагается через StatusBar:
Ранее уже были образцы с SimpleStatusBar. Однако, симплстатусбар никак не анимирует модель, а всего лишь растягивает/урезает текстуру. Такое не сложно сделать и обычными средствами, зная пропорцию и растянуть изображение. Однако, этот инструмент не растягивает изображение, а урезает, что находит свое мини-преимущество.
Снизу это фон backdrop (иконка рыцаря смерти), сверху это текстура бара (иконка паладина). Она не размазывается при растяжении/сжатии полоски, как видим урезается часть изображения.

Вернемся к нашему обычному статус-бару. Дело в том, что анимации в спрайтах и моделях никак не регулируются, вы запустили, и анимация пошла, нельзя влиять на скорость воспроизведения, плохо работают, и прочее. И поэтому дело берет в свои руки StatusBar
STATUSBAR — это неинтерактивный (не игровой) фрейм, отображающий модель Warcraft 3. В отличие от Sprite, он не зацикливает анимацию, но текущее время animationTime можно установить с помощью BlzFrameSetValue в виде % от Min/Max до AnimationTime.
  1. Говорят, что «STATUSBAR» поддерживает только анимацию интервалом 1 сек, последовательности после 1 сек отбрасываются.
  2. Этот тип довольно хорошо можно создать с помощью кода только ModelBar без FDF.
От авторов: Hate и TriggerHappy:
do
    local real = MarkGameStarted

    function MarkGameStarted()
        real()
        local bar = BlzCreateFrameByType("STATUSBAR", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)        
        BlzFrameSetAbsPoint(bar, FRAMEPOINT_TOPLEFT, 0.4, 0.3)
        -- Screen Size does not matter but has to be there
        BlzFrameSetSize(bar, 0.00001, 0.00001)
        
        -- Models don't care about Frame Size, But world Object Models are huge . To use them in the UI one has to scale them down alot.
        BlzFrameSetScale(bar, 1)
        
        --BlzFrameSetModel(bar, "ui/feedback/cooldown/ui-cooldown-indicator.mdx", 0)
        --BlzFrameSetModel(bar, "ui/feedback/XpBar/XpBarConsole.mdx", 0)        
        BlzFrameSetModel(bar, "ui/feedback/progressbar/timerbar.mdx", 0)
        --BlzFrameSetModel(bar, "ui/feedback/buildprogressbar/buildprogressbar.mdx", 0)
        --BlzFrameSetMinMaxValue(bar, 0, 100)
        local i = 0
        TimerStart(CreateTimer(), 0.1, true, function()
            BlzFrameSetValue(bar, i)
            i = i + 1
            --i = GetRandomInt(0, 100)
            print(BlzFrameGetValue(bar))
        end)
 
        print("done")
    end
end
Подобным статус баром можно анимировать все что угодно. Если ранее мы анимировали полосы, то можно анимировать бутылки, или анимации как хп/мана бар в диабло, где не типичные полосы, а шары по бокам. Кулдаун можно свой анимировать. На этом - всё.

Как шкалу запустить от 0 до 100% таймером?

  • period - 0.05, период обновления,
  • cd - длительность, сколько должен заполнятся хп бар;
Мой фрейм перезарядки слева направо, адаптируйте под себя:
function StartFrameCD(cd, fh,period)
    local amount = period*100 / cd
    local full = 0

    TimerStart(CreateTimer(), period, true, function()
        full = full + amount
        BlzFrameSetValue(fh, full)
        if full >= 100 then
            DestroyTimer(GetExpiredTimer())
            full = 0
        end
    end)
end
Это работает железно, я так делаю каст бары из фреймов или эффектов, вот ещё пример
Напоследок, карта от Берги, где прикручена модель со вспышкой CD.

Содержание
`
ОЖИДАНИЕ РЕКЛАМЫ...
38
Надо переписывать все эти статьи от спойлер-мании, читать их просто издец, можно почувствовать физическую боль
27
Надо переписывать все эти статьи от спойлер-мании, читать их просто издец, можно почувствовать физическую боль
Спойлеры оч удобны. Зачем мне листать миллиарды текстов на этой страничке, если можно найти раздел и открыть его. Когда что то нужно, быстро нвходишь таким же способом. Клик по кату, и открыл.
Ну статьи надо. Но честно, мотивации нет переделывать все это. Уогда уже нвдоело смотреть в одни и те же тексты. Надо какого нибудь редактора хорошего найти с пониманием рус языка, и вырезать тавтологию, и как то получше выразить мысль. Итак по желанию че то делаю. Занят пока. Кажется, что слишком не нужное все это.. читает мало людей.
25
Дополню немного
Updt. А почему с публикации снято?

Функцией BlzFrameSetSize трудно изменить размеры модели. По факту, нативка совсем не изменяет размер модели спрайта. Замечано, что задание размеров size фрейма изменяют только положение модели спрайта от текущего положения спрайта. Т.е. модель спрайта почему-то не всегда там, где спрайт. Советую не трогать BlzFrameSetSize.
До конца так и не понял как работает этот параметр со спрайтом, но выглядет так, будто он влияет на сдвиг проекции 3D модели в 2D фрейм (возможно, я сейчас сказал полный бред). Исходя из своего опыта ковыряния спрайтов, могу дать такую рекомендацию: если камера модели не используется (то есть выводим со стандартным видом сверху при условном наблюдателе слева), то задаём Size близким к нулю, но не равным нулю. То есть BlzFrameSize(spriteframe, 0.001, 0.001). Если же камера модели используется, то не задаём Size вообще.

настраивать размер спрайта можно через BlzFrameSetScale(sprite, 0.15)
Есть один момент, который может быть не очевиден. Единицы размерности фреймов экрана и единицы размерности модели — это одни и те же единицы. В принципе, можно заглянуть в модели интерфейса и модели лоадскринов, они там все будут в пределах 0.8 x 0.6 (размер экрана). То есть модель нужно либо сразу уменьшать до десятых/сотых/тысячных, либо (если она нормальных "игровых" размеров) уменьшать нативкой до этих же пределов.
Второй неочевидный момент: у модели должны быть правильно рассчитаны границы. Даже если уменьшить модель, но не пересчитать границы, то спрайт с этой моделью будет выводиться не так, как ожидается. BlzFrameSetScale тоже будет работать криво.
Ещё один нюанс: если модель выводится со своей камерой, то задавать BlzFrameSetScale не нужно. Использование камеры предполагает вывод модели на весь экран с видом из камеры, и масштаб в этом случае работает кривовато.

Недавно обнаружил одну проблему: если в модели есть неиспользуемые кости (ноды), то с очень высокой вероятностью при выводе этой модели спрайтом на экран, игра намертво зависнет.

Есть ещё баг. Если в модели есть PopcornFX эффекты и событийные звуки, то они появятся в центре игровой карты. Возможно не только они, но я не тестил другие объекты моделей. Подробнее тут

Если в модели нет ни одного источника света, то модель будет отрендерена, как Unshaded, со всеми вытекающими. Ни одной тени на модели не будет, у HD моделей, например, отвалятся карты нормалей. Если добавить свет, то будет лучше, хотя, как мне кажется, даже в этом случае шейдер будет несколько упрощён.
38
poisoNDealer, переключил авторство публикации
25
poisoNDealer, переключил авторство публикации
А я причём до авторства, это же Ворона статья? Меня просто удивило, что ресурс неопубликованный висит
Чтобы оставить комментарий, пожалуйста, войдите на сайт.