Skip to content

Conversation

MobinYengejehi
Copy link

@MobinYengejehi MobinYengejehi commented Dec 16, 2022

hi
i made a gif player which load and play gifs as fast as possible
you can create a gif like:

local gif = gifCreate(file_path or gif_buffer) -- "logo.gif" for example

local size = Vector2(dxGetMaterialSize(gif))

addEventHandler("onClientRender",getRootElement(),function()
    if isElement(gif) then
        dxDrawImage(0,0,size,gif)
    end
end)

cuz it is a texture element you can use it, inside shaders or inside all dx related functions

@patrikjuvonen patrikjuvonen added the enhancement New feature or request label Dec 16, 2022
@patrikjuvonen
Copy link
Contributor

Thanks for the pull request! Cool idea!

I'm wondering if there is an open source Gif loader library out there that we could use instead of implementing the intricacies ourselves, thinking from a future maintainability and security perspective.

@tederis
Copy link
Member

tederis commented Dec 16, 2022

Great. But I think you should use the new Lua parser.

@MobinYengejehi
Copy link
Author

MobinYengejehi commented Dec 16, 2022

Thanks for the pull request! Cool idea!

I'm wondering if there is an open source Gif loader library out there that we could use instead of implementing the intricacies ourselves, thinking from a future maintainability and security perspective.

yeah we can
i just used https://github.com/hidefromkgb/gif_load and made it a little better because it needed some changes. you can go and see the real code. it is from @hidefromkgb
i thought that we must write code like this
this is my first time trying to contribute mta-blue

@lopezloo
Copy link
Member

lopezloo commented Jul 9, 2023

Do we really need this?

@CrosRoad95
Copy link

Do we really need this?

actualy, no. If you for example want to have gif in mta, i bet there is a program that can turn it into atlas texture with every frame.
If you want to have dynamic gifs, let's say gif avatars then use for example: https://www.npmjs.com/package/gif-to-png

@dmi7ry
Copy link

dmi7ry commented Jul 10, 2023

Do we really need this?

actualy, no. If you for example want to have gif in mta, i bet there is a program that can turn it into atlas texture with every frame. If you want to have dynamic gifs, let's say gif avatars then use for example: https://www.npmjs.com/package/gif-to-png

Keep in mind that GIF is not just a collection of pictures displayed one after the other. GIF allows you to set pauses between frames and other things. If such GIF is directly converted to a png set, then the size of the textures will be much MUCH larger.
And to avoid this, you still have to write a sequencer that will take into account all the pauses between frames, etc. I think that this will be somewhat difficult for many developers.

@CrosRoad95
Copy link

take into account all the pauses between frames, etc.

Probably along with frames you can use some tool to extract metadata.

@dmi7ry
Copy link

dmi7ry commented Jul 10, 2023

take into account all the pauses between frames, etc.
Probably along with frames you can use some tool to extract metadata.

Me personally prefer to use Rive and Spine. But how about not very experienced deveopers? Of course this means that just no one will use animations, and therefore the interfaces will look less interesting than they could be.

@MobinYengejehi
Copy link
Author

MobinYengejehi commented Jul 22, 2023

Do we really need this?

actualy, no. If you for example want to have gif in mta, i bet there is a program that can turn it into atlas texture with every frame. If you want to have dynamic gifs, let's say gif avatars then use for example: https://www.npmjs.com/package/gif-to-png

well then you won't be able to use shaders to control the texture pixels
this feature is not that important cuz developers can use browsers which is much better
but my experience says CEF sometimes doesn't work properly on weak cpus
actually it happened to me multiple times and it wasn't only me who experienced that
mta created browser and also onClientBrowserCreated event was triggered but my display was empty
it seemed like cef didn't change browser texture pixels and all of those was 0x00000000
so i decided to contribute mta and add this feature that is fast and allows developers save some frames inside a gif and use that frames the way they want
and also because this gif element is a dx texture developers can use shaders for it and also apply this shaders on models
for example animated labels on vehicles or something like that
and the way to use it is like this:

local gif = gifCreate("label.gif");

local shader = dxCreateShader("shader.fx");
assert(shader, "couldn't create the shader!");

dxSetShaderValue(shader, "gif", gif);

addCommandHandler("startanim", function()
    gifPlay(gif);
);

addCommandHandler("stopanim", function()
    gifStop(gif);
end);

addCommandHandler("setlabel", function()
    -- engineApplyShaderToWorldTexture ...
end);
texture gif;
sampler2D gifSampler{
    Texture = gif;
};

float4 pixels(float2 coords : TEXCOORD0) : COLOR0 {
    // and for example i want to remove green background here
    float4 color = tex2D(gifSampler, coords);
    
    if (color == float4(0, 1, 0, 1)) {
        return (float4)0;
    }
    
    return color;
}

technique Render{
    pass p0 {
        PixelShader = compile ps_2_a pixels();
    }
}

this feature has less fps drop than the render target or other possible methods
with this api also the clients who use weak systems can experience this animated labels on their vehicles

@PlatinMTA
Copy link
Contributor

The shader idea is kinda cool, I can see myself using it. I would use it to display some forum avatars aswell.

this feature has less fps drop than the render target or other possible methods
Just out of curiosity, do you have some benchmarks about that? Just having the easy implementation is enough, but having it be faster is a no brainer if you need to use .gifs.

