SR_team

like pancake
Автор темы
BH Team
4,720
6,365
GifPlayer - DX9 враппер для либы gifdec. Использовать его можно в любой dx9 игре, а не только в GTA.


Класс 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Кадры, которые не успевают вывестись вовремя будут проигнорированы
frame_t
Это внутренняя структура для хранения кадра анимации

Пример использования
Пример основан на моем шаблоне аси плагинов
Полный код примера: 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() );
}
Здесь на 13 строке создается объект плеера для проигрывания файла anim.gif, после чего в потоке рендера, на 38 строке, я получаю от плеера текстуру для рендера и чуть ниже рисую ее на экране.
При изменении разрешения игры или сворачивании/разворачивании окна, вызываются события onLostDevice и onResetDevice, в которых обновляются текстуры плеера (строки 46 и 51). Без обновления текстур игра будет зависать при изменении разрешения и сворачивании/разворачивании окна





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

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

Вложения

  • Example.zip
    2.1 MB · Просмотры: 26

SR_team

like pancake
Автор темы
BH Team
4,720
6,365
С ImGui можно использовать так:
C++:
ImGui::Image( player->ProcessPlay(), { 180, 120 } );
Это создаст в окне анимированное изображение размером 180*200. Вместо 180*200 можно использовать player->GetWidth() и player->GetHeight(), что бы использовать размеры gif
 

copypaste_scripter

Известный
1,218
223
ну я изсиняюсь, всегда почти оффтоп пишу, но правда я любитель таких фишек, ответь пожалуйста. как сделать винду выглядеть так, или что это ваще? яблоко что ли?
 

SR_team

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

Собственно все. В таком конфиге SAMP работает отлично. Для остальных программ использую Wine 6.12 потому что там WinAPI больше совпадает с виндой.
 
  • Нравится
Реакции: deleted-user-163337