SvgCreate: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
No edit summary
(Remove obsolete Requirements section)
 
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Client function}}
{{Client function}}
__NOTOC__
__NOTOC__
{{Added feature/item|1.5.9|1.5.8|20979|}}
{{Added feature/item|1.5.9|1.5.8|20979|
Creates an [[svg]] from size (blank document), filepath or raw data.
Creates an [[svg]] from size (blank document), filepath or raw data.
}}
{{Important Note|Before r21155 ([https://github.com/multitheftauto/mtasa-blue/commit/31579051cc046bc5cb55c59fc4e9e70ec1bdce34 3157905]) the provided callback was only fired '''once''' after the function had performed its task. This is no longer the case - each SVG can now store a single callback function (optional) which is fired '''every time''' the SVG texture has been changed/updated.}}
{{Note|SVG in MTA is handled by the '''lunasvg''' rendering engine - Some features in MTA may not work properly, compared to the browser.}}
''Check the list of supported [https://github.com/sammycage/lunasvg?tab=readme-ov-file#features features].'''
{{Tip|If you are experiencing poor texture quality or artifacts in the form of black outlines, setting the blend mode to '''add''' might help}}
==Syntax==  
==Syntax==  
<syntaxhighlight lang="lua">svg svgCreate ( int width, int height [, string pathOrRawData, function callback ( bool didLoad ) ] )</syntaxhighlight>
<syntaxhighlight lang="lua">svg svgCreate ( int width, int height [, string pathOrRawData, function callback ( element svg ) ] )</syntaxhighlight>


===Required Arguments===
===Required Arguments===
Line 13: Line 22:
{{OptionalArg}}
{{OptionalArg}}
*'''pathOrRawData:''' A string representing the path to your SVG file, or the raw SVG data
*'''pathOrRawData:''' A string representing the path to your SVG file, or the raw SVG data
*'''callback:''' A callback function which is invoked upon SVG document and texture creation, useful for knowing when the [[svg]] is ready
*'''callback:''' A callback function which is stored on the SVG and fired every time the SVG texture is updated (for example, via [[svgSetDocumentXML]]).


'''Note:''' See [[svgSetUpdateCallback]] for setting an svg's callback function after it has been created.
===Returns===
===Returns===
* Returns an [[svg]] if created successfully, ''false'' otherwise.
* Returns an [[svg]] if created successfully, ''false'' otherwise.


==Example==
==Example==
The example below shows how you can load an SVG from raw data (or path) and draw it with [[dxDrawImage]] via [[onClientRender]].
This is a basic example of how you can create an SVG from raw data (or path) and draw it with [[dxDrawImage]] via [[onClientRender]].
 
<syntaxhighlight lang="lua">
-- This could also be a file, with the path provided to svgCreate instead
local rawSvgData = [[
    <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
        <circle cx="250" cy="250" r="250" fill="#0fc0fc" />
    </svg>
]]
 
local myCircleSvg
 
local function drawCircleSvg()
    dxDrawImage(0, 0, 500, 500, myCircleSvg, 0, 0, 0, tocolor(255, 255, 255), false)
end


'''IMPORTANT''': Depending on your implementation, callback usage may be necessary to ensure the SVG texture and XML document are ready.
local function init()
    -- Create an SVG containing a circle, using the raw XML data above
    myCircleSvg = svgCreate(500, 500, rawSvgData)
    addEventHandler("onClientRender", root, drawCircleSvg)
end
addEventHandler("onClientResourceStart", resourceRoot, init)
</syntaxhighlight>
 
Here's another, more in-depth example which utilizes the callback argument. You can use the F2 key to set the SVG to a random size and see the update callback output a message to debugscript.


<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- This could also be a file, with the path provided to svgCreate
-- This could also be a file, with the path provided to svgCreate instead
local rawSvgData = [[
local rawSvgData = [[
     <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
     <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
Line 31: Line 64:
]]
]]


local svg
local svgs = {}
 
local function render(svg)
    if (not isElement(svg)) or (getElementType(svg) ~= "svg") then
        removeEventHandler("onClientRender", root, svgs[svg].handler)
        svgs[svg] = nil
    end
 
    local width, height = svgGetSize(svg)
    dxDrawImage(0, 0, width, height, svg, 0, 0, 0, tocolor(255, 255, 255), false)
end
 
local function onUpdate(svg)
    -- If this is the first update, add svg to our table and start drawing it
    if (not svgs[svg]) then
        svgs[svg] = {
            state = true,
            handler = function()
                render(svg)
            end
        }
 
        addEventHandler("onClientRender", root, svgs[svg].handler)
    end


function init()
    iprint("SVG texture updated", svg, getTickCount())
end
 
local function init()
     -- Create an SVG containing a circle, using the raw XML data above
     -- Create an SVG containing a circle, using the raw XML data above
     svg = svgCreate(500, 500, rawSvgData, function(didLoad)
     local mySvg = svgCreate(500, 500, rawSvgData, onUpdate)
        if (not didLoad) then -- SVG failed to load, so don't continue
            return
        end


        addEventHandler("onClientRender", root, render)
    -- Bind a key to set SVG to a random size, which will trigger the onUpdate callback
    bindKey("F2", "down", function()
        setRandomSVGSize(mySvg)
     end)
     end)
end
end
addEventHandler("onClientResourceStart", resourceRoot, init)
addEventHandler("onClientResourceStart", resourceRoot, init)


function render()
function setRandomSVGSize(svg)
     dxDrawImage(0, 0, 500, 500, svg, 0, 0, 0, tocolor(255, 255, 255), false)
    local width, height = svgGetSize(svg)
     local diff = math.min(width, height) /  math.max(width, height)
    local size = math.random(100, 500)
 
    svgSetSize(svg, size, size * diff)
end
end
</syntaxhighlight>
</syntaxhighlight>
==Requirements==
{{Requirements|n/a|1.5.8-9.20979|}}


==See Also==
==See Also==

Latest revision as of 17:29, 7 November 2024

Creates an svg from size (blank document), filepath or raw data.


[[{{{image}}}|link=|]] Important Note: Before r21155 (3157905) the provided callback was only fired once after the function had performed its task. This is no longer the case - each SVG can now store a single callback function (optional) which is fired every time the SVG texture has been changed/updated.
[[{{{image}}}|link=|]] Note: SVG in MTA is handled by the lunasvg rendering engine - Some features in MTA may not work properly, compared to the browser.

Check the list of supported features.'


[[{{{image}}}|link=|]] Tip: If you are experiencing poor texture quality or artifacts in the form of black outlines, setting the blend mode to add might help

Syntax

svg svgCreate ( int width, int height [, string pathOrRawData, function callback ( element svg ) ] )

Required Arguments

  • width: Desired width, preferably power of two (16, 32, 64 etc.), maximum is 4096
  • height : Desired height, preferably power of two (16, 32, 64 etc.), maximum is 4096

Optional Arguments

NOTE: When using optional arguments, you might need to supply all arguments before the one you wish to use. For more information on optional arguments, see optional arguments.

  • pathOrRawData: A string representing the path to your SVG file, or the raw SVG data
  • callback: A callback function which is stored on the SVG and fired every time the SVG texture is updated (for example, via svgSetDocumentXML).

Note: See svgSetUpdateCallback for setting an svg's callback function after it has been created.

Returns

  • Returns an svg if created successfully, false otherwise.

Example

This is a basic example of how you can create an SVG from raw data (or path) and draw it with dxDrawImage via onClientRender.

-- This could also be a file, with the path provided to svgCreate instead
local rawSvgData = [[
    <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
        <circle cx="250" cy="250" r="250" fill="#0fc0fc" />
    </svg>
]]

local myCircleSvg

local function drawCircleSvg()
    dxDrawImage(0, 0, 500, 500, myCircleSvg, 0, 0, 0, tocolor(255, 255, 255), false)
end

local function init()
    -- Create an SVG containing a circle, using the raw XML data above
    myCircleSvg = svgCreate(500, 500, rawSvgData)
    addEventHandler("onClientRender", root, drawCircleSvg)
end
addEventHandler("onClientResourceStart", resourceRoot, init)

Here's another, more in-depth example which utilizes the callback argument. You can use the F2 key to set the SVG to a random size and see the update callback output a message to debugscript.

-- This could also be a file, with the path provided to svgCreate instead
local rawSvgData = [[
    <svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
        <circle cx="250" cy="250" r="250" fill="#0fc0fc" />
    </svg>
]]

local svgs = {}

local function render(svg)
    if (not isElement(svg)) or (getElementType(svg) ~= "svg") then
        removeEventHandler("onClientRender", root, svgs[svg].handler)
        svgs[svg] = nil
    end

    local width, height = svgGetSize(svg)
    dxDrawImage(0, 0, width, height, svg, 0, 0, 0, tocolor(255, 255, 255), false)
end

local function onUpdate(svg)
    -- If this is the first update, add svg to our table and start drawing it
    if (not svgs[svg]) then
        svgs[svg] = {
            state = true,
            handler = function()
                render(svg)
            end
        }

        addEventHandler("onClientRender", root, svgs[svg].handler)
    end

    iprint("SVG texture updated", svg, getTickCount())
end

local function init()
    -- Create an SVG containing a circle, using the raw XML data above
    local mySvg = svgCreate(500, 500, rawSvgData, onUpdate)

    -- Bind a key to set SVG to a random size, which will trigger the onUpdate callback
    bindKey("F2", "down", function()
        setRandomSVGSize(mySvg)
    end)
end
addEventHandler("onClientResourceStart", resourceRoot, init)

function setRandomSVGSize(svg)
    local width, height = svgGetSize(svg)
    local diff = math.min(width, height) /  math.max(width, height)
    local size = math.random(100, 500)

    svgSetSize(svg, size, size * diff)
end

See Also