PDA

Просмотр полной версии : GifPlayer


SR_team
20.07.2021, 21:24
GifPlayer - DX9 враппер для либы gifdec (https://github.com/lecram/gifdec). Использовать его можно в любой dx9 игре, а не только в GTA.

КлассGifPlayer

explicit GifPlayer( const char *file_name );Конструктор. В конструкторе из файла загружаются фреймы. Для каждого фрейма аллоцируется отдельная память, что бы не считывать файл повторно.void Initialize( class IDirect3DDevice9 *pD3Ddev ) noexcept;Инициализация текстур DX9. Должно каждый раз вызываться из OnResetDevice, и 1 раз после создания объектаvoid Invalidate() noexcept;Удаление текстур DX9 из видеопамяти. Должно каждый раз вызываться из OnLostDeviceclass IDirect3DTexture9 *ProcessPlay( eFrameOrder order ) const noexcept;Функция проигрывания gif-анимации. Сама функция ничего не рисует, она возвращает DX9 текстуру для рендераvoid ResetLoop() const noexcept;Сброс циклов воспроизведения, для воспроизведения анимации с началаbool IsLoopEnded() const noexcept;Проверка, закончилась ли анимация.bool IsDrawBg() const noexcept;Проверка, рисуется ли для этой gif задний план. По умолчанию рисовать ли задник определяется в конструктореvoid ToggleBg( bool state ) noexcept;Переключить отрисовку заднего плана.void ToggleBgNoUpdate( bool state ) noexcept;То же самое, что и выше, но текстуры не изменятся, пока не наступит событие OnResetDevice или не будет вызвано принудительное обновлениеvoid Update() noexcept;Принудительное обновление текстур анимацииuint16_t GetWidth() const noexcept;Ширина изображения GIFuint16_t GetHeight() const noexcept;Высота изображения GIF

Внутренние типы

eFrameOrder

kRenderAllFramesВсе кадры анимации выводятся по очереди, даже если с момента прошлого кадра прошло времени больше, чем должен выводиться следующий кадрkSkipTimedOutFramesКадры, которые не успевают вывестись вовремя будут проигнорированы
frame_t

Это внутренняя структура для хранения кадра анимации

Пример использования

Пример основан на моемшаблоне аси плагинов (https://gitlab.com/prime-hack/samp/plugins/templates/AsiPlugin)

Полный код примера: https://gitlab.com/prime-hack/samp/plugins/gifrender

C++:






#include "main.h"
#include
#include
#include
#include
AsiPlugin
::
AsiPlugin
(
)
:
SRDescent
(
nullptr
)
{
did
=
g_class
.
draw
->
onDraw
+=
std
::
tuple
{
this
,
&
AsiPlugin
::
draw
}
;
lid
=
g_class
.
draw
->
onPreReset
+=
std
::
tuple
{
this
,
&
AsiPlugin
::
lost
}
;
rid
=
g_class
.
draw
->
onPostReset
+=
std
::
tuple
{
this
,
&
AsiPlugin
::
reset
}
;
std
::
thread
(
[
this
]
{
player
=
new
GifPlayer
(
"anim.gif"
)
;
gif_loaded
=
true
;
}
)
.
detach
(
)
;
}
AsiPlugin
::
~
AsiPlugin
(
)
{
g_class
.
draw
->
onPostReset
-=
rid
;
g_class
.
draw
->
onPreReset
-=
lid
;
g_class
.
draw
->
onDraw
-=
did
;
delete
player
;
if
(
render
)
g_class
.
draw
->
d3d9_releaseRender
(
render
)
;
}
void
AsiPlugin
::
draw
(
)
{
if
(
!
gif_loaded
)
return
;
static
bool
texturesInitialized
=
false
;
if
(
!
texturesInitialized
)
{
player
->
Initialize
(
DrawHook
::
d3d9_device
(
)
)
;
texturesInitialized
=
true
;
}
if
(
!
render
)
render
=
g_class
.
draw
->
d3d9_createRender
(
)
;
auto
texture
=
player
->
ProcessPlay
(
)
;
render
->
D3DBindTexture
(
texture
)
;
render
->
D3DTexQuad
(
0
,
0
,
player
->
GetWidth
(
)
,
player
->
GetHeight
(
)
)
;
render
->
D3DBindTexture
(
nullptr
)
;
}
void
AsiPlugin
::
lost
(
)
{
if
(
!
gif_loaded
)
return
;
if
(
player
)
player
->
Invalidate
(
)
;
}
void
AsiPlugin
::
reset
(
)
{
if
(
!
gif_loaded
)
return
;
if
(
player
)
player
->
Initialize
(
DrawHook
::
d3d9_device
(
)
)
;
}




Здесь на 13 строке создается объект плеера для проигрывания файла anim.gif, после чего в потоке рендера, на 38 строке, я получаю от плеера текстуру для рендера и чуть ниже рисую ее на экране.

При изменении разрешения игры или сворачивании/разворачивании окна, вызываются события onLostDevice и onResetDevice, в которых обновляются текстуры плеера (строки 46 и 51). Без обновления текстур игра будет зависать при изменении разрешения и сворачивании/разворачивании окна

Исходникки плеера:https://gitlab.com/SR_team/gifplayer


В приложении архив со скомпилированным примером и gif-файлом

SR_team
20.07.2021, 21:26
С ImGui можно использовать так:

C++:






ImGui
::
Image
(
player
->
ProcessPlay
(
)
,
{
180
,
120
}
)
;




Это создаст в окне анимированное изображение размером 180*200. Вместо 180*200 можно использовать

player->GetWidth()

и

player->GetHeight()

, что бы использовать размеры gif

Dragynovv
20.07.2021, 21:31
эхх, появилась бы эта тема год назад :(

copypaste_scripter
20.07.2021, 23:30
ну я изсиняюсь, всегда почти оффтоп пишу, но правда я любитель таких фишек, ответь пожалуйста. как сделать винду выглядеть так, или что это ваще? яблоко что ли?

poofe
20.07.2021, 23:53
ну я изсиняюсь, всегда почти оффтоп пишу, но правда я любитель таких фишек, ответь пожалуйста. как сделать винду выглядеть так, или что это ваще? яблоко что ли?


Это linux

SR_team
21.07.2021, 14:53
Сделай инструкцию


Wine 5.19 (самая стабильная версия, для которой есть протоновский патч FS hack), на 6.12 он тоже работает, но у него есть мелкие баги, когда экран моргает черным как на винде при запуске игры в окне через лаунчер аризоны. В wine наставлены d3d9_* либы, которые отвечают за спрайты и шрифты, которые использует SAMP (без них чат обрезан, а кнопки в диалогах выше положенного), а так же доставлены d3d9_compiler*, но они нужны мне были для компиляции шейдеров, а для игры они не нужны. Ну и конечно стоит DXVK, что бы игра использовала Vulkan, а не OpenGL для DirectX9.

Собственно все. В таком конфиге SAMP работает отлично. Для остальных программ использую Wine 6.12 потому что там WinAPI больше совпадает с виндой.