@MobinYengejehi
Copy link
Author

MobinYengejehi commented Jul 25, 2023

The shader idea is kinda cool, I can see myself using it. I would use it to display some forum avatars aswell.

this feature has less fps drop than the render target or other possible methods Just out of curiosity, do you have some benchmarks about that? Just having the easy implementation is enough, but having it be faster is a no brainer if you need to use .gifs.

actually i was thinking about playing videos on mta client
i know we can play videos or other medias with CEF
but as i mentioned mta sometimes can't load browser textures
so i decided to somehow create my own library to load videos but i knew lua isn't that fast that i can load my webm buffer and display it on screen
i thought maybe if we had some features in mta that we could allocate memory to save frames and use them can help me.
at first i used textures for that
when i tested it, it took 30 seconds to load only 50 frames and after all frames loaded when i displayed them on screen it was using 8% of my cpu
and most important thing was that creating the texture occupied the memory of graphic card
so i thought if i create only one texture and allocate some bytes from computer memory to save my frames and send that bytes to graphic card memory this can fix my problem (and this is exactly what this gif player does)
then i came up with this gif player idea and decided to make it and ask mta team if they like my idea add it to the launcher
when i used gif player to load my webm frames, it took less than 100 ms to load more than 700 frames and on display, it was
only using something like 0.5% of my cpu
and you can control your player to display frames with gifSetProperty and gifGetProperty functions

new functions:

gifGetProperty(element [gif (dx material)], [int (frame index)] string [property]);
gifSetProperty(element [gif (dx material)], [int (frame index)] string [property], string or number [value]);

gif get properties:
Frame:

delay : gets the frame delay
default_delay : gets the frame default delay

Global:

showing_frame : gets the showing frame
frame_count : gets the loaded frames count
format : gets the gif format GIF89a or GIF87a
tick : gets last updated tick

gif set properties:
Frame:

delay : sets frame delay

Global:

showing_frame : sets showing frame

you know i don't want to open another application in my computers background and create other vm s to display a simple gif

@tederis
Copy link
Member

tederis commented May 31, 2025

@MobinYengejehi Please, resolve the conflicts.

@MobinYengejehi
Copy link
Author

MobinYengejehi commented Jul 15, 2025

@tederis conflicts have been resolved

Copy link
Member

@FileEX FileEX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code generally looks very messy. There are missing line breaks, everything is stacked together, and inside functions there are definitions and structures inserted. It all looks very untidy and needs cleaning up for better readability.

It might be worth reviewing the guidelines:
https://github.com/multitheftauto/mtasa-docs/blob/main/mtasa-blue/CODING_GUIDELINES.md

@@ -36,6 +37,7 @@ class CClientRenderElementManager
CClientScreenSource* CreateScreenSource(uint uiSizeX, uint uiSizeY);
CClientWebBrowser* CreateWebBrowser(uint uiSizeX, uint uiSizeY, bool bIsLocal, bool bTransparent);
CClientVectorGraphic* CreateVectorGraphic(uint width, uint height);
CClientGif* CreateGif(uint width, uint height);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint -> std::uint32_t

@@ -47,6 +49,7 @@ class CClientRenderElementManager
uint GetScreenSourceCount() { return m_uiStatsScreenSourceCount; }
uint GetWebBrowserCount() { return m_uiStatsWebBrowserCount; }
uint GetVectorGraphicCount() { return m_uiStatsVectorGraphicCount; }
uint GetGifCount() { return m_uiStatsGifCount; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint -> std::uint32_t

CClientGif* CClientRenderElementManager::CreateGif(uint width, uint height)
{
// Create the item
CGifItem* pGifItem = m_pRenderItemManager->CreateGif(width, height);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer use Hungarian notation.

pGifItem -> gifItem

Comment on lines +292 to +294
{
return nullptr;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove braces here

Comment on lines +31 to +32
CClientGif* m_pGif;
bool m_bIsCleared;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer use Hungarian notation.

Comment on lines +44 to +50
uint8_t* GetBuffer() { return m_pBuffer; }
long& GetWidth() { return m_lgWidth; }
long& GetHeight() { return m_lgHeight; }
long& GetDelay() { return m_lgDelay; }
long& GetFrameNumber() { return m_lgFrameNumber; }
long& GetFrameCount() { return m_uiFrameCount; }
SString GetFormat() { return m_strFormat; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const + noexcept

public:
CClientGifLoader() = default;
CClientGifLoader(SString& data);
CClientGifLoader(uint8_t* data, unsigned long dataSize);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::uint8_t

Comment on lines +25 to +28
uint left = 0;
uint top = 0;
uint width = 0;
uint height = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::uint32_t

@@ -34,6 +34,7 @@ class CRenderItemManager : public CRenderItemManagerInterface
bool bForce = false);
virtual CScreenSourceItem* CreateScreenSource(uint uiSizeX, uint uiSizeY);
virtual CVectorGraphicItem* CreateVectorGraphic(uint width, uint height);
virtual CGifItem* CreateGif(uint width,uint height);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::uint32_t

// Check underlying data is present
//
////////////////////////////////////////////////////////////////
bool CGifItem::IsValid()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const + noexcept?

@MobinYengejehi MobinYengejehi requested a review from FileEX August 27, 2025 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.