- 4,809
- 6,487
GifPlayer - DX9 враппер для либы gifdec. Использовать его можно в любой dx9 игре, а не только в GTA.
Класс GifPlayer
Внутренние типы
eFrameOrder
frame_t
Это внутренняя структура для хранения кадра анимации
Пример использования
Пример основан на моем шаблоне аси плагинов
Полный код примера: https://gitlab.com/prime-hack/samp/plugins/gifrender
Здесь на 13 строке создается объект плеера для проигрывания файла anim.gif, после чего в потоке рендера, на 38 строке, я получаю от плеера текстуру для рендера и чуть ниже рисую ее на экране.
При изменении разрешения игры или сворачивании/разворачивании окна, вызываются события onLostDevice и onResetDevice, в которых обновляются текстуры плеера (строки 46 и 51). Без обновления текстур игра будет зависать при изменении разрешения и сворачивании/разворачивании окна
Исходникки плеера: https://gitlab.com/SR_team/gifplayer
В приложении архив со скомпилированным примером и gif-файлом
Класс GifPlayer
explicit GifPlayer( const char *file_name ); | Конструктор. В конструкторе из файла загружаются фреймы. Для каждого фрейма аллоцируется отдельная память, что бы не считывать файл повторно. |
void Initialize( class IDirect3DDevice9 *pD3Ddev ) noexcept; | Инициализация текстур DX9. Должно каждый раз вызываться из OnResetDevice, и 1 раз после создания объекта |
void Invalidate() noexcept; | Удаление текстур DX9 из видеопамяти. Должно каждый раз вызываться из OnLostDevice |
class 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; | Ширина изображения GIF |
uint16_t GetHeight() const noexcept; | Высота изображения GIF |
Внутренние типы
eFrameOrder
kRenderAllFrames | Все кадры анимации выводятся по очереди, даже если с момента прошлого кадра прошло времени больше, чем должен выводиться следующий кадр |
kSkipTimedOutFrames | Кадры, которые не успевают вывестись вовремя будут проигнорированы |
Это внутренняя структура для хранения кадра анимации
Пример использования
Пример основан на моем шаблоне аси плагинов
Полный код примера: https://gitlab.com/prime-hack/samp/plugins/gifrender
C++:
#include "main.h"
#include <d3d9/DrawHook.h>
#include <d3d9/d3drender.h>
#include <GifPlayer.h>
#include <thread>
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() );
}
При изменении разрешения игры или сворачивании/разворачивании окна, вызываются события onLostDevice и onResetDevice, в которых обновляются текстуры плеера (строки 46 и 51). Без обновления текстур игра будет зависать при изменении разрешения и сворачивании/разворачивании окна
Исходникки плеера: https://gitlab.com/SR_team/gifplayer
В приложении архив со скомпилированным примером и gif-файлом