├── .rive_head
├── samples
├── Viewer
│ ├── Assets
│ │ ├── ball.riv
│ │ ├── tape.riv
│ │ ├── runner.riv
│ │ ├── StoreLogo.png
│ │ ├── switch_event_example.riv
│ │ ├── SplashScreen.scale-200.png
│ │ ├── LockScreenLogo.scale-200.png
│ │ ├── Square44x44Logo.scale-200.png
│ │ ├── Wide310x150Logo.scale-200.png
│ │ ├── Square150x150Logo.scale-200.png
│ │ └── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── App.xaml
│ ├── Viewer.csproj.user
│ ├── MainPage.xaml.cs
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ └── Default.rd.xml
│ ├── MainPage.xaml
│ ├── Package.appxmanifest
│ ├── App.xaml.cs
│ └── Viewer.csproj
└── StateMachineInputs
│ ├── Assets
│ ├── StoreLogo.png
│ ├── SplashScreen.scale-200.png
│ ├── LockScreenLogo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ └── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── App.xaml
│ ├── MainPage.xaml.cs
│ ├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
│ ├── Package.appxmanifest
│ ├── MainPage.xaml
│ ├── App.xaml.cs
│ └── StateMachineInputs.csproj
├── .gitmodules
├── Goldens
├── Properties
│ └── launchSettings.json
├── Goldens.csproj
└── Goldens.cs
├── RiveSharp
├── RiveSharp.targets
├── RiveSharp.csproj
├── RiveSharp.nuspec
├── RenderImage.cs
├── create_nupkg.sh
├── 2D.cs
├── Factory.cs
├── Scene.cs
├── RenderPath.cs
├── Renderer.cs
├── RenderPaint.cs
└── RiveAPI.cs
├── RiveSharp.Views.UWP
├── Properties
│ ├── AssemblyInfo.cs
│ └── RiveSharp.Views.UWP.rd.xml
├── StateMachineInputCollection.cs
├── StateMachineInput.cs
├── RivePlayer.Properties.cs
├── RiveSharp.Views.UWP.csproj
└── RivePlayer.cs
├── README.txt
├── native
├── premake5_wasm.lua
├── premake5.lua
└── RiveSharpInterop.cpp
├── RiveSharpSample.sln
└── .editorconfig
/.rive_head:
--------------------------------------------------------------------------------
1 | 24d9162103a73712ba3c80cfc909fee6948a0089
2 |
--------------------------------------------------------------------------------
/samples/Viewer/Assets/ball.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/ball.riv
--------------------------------------------------------------------------------
/samples/Viewer/Assets/tape.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/tape.riv
--------------------------------------------------------------------------------
/samples/Viewer/Assets/runner.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/runner.riv
--------------------------------------------------------------------------------
/samples/Viewer/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "submodules/rive-cpp"]
2 | path = submodules/rive-cpp
3 | url = https://github.com/rive-app/rive-cpp.git
4 |
--------------------------------------------------------------------------------
/samples/Viewer/Assets/switch_event_example.riv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/switch_event_example.riv
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/samples/Viewer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/Viewer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rive-app/rive-sharp/HEAD/samples/StateMachineInputs/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/samples/Viewer/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Goldens/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "Goldens": {
4 | "commandName": "Project",
5 | "commandLineArgs": "--rivs ..\\..\\gold\\rivs --destination candidates\\ --verbose true",
6 | "workingDirectory": "$(SolutionDir)",
7 | "nativeDebugging": true
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/RiveSharp/RiveSharp.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/samples/Viewer/Viewer.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 |
6 |
7 | true
8 |
9 |
10 |
--------------------------------------------------------------------------------
/RiveSharp/RiveSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | AnyCPU
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/samples/Viewer/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using Windows.UI.Xaml.Controls;
4 |
5 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
6 |
7 | namespace Viewer
8 | {
9 | ///
10 | /// An empty page that can be used on its own or navigated to within a Frame.
11 | ///
12 | public sealed partial class MainPage : Page
13 | {
14 | public MainPage()
15 | {
16 | this.InitializeComponent();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using Windows.UI.Xaml.Controls;
4 |
5 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
6 |
7 | namespace StateMachineInputs
8 | {
9 | ///
10 | /// An empty page that can be used on its own or navigated to within a Frame.
11 | ///
12 | public sealed partial class MainPage : Page
13 | {
14 | public MainPage()
15 | {
16 | this.InitializeComponent();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/samples/Viewer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Viewer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Rive")]
12 | [assembly: AssemblyProduct("Viewer")]
13 | [assembly: AssemblyCopyright("Copyright © Rive 2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
30 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("RiveSharp.Views.UWP")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Rive")]
12 | [assembly: AssemblyProduct("RiveSharp.Views.UWP")]
13 | [assembly: AssemblyCopyright("Copyright © Rive 2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
30 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("StateMachineInputCollection")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Rive")]
12 | [assembly: AssemblyProduct("StateMachineInputCollection")]
13 | [assembly: AssemblyCopyright("Copyright © Rive 2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
30 |
--------------------------------------------------------------------------------
/samples/Viewer/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/samples/Viewer/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Goldens/Goldens.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 | True
12 |
13 |
14 |
15 | True
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | PreserveNewest
29 | rive.dll
30 |
31 |
32 | PreserveNewest
33 | rive.pdb
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | CONTENTS OF THIS FILE
2 | ---------------------
3 |
4 | * Introduction
5 | * Building
6 |
7 | INTRODUCTION
8 | ------------
9 |
10 | RiveSharpSample.sln contains the Rive C# runtime, along with examples on how
11 | to use it:
12 |
13 | Viewer.csproj: A simple UWP app that draws 4 .riv files with pointer events.
14 |
15 | StateMachineInputs.csproj: A simple UWP app that draws a remote .riv file and
16 | data binds state machine inputs to XAML controls.
17 |
18 | Goldens.csproj: A console app that renders images for testing
19 |
20 | BUILDING
21 | ------------
22 |
23 | ==== In the public "rive-sharp" repo ====
24 |
25 | You just need to fetch the rive-cpp submodule:
26 |
27 | git submodule update --init
28 |
29 | After that, you should be able to open RiveSharpSample.sln in Visual Studio 2022
30 | community, build, and run!
31 |
32 | Rive is constantly making use of the latest clang features, so please only use the LLVM Platform Toolset and ensure your Visual Studio is up to date with the latest version.
33 |
34 | ==== In the internal "rive" repo ====
35 |
36 | To build, you first need to generate rive.vcproj, the project that builds the
37 | native rive.dll:
38 |
39 | cd Native
40 | premake5.exe vs2022
41 |
42 | Once rive.vcproj is generated, you should be able to open RiveSharpSample.sln in
43 | Visual Studio 2022 community, build, and run!
44 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/RiveSharp/RiveSharp.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Rive.RiveSharp
5 | $version$
6 | RiveSharp
7 | Rive
8 | false
9 | MIT
10 |
11 | https://rive.app
12 | Low level runtime API for playing Rive animations
13 | Initial alpha release
14 | Copyright 2022
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/native/premake5_wasm.lua:
--------------------------------------------------------------------------------
1 | workspace('rive-cpp')
2 |
3 | configurations({ 'Release' })
4 |
5 | -- Are we in the "rive-sharp" or "rive" repository?
6 | local git_handle = io.popen('git remote -v')
7 | local git_remote = git_handle:read('*a')
8 | git_handle:close()
9 | if string.find(git_remote, 'rive%-sharp') then
10 | -- In rive-sharp. Rive runtime is a submodule.
11 | RIVE_RUNTIME_DIR = '../submodules/rive-cpp'
12 | else
13 | -- In rive. Rive runtime is further up the tree.
14 | RIVE_RUNTIME_DIR = '../../runtime'
15 | end
16 |
17 | local emcc_handle = io.popen(
18 | 'emcc --version | grep ^emcc | sed \'s/^.*\\([0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\\).*$/\\1/\''
19 | )
20 | local emcc_version = emcc_handle:read('*a'):gsub('%s+', '')
21 | emcc_handle:close()
22 | TARGET_DIR = 'bin/emsdk/' .. emcc_version
23 | print('TARGET_DIR: ' .. TARGET_DIR)
24 |
25 | project('rive')
26 | do
27 | kind('StaticLib')
28 | language('C++')
29 | cppdialect('C++17')
30 | targetdir(TARGET_DIR)
31 | objdir('obj/wasm')
32 | optimize('Size')
33 | flags({ 'FatalCompileWarnings' })
34 | includedirs({ RIVE_RUNTIME_DIR .. '/include', '../../include' })
35 | files({ RIVE_RUNTIME_DIR .. '/src/**.cpp', 'RiveSharpInterop.cpp' })
36 | defines({ 'RELEASE', 'NDEBUG', 'WASM' })
37 | filter('options:not no-exceptions')
38 | do
39 | -- WebAssembly Exceptions support is now required by Uno.
40 | buildoptions({ '-fwasm-exceptions' })
41 | end
42 | end
43 |
44 | newoption({
45 | trigger = 'no-exceptions',
46 | description = 'build without -fwasm-exceptions',
47 | })
48 |
--------------------------------------------------------------------------------
/native/premake5.lua:
--------------------------------------------------------------------------------
1 | workspace('rive-cpp')
2 |
3 | configurations({ 'Debug', 'Release' })
4 | platforms({ 'x64', 'x86', 'ARM64', 'ARM' })
5 |
6 | -- Are we in the "rive-sharp" or "rive" repository?
7 | local handle = io.popen('git remote -v')
8 | local git_remote = handle:read('*a')
9 | handle:close()
10 | if string.find(git_remote, 'rive%-sharp') then
11 | -- In rive-sharp. Rive runtime is a submodule.
12 | RIVE_RUNTIME_DIR = '../submodules/rive-cpp'
13 | else
14 | -- In rive. Rive runtime is further up the tree.
15 | RIVE_RUNTIME_DIR = '../../runtime'
16 | end
17 |
18 | project('rive')
19 | kind('SharedLib')
20 | language('C++')
21 | cppdialect('C++17')
22 | targetdir('bin/%{cfg.platform}/%{cfg.buildcfg}')
23 | objdir('obj/%{cfg.platform}/%{cfg.buildcfg}')
24 | staticruntime('off') -- /MD for dll
25 | flags({ 'FatalCompileWarnings' })
26 | includedirs({ RIVE_RUNTIME_DIR .. '/include', '../../include' })
27 | files({ RIVE_RUNTIME_DIR .. '/src/**.cpp', 'RiveSharpInterop.cpp' })
28 | -- this is building the actual rive library so it seems we need this here.
29 | defines({ '_RIVE_INTERNAL_' })
30 |
31 | filter('configurations:Debug')
32 | defines({ 'DEBUG' })
33 | symbols('On')
34 |
35 | filter('configurations:Release')
36 | defines({ 'RELEASE' })
37 | defines({ 'NDEBUG' })
38 | optimize('Size')
39 |
40 | filter('platforms:x64')
41 | architecture('x64')
42 | toolset('clang')
43 |
44 | filter('platforms:x86')
45 | architecture('x86')
46 | toolset('clang')
47 |
48 | filter('platforms:ARM64')
49 | architecture('ARM64')
50 | toolset('clang')
51 |
52 | filter('platforms:ARM')
53 | architecture('ARM')
54 | toolset('msc') -- clang isn't supported on ARM32
55 |
56 | filter({})
57 |
--------------------------------------------------------------------------------
/RiveSharp/RenderImage.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using SkiaSharp;
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace RiveSharp
8 | {
9 | public class RenderImage
10 | {
11 | static readonly RenderImageDelegates Delegates = new RenderImageDelegates
12 | {
13 | Release = RiveAPI.ReleaseNativeRefCallback,
14 | Width = WidthCallback,
15 | Height = HeightCallback
16 | };
17 |
18 | static RenderImage()
19 | {
20 | RiveAPI.RenderImage_RegisterDelegates(Delegates);
21 | }
22 |
23 | public readonly SKImage SKImage;
24 |
25 | public static RenderImage Decode(byte[] data)
26 | {
27 | var skimage = SKImage.FromEncodedData(data);
28 | return skimage != null ? new RenderImage(skimage) : null;
29 | }
30 |
31 | private RenderImage(SKImage skimage)
32 | {
33 | SKImage = skimage;
34 | }
35 |
36 | public int Width => SKImage.Width;
37 | public int Height => SKImage.Height;
38 |
39 | [MonoPInvokeCallback(typeof(RenderImageDelegates.WidthHeightDelegate))]
40 | static Int32 WidthCallback(IntPtr @ref)
41 | {
42 | var renderImage = RiveAPI.CastNativeRef(@ref);
43 | return renderImage.Width;
44 | }
45 |
46 | [MonoPInvokeCallback(typeof(RenderImageDelegates.WidthHeightDelegate))]
47 | static Int32 HeightCallback(IntPtr @ref)
48 | {
49 | var renderImage = RiveAPI.CastNativeRef(@ref);
50 | return renderImage.Height;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/Properties/RiveSharp.Views.UWP.rd.xml:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/samples/Viewer/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | Viewer
18 | csmartdalton
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | StateMachineInputs
18 | csmartdalton
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/RiveSharp/create_nupkg.sh:
--------------------------------------------------------------------------------
1 | VERSION=${1:-"1.0.0"}
2 |
3 | if ! command -v msbuild.exe &> /dev/null
4 | then
5 | echo
6 | echo Put msbuild.exe on your \$PATH!
7 | exit -1
8 | fi
9 |
10 | if ! command -v emcc &> /dev/null
11 | then
12 | echo
13 | echo Set up your emscripten environment!
14 | exit -1
15 | fi
16 |
17 | if ! command -v nuget.exe &> /dev/null
18 | then
19 | echo
20 | echo Put nuget.exe on your \$PATH!
21 | exit -1
22 | fi
23 |
24 | pushd ../native
25 |
26 | # Build native dlls.
27 | premake5.exe --scripts=../../runtime/build vs2022
28 | msbuild.exe rive.vcxproj -p:Configuration=Release -p:Platform=x64 -p:UseMultiToolTask=true -p:EnforceProcessCountAcrossBuilds=true -m:10
29 | msbuild.exe rive.vcxproj -p:Configuration=Release -p:Platform=x86 -p:UseMultiToolTask=true -p:EnforceProcessCountAcrossBuilds=true -m:10
30 | msbuild.exe rive.vcxproj -p:Configuration=Release -p:Platform=ARM64 -p:UseMultiToolTask=true -p:EnforceProcessCountAcrossBuilds=true -m:10
31 | msbuild.exe rive.vcxproj -p:Configuration=Release -p:Platform=ARM -p:UseMultiToolTask=true -p:EnforceProcessCountAcrossBuilds=true -m:10
32 |
33 | # Build the wasm library with emsdk 2.0.23 (for Uno.Wasm.Bootstrap 3.x).
34 | emsdk install 2.0.23
35 | emsdk activate 2.0.23
36 | premake5.exe --scripts=../../runtime/build --file=premake5_wasm.lua --no-exceptions cmake
37 | emcmake cmake .
38 | cmake --build . -j10
39 |
40 | # Build the wasm library with emsdk 3.1.12 (for Uno.Wasm.Bootstrap 7.x).
41 | emsdk install 3.1.12
42 | emsdk activate 3.1.12
43 | premake5.exe --scripts=../../runtime/build --file=premake5_wasm.lua cmake
44 | emcmake cmake .
45 | cmake --build . -j10
46 |
47 | popd
48 |
49 | #Pack!
50 | nuget.exe restore RiveSharp.csproj
51 | nuget.exe pack RiveSharp.csproj \
52 | -Build \
53 | -Properties Configuration=Release \
54 | -Properties version="$VERSION-alpha.$(git rev-parse --short HEAD)"
55 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/StateMachineInputCollection.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using Windows.Foundation.Collections;
5 | using Windows.UI.Xaml;
6 |
7 | namespace RiveSharp.Views
8 | {
9 | // Manages a collection of StateMachineInput objects for RivePlayer. The [ContentProperty] tag
10 | // on RivePlayer instructs the XAML engine automatically route nested inputs through this
11 | // collection:
12 | //
13 | //
14 | //
15 | //
16 | //
17 | public class StateMachineInputCollection : DependencyObjectCollection
18 | {
19 | private readonly WeakReference rivePlayer;
20 |
21 | public StateMachineInputCollection(RivePlayer rivePlayer)
22 | {
23 | this.rivePlayer = new WeakReference(rivePlayer);
24 | VectorChanged += InputsVectorChanged;
25 | }
26 |
27 | private void InputsVectorChanged(IObservableVector sender,
28 | IVectorChangedEventArgs @event)
29 | {
30 | switch (@event.CollectionChange)
31 | {
32 | case CollectionChange.ItemInserted:
33 | case CollectionChange.ItemChanged:
34 | {
35 | var input = (StateMachineInput)sender[(int)@event.Index];
36 | input.SetRivePlayer(rivePlayer);
37 | }
38 | break;
39 | case CollectionChange.ItemRemoved:
40 | {
41 | var input = (StateMachineInput)sender[(int)@event.Index];
42 | input.SetRivePlayer(new WeakReference(null));
43 | break;
44 | }
45 | case CollectionChange.Reset:
46 | foreach (StateMachineInput input in sender)
47 | {
48 | input.SetRivePlayer(new WeakReference(null));
49 | }
50 | break;
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/RiveSharp/2D.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace RiveSharp
7 | {
8 | [StructLayout(LayoutKind.Sequential)]
9 | public struct AABB
10 | {
11 | public float MinX, MinY, MaxX, MaxY;
12 |
13 | public AABB(float minX, float minY, float maxX, float maxY)
14 | {
15 | MinX = minX;
16 | MinY = minY;
17 | MaxX = maxX;
18 | MaxY = maxY;
19 | }
20 | }
21 |
22 | [StructLayout(LayoutKind.Sequential)]
23 | public struct Vec2D
24 | {
25 | public float X, Y;
26 |
27 | public Vec2D(float x, float y)
28 | {
29 | X = x;
30 | Y = y;
31 | }
32 | }
33 |
34 | [StructLayout(LayoutKind.Sequential)]
35 | public struct Mat2D
36 | {
37 | public float X1, Y1, X2, Y2, Tx, Ty;
38 |
39 | public static Mat2D Identity { get { return new Mat2D(1, 0, 0, 1, 0, 0); } }
40 |
41 | public static Mat2D FromTranslate(float x, float y)
42 | {
43 | return new Mat2D(1, 0, 0, 1, x, y);
44 | }
45 |
46 | public static Mat2D FromScale(float sx, float sy)
47 | {
48 | return new Mat2D(sx, 0, 0, sy, 0, 0);
49 | }
50 |
51 | public static Mat2D FromRotation(float radians)
52 | {
53 | float sin = (float)Math.Sin(radians);
54 | float cos = (float)Math.Cos(radians);
55 | return new Mat2D(cos, sin, -sin, cos, 0, 0);
56 | }
57 |
58 | public Mat2D(float x1, float y1, float x2, float y2, float tx, float ty)
59 | {
60 | this.X1 = x1;
61 | this.Y1 = y1;
62 | this.X2 = x2;
63 | this.Y2 = y2;
64 | this.Tx = tx;
65 | this.Ty = ty;
66 | }
67 |
68 | public static unsafe Mat2D operator *(Mat2D a, Mat2D b)
69 | {
70 | var product = new Mat2D();
71 | RiveAPI.Mat2D_Multiply(a, b, &product);
72 | return product;
73 | }
74 |
75 | public static unsafe Vec2D operator *(Mat2D a, Vec2D b)
76 | {
77 | var product = new Vec2D();
78 | RiveAPI.Mat2D_MultiplyVec2D(a, b, &product);
79 | return product;
80 | }
81 |
82 | public unsafe bool Invert(out Mat2D inverse)
83 | {
84 | var result = new Mat2D();
85 | if (RiveAPI.Mat2D_Invert(this, &result) != 0)
86 | {
87 | inverse = result;
88 | return true;
89 | }
90 | else
91 | {
92 | inverse = Mat2D.Identity;
93 | return false;
94 | }
95 | }
96 |
97 | public Mat2D InvertOrIdentity()
98 | {
99 | return Invert(out Mat2D inverse) ? inverse : Mat2D.Identity;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/RiveSharp/Factory.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using SkiaSharp;
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace RiveSharp
8 | {
9 | public class Factory
10 | {
11 | static readonly FactoryDelegates Delegates = new FactoryDelegates
12 | {
13 | Release = RiveAPI.ReleaseNativeRefCallback,
14 | MakeRenderPath = MakeRenderPathCallback,
15 | MakeEmptyRenderPath = MakeEmptyRenderPathCallback,
16 | MakeRenderPaint = MakeRenderPaintCallback,
17 | DecodeImage = DecodeImageCallback
18 | };
19 |
20 | static Factory()
21 | {
22 | RiveAPI.Factory_RegisterDelegates(Delegates);
23 | }
24 |
25 | public static readonly Factory Instance = new Factory();
26 | private Factory() { }
27 |
28 | RenderPath MakeRenderPath(SKPoint[] pts, byte[] verbs, FillRule fillRule)
29 | {
30 | return new RenderPath(pts, verbs, fillRule);
31 | }
32 |
33 | RenderPath MakeEmptyRenderPath()
34 | {
35 | return new RenderPath();
36 | }
37 |
38 | RenderPaint MakeRenderPaint()
39 | {
40 | return new RenderPaint();
41 | }
42 |
43 | RenderImage DecodeImage(byte[] data)
44 | {
45 | return RenderImage.Decode(data);
46 | }
47 |
48 | [MonoPInvokeCallback(typeof(FactoryDelegates.MakeRenderPathDelegate))]
49 | static IntPtr MakeRenderPathCallback(IntPtr @ref,
50 | IntPtr ptsArray, // SKPoint[nPts]
51 | int nPts,
52 | IntPtr verbsArray, // byte[nVerbs]
53 | int nVerbs,
54 | int fillRule)
55 | {
56 | var factory = RiveAPI.CastNativeRef(@ref);
57 | var pts = new SKPoint[nPts];
58 | RiveAPI.CopySKPointArray(ptsArray, pts, nPts);
59 | var verbs = new byte[nVerbs];
60 | Marshal.Copy(verbsArray, verbs, 0, nVerbs);
61 | return RiveAPI.CreateNativeRef(factory.MakeRenderPath(pts, verbs, (FillRule)fillRule));
62 | }
63 |
64 | [MonoPInvokeCallback(typeof(FactoryDelegates.MakeEmptyObjectDelegate))]
65 | static IntPtr MakeEmptyRenderPathCallback(IntPtr @ref)
66 | {
67 | var factory = RiveAPI.CastNativeRef(@ref);
68 | return RiveAPI.CreateNativeRef(factory.MakeEmptyRenderPath());
69 | }
70 |
71 | [MonoPInvokeCallback(typeof(FactoryDelegates.MakeEmptyObjectDelegate))]
72 | static IntPtr MakeRenderPaintCallback(IntPtr @ref)
73 | {
74 | var factory = RiveAPI.CastNativeRef(@ref);
75 | return RiveAPI.CreateNativeRef(factory.MakeRenderPaint());
76 | }
77 |
78 | [MonoPInvokeCallback(typeof(FactoryDelegates.DecodeImageDelegate))]
79 | static IntPtr DecodeImageCallback(IntPtr @ref, IntPtr bytesArray, int nBytes)
80 | {
81 | var factory = RiveAPI.CastNativeRef(@ref);
82 | var bytes = new byte[nBytes];
83 | Marshal.Copy(bytesArray, bytes, 0, nBytes);
84 | var image = factory.DecodeImage(bytes);
85 | return (IntPtr)(image != null ? RiveAPI.CreateNativeRef(image)
86 | : IntPtr.Zero);
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Goldens/Goldens.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using Microsoft.Extensions.Configuration;
4 | using RiveSharp;
5 | using SkiaSharp;
6 |
7 | namespace Goldens;
8 |
9 | internal class Goldens
10 | {
11 | const int CELL = 256;
12 | const int W = 5;
13 | const int H = 5;
14 | const int GAP = 2;
15 | const int SW = W * CELL + (W + 1) * GAP;
16 | const int SH = H * CELL + (H + 1) * GAP;
17 |
18 | static int Main(string[] commandLineArgs)
19 | {
20 | var args = new ConfigurationBuilder().AddCommandLine(commandLineArgs).Build();
21 | string rivs = args["rivs"];
22 | string destination = args["destination"];
23 | bool verbose = args["verbose"] == "true";
24 | var skImageInfo = new SKImageInfo(SW, SH, SKColorType.Rgba8888, SKAlphaType.Premul);
25 |
26 | var rivFiles = Directory.GetFiles(rivs);
27 | Console.WriteLine($"Rendering {rivFiles.Length} pngs...");
28 | foreach (string riv in rivFiles)
29 | {
30 | // Load the animation.
31 | if (riv.Contains("Centaur_v2.riv") || riv.Contains("Planet_clean.riv"))
32 | {
33 | continue; // https://github.com/rive-app/rive-cpp/issues/334
34 | }
35 | if (riv.Contains("paper.riv"))
36 | {
37 | continue; // https://github.com/rive-app/rive/issues/4573
38 | }
39 |
40 | if (verbose)
41 | {
42 | Console.Write($"Loading {riv}...\n");
43 | }
44 |
45 | var fileStream = File.OpenRead(riv);
46 | if (fileStream == null)
47 | {
48 | Console.WriteLine($"ERROR: failed to open file '{riv}'");
49 | return -1;
50 | }
51 | var scene = new Scene();
52 | if (!scene.LoadFile(fileStream) || !scene.LoadArtboard("") || !scene.LoadAnimation(""))
53 | {
54 | Console.WriteLine($"ERROR: failed to load .riv animation '{riv}'");
55 | return -1;
56 | }
57 | if (verbose)
58 | {
59 | Console.WriteLine($"Loaded scene \"{scene.Name}\"");
60 | }
61 |
62 | // Render the grid.
63 | var surface = SKSurface.Create(skImageInfo);
64 | var canvas = surface.Canvas;
65 | canvas.Clear(SKColors.White);
66 |
67 | const int FRAMES = H * W;
68 | double duration = scene.DurationSeconds;
69 | double frameDuration = duration / FRAMES;
70 |
71 | scene.AdvanceAndApply(0);
72 |
73 | var renderer = new Renderer(canvas);
74 | renderer.Translate(GAP, GAP);
75 | renderer.Save();
76 | for (int y = 0; y < H; ++y)
77 | {
78 | for (int x = 0; x < W; ++x)
79 | {
80 | renderer.Save();
81 |
82 | renderer.Translate(x * (CELL + GAP), y * (CELL + GAP));
83 | renderer.Align(Fit.Cover, Alignment.Center,
84 | new AABB(0, 0, CELL, CELL),
85 | new AABB(0, 0, scene.Width, scene.Height));
86 | scene.Draw(renderer);
87 |
88 | scene.AdvanceAndApply(frameDuration);
89 |
90 | renderer.Restore();
91 | }
92 | }
93 | renderer.Restore();
94 |
95 | // Save out a png.
96 | canvas.Flush();
97 | var pngData = surface.Snapshot().Encode(SKEncodedImageFormat.Png, quality:100);
98 | Directory.CreateDirectory(destination);
99 | string png = Path.Combine(destination, Path.GetFileNameWithoutExtension(riv) + ".png");
100 | File.WriteAllBytes(png, pngData.Span.ToArray());
101 |
102 | if (verbose)
103 | {
104 | Console.WriteLine($"Wrote {png}\n");
105 | }
106 | }
107 |
108 | return 0;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/samples/Viewer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace Viewer
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 | Frame rootFrame = Window.Current.Content as Frame;
43 |
44 | // Do not repeat app initialization when the Window already has content,
45 | // just ensure that the window is active
46 | if (rootFrame == null)
47 | {
48 | // Create a Frame to act as the navigation context and navigate to the first page
49 | rootFrame = new Frame();
50 |
51 | rootFrame.NavigationFailed += OnNavigationFailed;
52 |
53 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
54 | {
55 | //TODO: Load state from previously suspended application
56 | }
57 |
58 | // Place the frame in the current Window
59 | Window.Current.Content = rootFrame;
60 | }
61 |
62 | if (e.PrelaunchActivated == false)
63 | {
64 | if (rootFrame.Content == null)
65 | {
66 | // When the navigation stack isn't restored navigate to the first page,
67 | // configuring the new page by passing required information as a navigation
68 | // parameter
69 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
70 | }
71 | // Ensure the current window is active
72 | Window.Current.Activate();
73 | }
74 | }
75 |
76 | ///
77 | /// Invoked when Navigation to a certain page fails
78 | ///
79 | /// The Frame which failed navigation
80 | /// Details about the navigation failure
81 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
82 | {
83 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
84 | }
85 |
86 | ///
87 | /// Invoked when application execution is being suspended. Application state is saved
88 | /// without knowing whether the application will be terminated or resumed with the contents
89 | /// of memory still intact.
90 | ///
91 | /// The source of the suspend request.
92 | /// Details about the suspend request.
93 | private void OnSuspending(object sender, SuspendingEventArgs e)
94 | {
95 | var deferral = e.SuspendingOperation.GetDeferral();
96 | //TODO: Save application state and stop any background activity
97 | deferral.Complete();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace StateMachineInputs
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 | Frame rootFrame = Window.Current.Content as Frame;
43 |
44 | // Do not repeat app initialization when the Window already has content,
45 | // just ensure that the window is active
46 | if (rootFrame == null)
47 | {
48 | // Create a Frame to act as the navigation context and navigate to the first page
49 | rootFrame = new Frame();
50 |
51 | rootFrame.NavigationFailed += OnNavigationFailed;
52 |
53 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
54 | {
55 | //TODO: Load state from previously suspended application
56 | }
57 |
58 | // Place the frame in the current Window
59 | Window.Current.Content = rootFrame;
60 | }
61 |
62 | if (e.PrelaunchActivated == false)
63 | {
64 | if (rootFrame.Content == null)
65 | {
66 | // When the navigation stack isn't restored navigate to the first page,
67 | // configuring the new page by passing required information as a navigation
68 | // parameter
69 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
70 | }
71 | // Ensure the current window is active
72 | Window.Current.Activate();
73 | }
74 | }
75 |
76 | ///
77 | /// Invoked when Navigation to a certain page fails
78 | ///
79 | /// The Frame which failed navigation
80 | /// Details about the navigation failure
81 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
82 | {
83 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
84 | }
85 |
86 | ///
87 | /// Invoked when application execution is being suspended. Application state is saved
88 | /// without knowing whether the application will be terminated or resumed with the contents
89 | /// of memory still intact.
90 | ///
91 | /// The source of the suspend request.
92 | /// Details about the suspend request.
93 | private void OnSuspending(object sender, SuspendingEventArgs e)
94 | {
95 | var deferral = e.SuspendingOperation.GetDeferral();
96 | //TODO: Save application state and stop any background activity
97 | deferral.Complete();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/StateMachineInput.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using Windows.UI.Xaml;
5 | using Windows.UI.Xaml.Markup;
6 |
7 | namespace RiveSharp.Views
8 | {
9 | // This base class wraps a custom, named state machine input value.
10 | public abstract class StateMachineInput : DependencyObject
11 | {
12 | private string _target;
13 | public string Target
14 | {
15 | get => _target; // Must be null-checked before use.
16 | set
17 | {
18 | _target = value;
19 | Apply();
20 | }
21 | }
22 |
23 | private WeakReference _rivePlayer = new WeakReference(null);
24 | protected WeakReference RivePlayer => _rivePlayer;
25 |
26 | // Sets _rivePlayer to the given rivePlayer object and applies our input value to the state
27 | // machine. Does nothing if _rivePlayer was already equal to rivePlayer.
28 | internal void SetRivePlayer(WeakReference rivePlayer)
29 | {
30 | _rivePlayer = rivePlayer;
31 | Apply();
32 | }
33 |
34 | protected void Apply()
35 | {
36 | if (!String.IsNullOrEmpty(_target) && _rivePlayer.TryGetTarget(out var rivePlayer))
37 | {
38 | Apply(rivePlayer, _target);
39 | }
40 | }
41 |
42 | // Applies our input value to the rivePlayer's state machine.
43 | // rivePlayer and inputName are guaranteed to not be null or empty.
44 | protected abstract void Apply(RivePlayer rivePlayer, string inputName);
45 | }
46 |
47 | [ContentProperty(Name = nameof(Value))]
48 | public class BoolInput : StateMachineInput
49 | {
50 | // Define "Value" as a DependencyProperty so it can be data-bound.
51 | public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
52 | nameof(Value),
53 | typeof(bool),
54 | typeof(BoolInput),
55 | new PropertyMetadata(false, new PropertyChangedCallback(OnValueChanged))
56 | );
57 |
58 | public bool Value
59 | {
60 | get => (bool)GetValue(ValueProperty);
61 | set => SetValue(ValueProperty, value);
62 | }
63 |
64 | private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
65 | {
66 | ((BoolInput)d).Apply();
67 | }
68 |
69 | protected override void Apply(RivePlayer rivePlayer, string inputName)
70 | {
71 | rivePlayer.SetBool(inputName, this.Value);
72 | }
73 | }
74 |
75 | [ContentProperty(Name = nameof(Value))]
76 | public class NumberInput : StateMachineInput
77 | {
78 | // Define "Value" as a DependencyProperty so it can be data-bound.
79 | private static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
80 | nameof(Value),
81 | typeof(double),
82 | typeof(NumberInput),
83 | new PropertyMetadata(0.0, new PropertyChangedCallback(OnValueChanged))
84 | );
85 |
86 | public double Value
87 | {
88 | get => (double)GetValue(ValueProperty);
89 | set => SetValue(ValueProperty, value);
90 | }
91 |
92 | private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
93 | {
94 | ((NumberInput)d).Apply();
95 | }
96 |
97 | protected override void Apply(RivePlayer rivePlayer, string inputName)
98 | {
99 | rivePlayer.SetNumber(inputName, (float)this.Value);
100 | }
101 | }
102 |
103 | public class TriggerInput : StateMachineInput
104 | {
105 | public void Fire()
106 | {
107 | if (!String.IsNullOrEmpty(this.Target) && this.RivePlayer.TryGetTarget(out var rivePlayer))
108 | {
109 | rivePlayer.FireTrigger(this.Target);
110 | }
111 | }
112 |
113 | // Make a Fire() overload that matches the RoutedEventHandler delegate.
114 | // This allows us do to things like
115 | public void Fire(object s, RoutedEventArgs e) => Fire();
116 |
117 | // Triggers don't have any persistent data to apply.
118 | protected override void Apply(RivePlayer rivePlayer, string inputName) { }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/RiveSharp/Scene.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace RiveSharp
8 | {
9 | public enum Loop
10 | {
11 | // Play until the duration or end of work area of the animation.
12 | OneShot = 0,
13 |
14 | // Play until the duration or end of work area of the animation and then go back to the
15 | // start (0 seconds).
16 | Loop = 1,
17 |
18 | // Play to the end of the duration/work area and then play back.
19 | PingPong = 2
20 | };
21 |
22 | public class Scene
23 | {
24 | public readonly IntPtr NativePtr;
25 |
26 | public Scene()
27 | {
28 | NativePtr = RiveAPI.Scene_New(RiveAPI.CreateNativeRef(Factory.Instance));
29 | }
30 | ~Scene()
31 | {
32 | RiveAPI.Scene_Delete(NativePtr);
33 | }
34 |
35 | private bool _isLoaded = false;
36 | public bool IsLoaded => _isLoaded;
37 |
38 | public bool LoadFile(Stream stream)
39 | {
40 | var data = new byte[stream.Length];
41 | stream.Read(data, 0, data.Length);
42 | return LoadFile(data);
43 | }
44 |
45 | public bool LoadFile(byte[] data)
46 | {
47 | _isLoaded = false;
48 | if (data == null || data.Length == 0)
49 | {
50 | return false;
51 | }
52 | return RiveAPI.Scene_LoadFile(NativePtr, data, data.Length) != 0;
53 | }
54 |
55 | // Loads an artboard and animation from the already-loaded file.
56 | public bool LoadArtboard(string artboardName)
57 | {
58 | _isLoaded = false;
59 | return RiveAPI.Scene_LoadArtboard(NativePtr, artboardName) != 0;
60 | }
61 |
62 | // Loads a state machine from the already-loaded artboard and file.
63 | public bool LoadStateMachine(string stateMachineName)
64 | {
65 | _isLoaded = RiveAPI.Scene_LoadStateMachine(NativePtr, stateMachineName) != 0;
66 | return this.IsLoaded;
67 | }
68 |
69 | // Loads an animation from the already-loaded artboard and file.
70 | public bool LoadAnimation(string animationName)
71 | {
72 | _isLoaded = RiveAPI.Scene_LoadAnimation(NativePtr, animationName) != 0;
73 | return this.IsLoaded;
74 | }
75 |
76 | public void SetBool(string name, bool value)
77 | {
78 | if (this.IsLoaded && RiveAPI.Scene_SetBool(NativePtr, name, value ? 1 : 0) == 0)
79 | {
80 | throw new Exception($"State machine bool input '{name}' not found.");
81 | }
82 | }
83 |
84 | public void SetNumber(string name, float value)
85 | {
86 | if (this.IsLoaded && RiveAPI.Scene_SetNumber(NativePtr, name, value) == 0)
87 | {
88 | throw new Exception($"State machine number input '{name}' not found.");
89 | }
90 | }
91 |
92 | public void FireTrigger(string name)
93 | {
94 | if (this.IsLoaded && RiveAPI.Scene_FireTrigger(NativePtr, name) == 0)
95 | {
96 | throw new Exception($"State machine trigger input '{name}' not found.");
97 | }
98 | }
99 |
100 | public float Width => RiveAPI.Scene_Width(NativePtr);
101 | public float Height => RiveAPI.Scene_Height(NativePtr);
102 |
103 | public string Name
104 | {
105 | get
106 | {
107 | int numChars = RiveAPI.Scene_Name(NativePtr, null);
108 | if (numChars > 1)
109 | {
110 | char[] charArray = new char[numChars];
111 | RiveAPI.Scene_Name(NativePtr, charArray);
112 | return new string(charArray);
113 | }
114 | return "";
115 | }
116 | }
117 |
118 | // Returns OneShot if this has no looping (e.g. a statemachine)
119 | public Loop Loop => (Loop)RiveAPI.Scene_Loop(NativePtr);
120 |
121 | // Returns true iff the Scene is known to not be fully opaque
122 | public bool IsTranslucent => RiveAPI.Scene_IsTranslucent(NativePtr) != 0;
123 |
124 | // returns -1 for continuous
125 | public double DurationSeconds => RiveAPI.Scene_DurationSeconds(NativePtr);
126 |
127 | // returns true if Draw() should be called
128 | public bool AdvanceAndApply(double elapsedSeconds)
129 | {
130 | return RiveAPI.Scene_AdvanceAndApply(NativePtr, (float)elapsedSeconds) != 0;
131 | }
132 |
133 | public void Draw(Renderer renderer)
134 | {
135 | var gch = GCHandle.Alloc(renderer);
136 | RiveAPI.Scene_Draw(NativePtr, GCHandle.ToIntPtr(gch));
137 | gch.Free();
138 | }
139 |
140 | public void PointerDown(Vec2D pos) => RiveAPI.Scene_PointerDown(NativePtr, pos);
141 | public void PointerMove(Vec2D pos) => RiveAPI.Scene_PointerMove(NativePtr, pos);
142 | public void PointerUp(Vec2D pos) => RiveAPI.Scene_PointerUp(NativePtr, pos);
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/RivePlayer.Properties.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Threading;
6 | using Windows.UI.Xaml;
7 | using Windows.UI.Xaml.Markup;
8 |
9 | namespace RiveSharp.Views
10 | {
11 | // XAML properies for RivePlayer.
12 | [ContentProperty(Name = nameof(StateMachineInputs))]
13 | public partial class RivePlayer
14 | {
15 | // Filename of the .riv file to open. Can be a file path or a URL.
16 | public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
17 | nameof(Source),
18 | typeof(string),
19 | typeof(RivePlayer),
20 | new PropertyMetadata(null, OnSourceNameChanged)
21 | );
22 |
23 | public string Source
24 | {
25 | get => (string)GetValue(SourceProperty);
26 | set => SetValue(SourceProperty, value);
27 | }
28 |
29 | // Name of the artbord to load from the .riv file. If null or empty, the default artboard
30 | // will be loaded.
31 | public static readonly DependencyProperty ArtboardProperty = DependencyProperty.Register(
32 | nameof(Artboard),
33 | typeof(string),
34 | typeof(RivePlayer),
35 | new PropertyMetadata(null, OnArtboardNameChanged)
36 | );
37 |
38 | public string Artboard
39 | {
40 | get => (string)GetValue(ArtboardProperty);
41 | set => SetValue(ArtboardProperty, value);
42 | }
43 |
44 | // Name of the state machine to load from the .riv file.
45 | public static readonly DependencyProperty StateMachineProperty = DependencyProperty.Register(
46 | nameof(StateMachine),
47 | typeof(string),
48 | typeof(RivePlayer),
49 | new PropertyMetadata(null, OnStateMachineNameChanged)
50 | );
51 |
52 | public string StateMachine
53 | {
54 | get => (string)GetValue(StateMachineProperty);
55 | set => SetValue(StateMachineProperty, value);
56 | }
57 |
58 | // Name of the fallback animation to load from the .riv if StateMachine is null or empty.
59 | public static readonly DependencyProperty AnimationProperty = DependencyProperty.Register(
60 | nameof(Animation),
61 | typeof(string),
62 | typeof(RivePlayer),
63 | new PropertyMetadata(null, OnAnimationNameChanged)
64 | );
65 |
66 | public string Animation
67 | {
68 | get => (string)GetValue(AnimationProperty);
69 | set => SetValue(AnimationProperty, value);
70 | }
71 |
72 | public static readonly DependencyProperty StateMachineInputsProperty = DependencyProperty.Register(
73 | nameof(StateMachineInputs),
74 | typeof(StateMachineInputCollection),
75 | typeof(RivePlayer),
76 | new PropertyMetadata(null)
77 | );
78 |
79 | public StateMachineInputCollection StateMachineInputs
80 | {
81 | get => (StateMachineInputCollection)GetValue(StateMachineInputsProperty);
82 | set => SetValue(StateMachineInputsProperty, value);
83 | }
84 |
85 | private static void OnSourceNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
86 | {
87 | var player = (RivePlayer)d;
88 | var newSourceName = (string)e.NewValue;
89 | // Clear the current Scene while we wait for the new one to load.
90 | player.sceneActionsQueue.Enqueue(() => player._scene = new Scene());
91 | if (player._activeSourceFileLoader != null)
92 | {
93 | player._activeSourceFileLoader.Cancel();
94 | }
95 |
96 | player._activeSourceFileLoader = new CancellationTokenSource();
97 | // Defer state machine inputs here until the new file is loaded.
98 | player._deferredSMInputsDuringFileLoad = new List();
99 | player.LoadSourceFileDataAsync(newSourceName, player._activeSourceFileLoader.Token);
100 | }
101 |
102 | private static void OnArtboardNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
103 | {
104 | var player = (RivePlayer)d;
105 | var newArtboardName = (string)e.NewValue;
106 | player.sceneActionsQueue.Enqueue(() => player._artboardName = newArtboardName);
107 | if (player._activeSourceFileLoader != null)
108 | {
109 | // If a file is currently loading async, it will apply the new artboard once
110 | // it completes. Loading a new artboard also invalidates any state machine
111 | // inputs that were waiting for the file load.
112 | player._deferredSMInputsDuringFileLoad.Clear();
113 | }
114 | else
115 | {
116 | player.sceneActionsQueue.Enqueue(() => player.UpdateScene(SceneUpdates.Artboard));
117 | }
118 | }
119 |
120 | private static void OnStateMachineNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
121 | {
122 | var player = (RivePlayer)d;
123 | var newStateMachineName = (string)e.NewValue;
124 | player.sceneActionsQueue.Enqueue(() => player._stateMachineName = newStateMachineName);
125 | if (player._activeSourceFileLoader != null)
126 | {
127 | // If a file is currently loading async, it will apply the new state machine
128 | // once it completes. Loading a new state machine also invalidates any state
129 | // machine inputs that were waiting for the file load.
130 | player._deferredSMInputsDuringFileLoad.Clear();
131 | }
132 | else
133 | {
134 | player.sceneActionsQueue.Enqueue(() => player.UpdateScene(SceneUpdates.AnimationOrStateMachine));
135 | }
136 | }
137 |
138 | private static void OnAnimationNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
139 | {
140 | var player = (RivePlayer)d;
141 | var newAnimationName = (string)e.NewValue;
142 | player.sceneActionsQueue.Enqueue(() => player._animationName = newAnimationName);
143 | // If a file is currently loading async, it will apply the new animation once it completes.
144 | if (player._activeSourceFileLoader == null)
145 | {
146 | player.sceneActionsQueue.Enqueue(() => player.UpdateScene(SceneUpdates.AnimationOrStateMachine));
147 | }
148 | }
149 |
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/RiveSharp/RenderPath.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.ComponentModel;
5 | using System.Runtime.InteropServices;
6 | using SkiaSharp;
7 |
8 | namespace RiveSharp
9 | {
10 | public enum FillRule
11 | {
12 | NonZero = 0,
13 | EvenOdd = 1
14 | }
15 |
16 | public class RenderPath
17 | {
18 | static readonly RenderPathDelegates Delegates = new RenderPathDelegates
19 | {
20 | Release = RiveAPI.ReleaseNativeRefCallback,
21 | Reset = ResetCallback,
22 | AddRenderPath = AddRenderPathCallback,
23 | FillRule = FillRuleCallback,
24 | MoveTo = MoveToCallback,
25 | LineTo = LineToCallback,
26 | QuadTo = QuadToCallback,
27 | CubicTo = CubicToCallback,
28 | Close = CloseCallback
29 | };
30 |
31 | static RenderPath()
32 | {
33 | RiveAPI.RenderPath_RegisterDelegates(Delegates);
34 | }
35 |
36 | public readonly SKPath SKPath = new SKPath();
37 |
38 | private static SKPathFillType ToSKPathFillType(FillRule rule)
39 | {
40 | switch (rule)
41 | {
42 | case FillRule.NonZero: return SKPathFillType.Winding;
43 | case FillRule.EvenOdd: return SKPathFillType.EvenOdd;
44 | }
45 | throw new InvalidEnumArgumentException("Invalid FillRule " + rule);
46 | }
47 |
48 | public RenderPath(SKPoint[] pts, byte[] verbs, FillRule fillRule)
49 | {
50 | SKPath.FillType = ToSKPathFillType(fillRule);
51 |
52 | // Unfortuately, SkiaSharp doesn't appear to expose the SkPathBuilder API yet.
53 | int ptsIdx = 0;
54 | foreach (byte v in verbs)
55 | {
56 | switch ((SKPathVerb)v)
57 | {
58 | case SKPathVerb.Move:
59 | SKPath.MoveTo(pts[ptsIdx]);
60 | ptsIdx++;
61 | break;
62 | case SKPathVerb.Line:
63 | SKPath.LineTo(pts[ptsIdx]);
64 | ptsIdx++;
65 | break;
66 | case SKPathVerb.Quad:
67 | SKPath.QuadTo(pts[ptsIdx], pts[ptsIdx + 1]);
68 | ptsIdx += 2;
69 | break;
70 | case SKPathVerb.Cubic:
71 | SKPath.CubicTo(pts[ptsIdx], pts[ptsIdx + 1], pts[ptsIdx + 2]);
72 | ptsIdx += 3;
73 | break;
74 | case SKPathVerb.Close:
75 | SKPath.Close();
76 | break;
77 | default:
78 | throw new Exception("invalid path verb");
79 | }
80 | }
81 | if (ptsIdx != pts.Length)
82 | {
83 | throw new Exception("invalid number of points");
84 | }
85 | }
86 |
87 | public RenderPath() { }
88 |
89 | public void Reset() { SKPath.Reset(); }
90 | public void AddRenderPath(RenderPath path, Mat2D m)
91 | {
92 | var mat = new SKMatrix(m.X1, m.X2, m.Tx, m.Y1, m.Y2, m.Ty, 0, 0, 1);
93 | SKPath.AddPath(path.SKPath, ref mat);
94 | }
95 | public FillRule FillRule { set { SKPath.FillType = ToSKPathFillType(value); } }
96 | public void MoveTo(float x, float y) { SKPath.MoveTo(x, y); }
97 | public void LineTo(float x, float y) { SKPath.LineTo(x, y); }
98 | public void QuadTo(float ox, float oy, float x, float y)
99 | {
100 | SKPath.QuadTo(ox, oy, x, y);
101 | }
102 | public void CubicTo(float ox, float oy, float ix, float iy, float x, float y)
103 | {
104 | SKPath.CubicTo(ox, oy, ix, iy, x, y);
105 | }
106 | public void Close() { SKPath.Close(); }
107 |
108 | [MonoPInvokeCallback(typeof(RenderPathDelegates.ResetDelegate))]
109 | static void ResetCallback(IntPtr @ref)
110 | {
111 | var renderPath = RiveAPI.CastNativeRef(@ref);
112 | renderPath.Reset();
113 | }
114 |
115 | [MonoPInvokeCallback(typeof(RenderPathDelegates.AddRenderPathDelegate))]
116 | static void AddRenderPathCallback(IntPtr @ref,
117 | IntPtr pathRef,
118 | float x1, float y1,
119 | float x2, float y2,
120 | float tx, float ty)
121 | {
122 | var renderPath = RiveAPI.CastNativeRef(@ref);
123 | var path = RiveAPI.CastNativeRef(pathRef);
124 | renderPath.AddRenderPath(path, new Mat2D(x1, y1, x2, y2, tx, ty));
125 | }
126 |
127 | [MonoPInvokeCallback(typeof(RenderPathDelegates.FillRuleDelegate))]
128 | static void FillRuleCallback(IntPtr @ref, int rule)
129 | {
130 | var renderPath = RiveAPI.CastNativeRef(@ref);
131 | renderPath.FillRule = (FillRule)rule;
132 | }
133 |
134 | [MonoPInvokeCallback(typeof(RenderPathDelegates.MoveToDelegate))]
135 | static void MoveToCallback(IntPtr @ref, float x, float y)
136 | {
137 | var renderPath = RiveAPI.CastNativeRef(@ref);
138 | renderPath.MoveTo(x, y);
139 | }
140 |
141 | [MonoPInvokeCallback(typeof(RenderPathDelegates.LineToDelegate))]
142 | static void LineToCallback(IntPtr @ref, float x, float y)
143 | {
144 | var renderPath = RiveAPI.CastNativeRef(@ref);
145 | renderPath.LineTo(x, y);
146 | }
147 |
148 | [MonoPInvokeCallback(typeof(RenderPathDelegates.QuadToDelegate))]
149 | static void QuadToCallback(IntPtr @ref, float ox, float oy, float x, float y)
150 | {
151 | var renderPath = RiveAPI.CastNativeRef(@ref);
152 | renderPath.QuadTo(ox, oy, x, y);
153 | }
154 |
155 | [MonoPInvokeCallback(typeof(RenderPathDelegates.CubicToDelegate))]
156 | static void CubicToCallback(IntPtr @ref, float ox, float oy, float ix, float iy, float x, float y)
157 | {
158 | var renderPath = RiveAPI.CastNativeRef(@ref);
159 | renderPath.CubicTo(ox, oy, ix, iy, x, y);
160 | }
161 |
162 | [MonoPInvokeCallback(typeof(RenderPathDelegates.CloseDelegate))]
163 | static void CloseCallback(IntPtr @ref)
164 | {
165 | var renderPath = RiveAPI.CastNativeRef(@ref);
166 | renderPath.Close();
167 | }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/RiveSharp.Views.UWP.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}
8 | Library
9 | Properties
10 | RiveSharp.Views.UWP
11 | RiveSharp.Views.UWP
12 | en-US
13 | UAP
14 | 10.0.22000.0
15 | 10.0.17763.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 |
20 |
21 | AnyCPU
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
27 | prompt
28 | 4
29 |
30 |
31 | AnyCPU
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | prompt
37 | 4
38 |
39 |
40 | x86
41 | true
42 | bin\x86\Debug\
43 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
44 | ;2008
45 | full
46 | false
47 | prompt
48 |
49 |
50 | x86
51 | bin\x86\Release\
52 | TRACE;NETFX_CORE;WINDOWS_UWP
53 | true
54 | ;2008
55 | pdbonly
56 | false
57 | prompt
58 |
59 |
60 | ARM
61 | true
62 | bin\ARM\Debug\
63 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
64 | ;2008
65 | full
66 | false
67 | prompt
68 |
69 |
70 | ARM
71 | bin\ARM\Release\
72 | TRACE;NETFX_CORE;WINDOWS_UWP
73 | true
74 | ;2008
75 | pdbonly
76 | false
77 | prompt
78 |
79 |
80 | ARM64
81 | true
82 | bin\ARM64\Debug\
83 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
84 | ;2008
85 | full
86 | false
87 | prompt
88 |
89 |
90 | ARM64
91 | bin\ARM64\Release\
92 | TRACE;NETFX_CORE;WINDOWS_UWP
93 | true
94 | ;2008
95 | pdbonly
96 | false
97 | prompt
98 |
99 |
100 | x64
101 | true
102 | bin\x64\Debug\
103 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
104 | ;2008
105 | full
106 | false
107 | prompt
108 |
109 |
110 | x64
111 | bin\x64\Release\
112 | TRACE;NETFX_CORE;WINDOWS_UWP
113 | true
114 | ;2008
115 | pdbonly
116 | false
117 | prompt
118 |
119 |
120 | PackageReference
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | 6.2.14
133 |
134 |
135 | 2.88.1
136 |
137 |
138 |
139 |
140 | {7a1048dc-d6e5-4dbf-b9ea-2321d0ee0c66}
141 | RiveSharp
142 |
143 |
144 |
145 | 14.0
146 |
147 |
148 |
155 |
--------------------------------------------------------------------------------
/samples/StateMachineInputs/StateMachineInputs.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}
8 | AppContainerExe
9 | Properties
10 | StateMachineInputs
11 | StateMachineInputs
12 | en-US
13 | UAP
14 | 10.0.22000.0
15 | 10.0.17763.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | true
20 | false
21 |
22 |
23 | true
24 | bin\x86\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | x86
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\x86\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | x86
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\ARM\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | ARM
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\ARM\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | ARM
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\ARM64\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | ARM64
75 | false
76 | prompt
77 | true
78 | true
79 |
80 |
81 | bin\ARM64\Release\
82 | TRACE;NETFX_CORE;WINDOWS_UWP
83 | true
84 | ;2008
85 | pdbonly
86 | ARM64
87 | false
88 | prompt
89 | true
90 | true
91 |
92 |
93 | true
94 | bin\x64\Debug\
95 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
96 | ;2008
97 | full
98 | x64
99 | false
100 | prompt
101 | true
102 |
103 |
104 | bin\x64\Release\
105 | TRACE;NETFX_CORE;WINDOWS_UWP
106 | true
107 | ;2008
108 | pdbonly
109 | x64
110 | false
111 | prompt
112 | true
113 | true
114 |
115 |
116 | PackageReference
117 |
118 |
119 |
120 | App.xaml
121 |
122 |
123 | MainPage.xaml
124 |
125 |
126 |
127 |
128 |
129 | Designer
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | PreserveNewest
143 | rive.dll
144 |
145 |
146 | PreserveNewest
147 | rive.pdb
148 |
149 |
150 |
151 |
152 | MSBuild:Compile
153 | Designer
154 |
155 |
156 | MSBuild:Compile
157 | Designer
158 |
159 |
160 |
161 |
162 | 6.2.14
163 |
164 |
165 |
166 |
167 | {f68f58d4-868b-49a2-a22f-6c9e076ea4ad}
168 | RiveSharp.Views.UWP
169 |
170 |
171 |
172 | 14.0
173 |
174 |
175 |
182 |
183 |
--------------------------------------------------------------------------------
/RiveSharp/Renderer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.Runtime.InteropServices;
5 | using SkiaSharp;
6 | using static RiveSharp.RiveAPI;
7 |
8 | namespace RiveSharp
9 | {
10 | public enum Fit
11 | {
12 | Fill = 0,
13 | Contain = 1,
14 | Cover = 2,
15 | FitWidth = 3,
16 | FitHeight = 4,
17 | None = 5,
18 | ScaleDown = 6
19 | };
20 |
21 | public class Alignment
22 | {
23 | public readonly float X, Y;
24 |
25 | Alignment(float x, float y)
26 | {
27 | X = x;
28 | Y = y;
29 | }
30 |
31 | public static Alignment TopLeft { get { return new Alignment(1.0f, -1.0f); } }
32 | public static Alignment TopCenter { get { return new Alignment(0.0f, -1.0f); } }
33 | public static Alignment TopRight { get { return new Alignment(1.0f, -1.0f); } }
34 | public static Alignment CenterLeft { get { return new Alignment(1.0f, 0.0f); } }
35 | public static Alignment Center { get { return new Alignment(0.0f, 0.0f); } }
36 | public static Alignment CenterRight { get { return new Alignment(1.0f, 0.0f); } }
37 | public static Alignment BottomLeft { get { return new Alignment(1.0f, 1.0f); } }
38 | public static Alignment BottomCenter { get { return new Alignment(0.0f, 1.0f); } }
39 | public static Alignment BottomRight { get { return new Alignment(1.0f, 1.0f); } }
40 | }
41 |
42 |
43 | public class Renderer
44 | {
45 | static readonly RendererDelegates Delegates = new RendererDelegates
46 | {
47 | Save = SaveCallback,
48 | Restore = RestoreCallback,
49 | Transform = TransformCallback,
50 | DrawPath = DrawPathCallback,
51 | ClipPath = ClipPathCallback,
52 | DrawImage = DrawImageCallback,
53 | DrawImageMesh = DrawImageMeshCallback
54 | };
55 |
56 | static Renderer()
57 | {
58 | RiveAPI.Renderer_RegisterDelegates(Delegates);
59 | }
60 |
61 | public static unsafe Mat2D ComputeAlignment(Fit fit,
62 | Alignment alignment,
63 | AABB frame,
64 | AABB content)
65 | {
66 | var args = new RiveAPI.ComputeAlignmentArgs
67 | {
68 | Fit = (int)fit,
69 | AlignX = alignment.X,
70 | AlignY = alignment.Y,
71 | Frame = frame,
72 | Content = content
73 | };
74 | RiveAPI.Renderer_ComputeAlignment(&args);
75 | return args.Matrix;
76 | }
77 |
78 | public readonly SKCanvas SKCanvas;
79 |
80 | public Renderer(SKCanvas skCanvas)
81 | {
82 | SKCanvas = skCanvas;
83 | }
84 |
85 | public void Save() { SKCanvas.Save(); }
86 | public void Restore() { SKCanvas.Restore(); }
87 |
88 | public void Transform(Mat2D m)
89 | {
90 | var mat = new SKMatrix(m.X1, m.X2, m.Tx, m.Y1, m.Y2, m.Ty, 0, 0, 1);
91 | SKCanvas.Concat(ref mat);
92 | }
93 |
94 | public void DrawPath(RenderPath path, RenderPaint paint)
95 | {
96 | SKCanvas.DrawPath(path.SKPath, paint.SKPaint);
97 | }
98 |
99 | public void ClipPath(RenderPath path)
100 | {
101 | SKCanvas.ClipPath(path.SKPath, SKClipOperation.Intersect, true);
102 | }
103 |
104 | public void DrawImage(RenderImage image, BlendMode blendMode, float opacity)
105 | {
106 | SKCanvas.DrawImage(image.SKImage, 0, 0, new SKPaint
107 | {
108 | IsAntialias = true,
109 | ColorF = new SKColorF(1, 1, 1, opacity),
110 | BlendMode = RenderPaint.ToSKBlendMode(blendMode),
111 | });
112 | }
113 |
114 | public void DrawImageMesh(RenderImage image,
115 | SKPoint[] vertices,
116 | SKPoint[] uvs,
117 | UInt16[] indices,
118 | BlendMode blendMode,
119 | float opacity) {
120 | if (uvs.Length != vertices.Length)
121 | {
122 | throw new ArgumentException("uvs must be the same length as vertices.");
123 | }
124 | var skVertices = SKVertices.CreateCopy(SKVertexMode.Triangles,
125 | positions: vertices,
126 | texs: uvs,
127 | colors: null,
128 | indices: indices);
129 | // DrawVertices ignores the blend mode if we don't have colors && uvs.
130 | SKCanvas.DrawVertices(skVertices, SKBlendMode.Dst, new SKPaint
131 | {
132 | IsAntialias = false, // DrawVertices ignores the IsAntialias flag.
133 | ColorF = new SKColorF(1, 1, 1, opacity),
134 | Shader = image.SKImage.ToShader(),
135 | BlendMode = RenderPaint.ToSKBlendMode(blendMode),
136 | });
137 | }
138 |
139 | // Transformation helpers.
140 | public void Translate(float x, float y) { Transform(Mat2D.FromTranslate(x, y)); }
141 | public void Scale(float sx, float sy) { Transform(Mat2D.FromScale(sx, sy)); }
142 | public void Rotate(float radians) { Transform(Mat2D.FromRotation(radians)); }
143 | public void Align(Fit fit, Alignment alignment, AABB frame, AABB content)
144 | {
145 | Transform(ComputeAlignment(fit, alignment, frame, content));
146 | }
147 |
148 | [MonoPInvokeCallback(typeof(RendererDelegates.SaveDelegate))]
149 | static void SaveCallback(IntPtr @ref)
150 | {
151 | var renderer = RiveAPI.CastNativeRef(@ref);
152 | renderer.Save();
153 | }
154 |
155 | [MonoPInvokeCallback(typeof(RendererDelegates.RestoreDelegate))]
156 | static void RestoreCallback(IntPtr @ref)
157 | {
158 | var renderer = RiveAPI.CastNativeRef(@ref);
159 | renderer.Restore();
160 | }
161 |
162 | [MonoPInvokeCallback(typeof(RendererDelegates.TransformDelegate))]
163 | static void TransformCallback(IntPtr @ref,
164 | float x1, float y1,
165 | float x2, float y2,
166 | float tx, float ty)
167 | {
168 | var renderer = RiveAPI.CastNativeRef(@ref);
169 | renderer.Transform(new Mat2D(x1, y1, x2, y2, tx, ty));
170 | }
171 |
172 | [MonoPInvokeCallback(typeof(RendererDelegates.DrawPathDelegate))]
173 | static void DrawPathCallback(IntPtr @ref, IntPtr pathRef, IntPtr paintRef)
174 | {
175 | var renderer = RiveAPI.CastNativeRef(@ref);
176 | var path = RiveAPI.CastNativeRef(pathRef);
177 | var paint = RiveAPI.CastNativeRef(paintRef);
178 | renderer.DrawPath(path, paint);
179 | }
180 |
181 | [MonoPInvokeCallback(typeof(RendererDelegates.ClipPathDelegate))]
182 | static void ClipPathCallback(IntPtr @ref, IntPtr pathRef)
183 | {
184 | var renderer = RiveAPI.CastNativeRef(@ref);
185 | var path = RiveAPI.CastNativeRef(pathRef);
186 | renderer.ClipPath(path);
187 | }
188 |
189 | [MonoPInvokeCallback(typeof(RendererDelegates.DrawImageDelegate))]
190 | static void DrawImageCallback(IntPtr @ref, IntPtr imageRef, int blendMode, float opacity)
191 | {
192 | var renderer = RiveAPI.CastNativeRef(@ref);
193 | var image = RiveAPI.CastNativeRef(imageRef);
194 | renderer.DrawImage(image, (BlendMode)blendMode, opacity);
195 | }
196 |
197 | [MonoPInvokeCallback(typeof(RendererDelegates.DrawImageMeshDelegate))]
198 | static void DrawImageMeshCallback(IntPtr @ref,
199 | IntPtr imageRef,
200 | IntPtr vertexArray, // SKPoint[nVertices]
201 | IntPtr uvArray, // SKPoint[nVertices]
202 | Int32 nVertices,
203 | IntPtr indexArray, // UInt16[nIndices]
204 | Int32 nIndices,
205 | Int32 blendMode,
206 | float opacity)
207 | {
208 | var renderer = RiveAPI.CastNativeRef(@ref);
209 | var image = RiveAPI.CastNativeRef(imageRef);
210 | var vertices = new SKPoint[nVertices];
211 | RiveAPI.CopySKPointArray(vertexArray, vertices, nVertices);
212 | var uvs = new SKPoint[nVertices];
213 | RiveAPI.CopySKPointArray(uvArray, uvs, nVertices);
214 | var indices = new UInt16[nIndices];
215 | RiveAPI.CopyU16Array(indexArray, indices, nIndices);
216 | renderer.DrawImageMesh(image, vertices, uvs, indices, (BlendMode)blendMode, opacity);
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/samples/Viewer/Viewer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}
8 | AppContainerExe
9 | Properties
10 | Viewer
11 | Viewer
12 | en-US
13 | UAP
14 | 10.0.22000.0
15 | 10.0.17763.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | true
20 | false
21 |
22 |
23 | true
24 | bin\x86\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | x86
29 | false
30 | prompt
31 | true
32 | true
33 |
34 |
35 | bin\x86\Release\
36 | TRACE;NETFX_CORE;WINDOWS_UWP
37 | true
38 | ;2008
39 | pdbonly
40 | x86
41 | false
42 | prompt
43 | true
44 | true
45 | true
46 |
47 |
48 | true
49 | bin\ARM\Debug\
50 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
51 | ;2008
52 | full
53 | ARM
54 | false
55 | prompt
56 | true
57 | true
58 |
59 |
60 | bin\ARM\Release\
61 | TRACE;NETFX_CORE;WINDOWS_UWP
62 | true
63 | ;2008
64 | pdbonly
65 | ARM
66 | false
67 | prompt
68 | true
69 | true
70 | true
71 |
72 |
73 | true
74 | bin\ARM64\Debug\
75 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
76 | ;2008
77 | full
78 | ARM64
79 | false
80 | prompt
81 | true
82 | true
83 | true
84 |
85 |
86 | bin\ARM64\Release\
87 | TRACE;NETFX_CORE;WINDOWS_UWP
88 | true
89 | ;2008
90 | pdbonly
91 | ARM64
92 | false
93 | prompt
94 | true
95 | true
96 | true
97 |
98 |
99 | true
100 | bin\x64\Debug\
101 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
102 | ;2008
103 | full
104 | x64
105 | false
106 | prompt
107 | true
108 | true
109 |
110 |
111 | bin\x64\Release\
112 | TRACE;NETFX_CORE;WINDOWS_UWP
113 | true
114 | ;2008
115 | pdbonly
116 | x64
117 | false
118 | prompt
119 | true
120 | true
121 | true
122 |
123 |
124 | PackageReference
125 |
126 |
127 |
128 | App.xaml
129 |
130 |
131 | MainPage.xaml
132 |
133 |
134 |
135 |
136 |
137 | Designer
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | PreserveNewest
151 | rive.dll
152 |
153 |
154 | PreserveNewest
155 | rive.pdb
156 |
157 |
158 |
159 |
160 | MSBuild:Compile
161 | Designer
162 |
163 |
164 | MSBuild:Compile
165 | Designer
166 |
167 |
168 |
169 |
170 | 6.2.14
171 |
172 |
173 |
174 |
175 | PreserveNewest
176 |
177 |
178 | PreserveNewest
179 |
180 |
181 | PreserveNewest
182 |
183 |
184 | PreserveNewest
185 |
186 |
187 |
188 |
189 | {f68f58d4-868b-49a2-a22f-6c9e076ea4ad}
190 | RiveSharp.Views.UWP
191 |
192 |
193 |
194 | 14.0
195 |
196 |
197 |
204 |
205 |
--------------------------------------------------------------------------------
/RiveSharp.Views.UWP/RivePlayer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using SkiaSharp.Views.UWP;
4 | using System;
5 | using System.Collections.Concurrent;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Net;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using Windows.ApplicationModel;
12 | using Windows.Storage;
13 | using Windows.UI.Core;
14 | using Windows.UI.Xaml;
15 | using Windows.UI.Xaml.Input;
16 |
17 | namespace RiveSharp.Views
18 | {
19 | // Implements a simple view that plays content from a .riv file.
20 | public partial class RivePlayer : SKSwapChainPanel
21 | {
22 | private CancellationTokenSource _activeSourceFileLoader = null;
23 |
24 | public RivePlayer()
25 | {
26 | this.StateMachineInputs = new StateMachineInputCollection(this);
27 | this.Loaded += OnLoaded;
28 | this.PointerPressed +=
29 | (object s, PointerRoutedEventArgs e) => HandlePointerEvent(_scene.PointerDown, e);
30 | this.PointerMoved +=
31 | (object s, PointerRoutedEventArgs e) => HandlePointerEvent(_scene.PointerMove, e);
32 | this.PointerReleased +=
33 | (object s, PointerRoutedEventArgs e) => HandlePointerEvent(_scene.PointerUp, e);
34 | this.PaintSurface += OnPaintSurface;
35 | }
36 |
37 | private async void LoadSourceFileDataAsync(string name, CancellationToken cancellationToken)
38 | {
39 | byte[] data = null;
40 | if (Uri.TryCreate(name, UriKind.Absolute, out var uri))
41 | {
42 | var client = new WebClient();
43 | data = await client.DownloadDataTaskAsync(uri);
44 | }
45 | else
46 | {
47 | var getFileTask = Package.Current.InstalledLocation.TryGetItemAsync(name);
48 | var storageFile = await getFileTask as StorageFile;
49 | if (storageFile != null && !cancellationToken.IsCancellationRequested)
50 | {
51 | var inputStream = await storageFile.OpenSequentialReadAsync();
52 | var fileStream = inputStream.AsStreamForRead();
53 | data = new byte[fileStream.Length];
54 | fileStream.Read(data, 0, data.Length);
55 | fileStream.Dispose(); // Don't keep the file open.
56 | }
57 | }
58 | if (data != null && !cancellationToken.IsCancellationRequested)
59 | {
60 | sceneActionsQueue.Enqueue(() => UpdateScene(SceneUpdates.File, data));
61 | // Apply deferred state machine inputs once the scene is fully loaded.
62 | foreach (Action stateMachineInput in _deferredSMInputsDuringFileLoad)
63 | {
64 | sceneActionsQueue.Enqueue(stateMachineInput);
65 | }
66 | }
67 | _deferredSMInputsDuringFileLoad = null;
68 | _activeSourceFileLoader = null;
69 | }
70 |
71 | // State machine inputs to set once the current async file load finishes.
72 | private List _deferredSMInputsDuringFileLoad = null;
73 |
74 | private void EnqueueStateMachineInput(Action stateMachineInput)
75 | {
76 | if (_deferredSMInputsDuringFileLoad != null)
77 | {
78 | // A source file is currently loading async. Don't set this input until it completes.
79 | _deferredSMInputsDuringFileLoad.Add(stateMachineInput);
80 | }
81 | else
82 | {
83 | sceneActionsQueue.Enqueue(stateMachineInput);
84 | }
85 | }
86 |
87 | public void SetBool(string name, bool value)
88 | {
89 | EnqueueStateMachineInput(() => _scene.SetBool(name, value));
90 | }
91 |
92 | public void SetNumber(string name, float value)
93 | {
94 | EnqueueStateMachineInput(() => _scene.SetNumber(name, value));
95 | }
96 |
97 | public void FireTrigger(string name)
98 | {
99 | EnqueueStateMachineInput(() => _scene.FireTrigger(name));
100 | }
101 |
102 | private delegate void PointerHandler(Vec2D pos);
103 |
104 | private void HandlePointerEvent(PointerHandler handler, PointerRoutedEventArgs e)
105 | {
106 | if (_activeSourceFileLoader != null)
107 | {
108 | // Ignore pointer events while a new scene is loading.
109 | return;
110 | }
111 |
112 | // Capture the viewSize and pointerPos at the time of the event.
113 | var viewSize = this.ActualSize;
114 | var pointerPos = e.GetCurrentPoint(this).Position;
115 |
116 | // Forward the pointer event to the render thread.
117 | sceneActionsQueue.Enqueue(() =>
118 | {
119 | Mat2D mat = ComputeAlignment(viewSize.X, viewSize.Y);
120 | if (mat.Invert(out var inverse))
121 | {
122 | Vec2D artboardPos = inverse * new Vec2D((float)pointerPos.X, (float)pointerPos.Y);
123 | handler(artboardPos);
124 | }
125 | });
126 | }
127 |
128 | // Incremented when the "InvalLoop" (responsible for scheduling PaintSurface events) should
129 | // terminate.
130 | int _invalLoopContinuationToken = 0;
131 |
132 | private void OnLoaded(object sender, RoutedEventArgs e)
133 | {
134 | Window.Current.VisibilityChanged += (object s, VisibilityChangedEventArgs vce) =>
135 | {
136 | ++_invalLoopContinuationToken; // Terminate the existing inval loop (if any).
137 | if (vce.Visible)
138 | {
139 | InvalLoopAsync(_invalLoopContinuationToken);
140 | }
141 | };
142 | }
143 |
144 | // Schedules continual PaintSurface events at 120fps until the window is no longer visible.
145 | // (Multiple calls to Invalidate() between PaintSurface events are coalesced.)
146 | private async void InvalLoopAsync(int continuationToken)
147 | {
148 | while (continuationToken == _invalLoopContinuationToken)
149 | {
150 | this.Invalidate();
151 | await Task.Delay(TimeSpan.FromMilliseconds(8)); // 120 fps
152 | }
153 | }
154 |
155 | // _scene is used on the render thread exclusively.
156 | Scene _scene = new Scene();
157 |
158 | // Source actions originating from other threads must be funneled through this queue.
159 | readonly ConcurrentQueue sceneActionsQueue = new ConcurrentQueue();
160 |
161 | // This is the render-thread copy of the animation parameters. They are set via
162 | // _sceneActionsQueue. _scene is then blah blah blah
163 | private string _artboardName;
164 | private string _animationName;
165 | private string _stateMachineName;
166 |
167 | private enum SceneUpdates
168 | {
169 | File = 3,
170 | Artboard = 2,
171 | AnimationOrStateMachine = 1,
172 | };
173 |
174 | DateTime _lastPaintTime;
175 |
176 | private void OnPaintSurface(object sender, SKPaintGLSurfaceEventArgs e)
177 | {
178 | // Handle pending scene actions from the main thread.
179 | while (sceneActionsQueue.TryDequeue(out var action))
180 | {
181 | action();
182 | }
183 |
184 | if (!_scene.IsLoaded)
185 | {
186 | return;
187 | }
188 |
189 | // Run the animation.
190 | var now = DateTime.Now;
191 | if (_lastPaintTime != null)
192 | {
193 | _scene.AdvanceAndApply((now - _lastPaintTime).TotalSeconds);
194 | }
195 | _lastPaintTime = now;
196 |
197 | // Render.
198 | e.Surface.Canvas.Clear();
199 | var renderer = new Renderer(e.Surface.Canvas);
200 | renderer.Save();
201 | renderer.Transform(ComputeAlignment(e.BackendRenderTarget.Width, e.BackendRenderTarget.Height));
202 | _scene.Draw(renderer);
203 | renderer.Restore();
204 | }
205 |
206 | // Called from the render thread. Updates _scene according to updates.
207 | void UpdateScene(SceneUpdates updates, byte[] sourceFileData = null)
208 | {
209 | if (updates >= SceneUpdates.File)
210 | {
211 | _scene.LoadFile(sourceFileData);
212 | }
213 | if (updates >= SceneUpdates.Artboard)
214 | {
215 | _scene.LoadArtboard(_artboardName);
216 | }
217 | if (updates >= SceneUpdates.AnimationOrStateMachine)
218 | {
219 | if (!String.IsNullOrEmpty(_stateMachineName))
220 | {
221 | _scene.LoadStateMachine(_stateMachineName);
222 | }
223 | else if (!String.IsNullOrEmpty(_animationName))
224 | {
225 | _scene.LoadAnimation(_animationName);
226 | }
227 | else
228 | {
229 | if (!_scene.LoadStateMachine(null))
230 | {
231 | _scene.LoadAnimation(null);
232 | }
233 | }
234 | }
235 | }
236 |
237 | // Called from the render thread. Computes alignment based on the size of _scene.
238 | private Mat2D ComputeAlignment(double width, double height)
239 | {
240 | return ComputeAlignment(new AABB(0, 0, (float)width, (float)height));
241 | }
242 |
243 | // Called from the render thread. Computes alignment based on the size of _scene.
244 | private Mat2D ComputeAlignment(AABB frame)
245 | {
246 | return Renderer.ComputeAlignment(Fit.Contain, Alignment.Center, frame,
247 | new AABB(0, 0, _scene.Width, _scene.Height));
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/RiveSharp/RenderPaint.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using System;
4 | using System.ComponentModel;
5 | using System.Runtime.InteropServices;
6 | using SkiaSharp;
7 |
8 | namespace RiveSharp
9 | {
10 | public enum RenderPaintStyle
11 | {
12 | Stroke = 0,
13 | Fill = 1
14 | }
15 |
16 | public enum StrokeJoin
17 | {
18 | Miter = 0,
19 | Round = 1,
20 | Bevel = 2
21 | }
22 |
23 | public enum StrokeCap
24 | {
25 | Butt = 0,
26 | Round = 1,
27 | Square = 2
28 | }
29 |
30 | public enum BlendMode
31 | {
32 | SrcOver = 3,
33 | Screen = 14,
34 | Overlay = 15,
35 | Darken = 16,
36 | Lighten = 17,
37 | ColorDodge = 18,
38 | ColorBurn = 19,
39 | HardLight = 20,
40 | SoftLight = 21,
41 | Difference = 22,
42 | Exclusion = 23,
43 | Multiply = 24,
44 | Hue = 25,
45 | Saturation = 26,
46 | Color = 27,
47 | Luminosity = 28
48 | }
49 |
50 | public class RenderPaint
51 | {
52 | static readonly RenderPaintDelegates Delegates = new RenderPaintDelegates
53 | {
54 | Release = RiveAPI.ReleaseNativeRefCallback,
55 | Style = StyleCallback,
56 | Color = ColorCallback,
57 | LinearGradient = LinearGradientCallback,
58 | RadialGradient = RadialGradientCallback,
59 | Thickness = ThicknessCallback,
60 | Join = JoinCallback,
61 | Cap = CapCallback,
62 | BlendMode = BlendModeCallback
63 | };
64 |
65 | static RenderPaint()
66 | {
67 | RiveAPI.RenderPaint_RegisterDelegates(Delegates);
68 | }
69 |
70 | public readonly SKPaint SKPaint = new SKPaint
71 | {
72 | Color = SKColors.Black,
73 | IsAntialias = true,
74 | Style = SKPaintStyle.Fill,
75 | };
76 |
77 | private static SKPaintStyle ToSKPaintStyle(RenderPaintStyle style)
78 | {
79 | switch (style)
80 | {
81 | case RenderPaintStyle.Stroke: return SKPaintStyle.Stroke;
82 | case RenderPaintStyle.Fill: return SKPaintStyle.Fill;
83 | }
84 | throw new InvalidEnumArgumentException("Invalid RenderPaintStyle " + style);
85 | }
86 |
87 | private static SKStrokeJoin ToSKStrokeJoin(StrokeJoin join)
88 | {
89 | switch (join)
90 | {
91 | case StrokeJoin.Miter: return SKStrokeJoin.Miter;
92 | case StrokeJoin.Round: return SKStrokeJoin.Round;
93 | case StrokeJoin.Bevel: return SKStrokeJoin.Bevel;
94 | }
95 | throw new InvalidEnumArgumentException("Invalid StrokeJoin " + join);
96 | }
97 |
98 | private static SKStrokeCap ToSKStrokeCap(StrokeCap cap)
99 | {
100 | switch (cap)
101 | {
102 | case StrokeCap.Butt: return SKStrokeCap.Butt;
103 | case StrokeCap.Round: return SKStrokeCap.Round;
104 | case StrokeCap.Square: return SKStrokeCap.Square;
105 | }
106 | throw new InvalidEnumArgumentException("Invalid StrokeCap " + cap);
107 | }
108 |
109 | internal static SKBlendMode ToSKBlendMode(BlendMode blendMode)
110 | {
111 | switch (blendMode)
112 | {
113 | case BlendMode.SrcOver: return SKBlendMode.SrcOver;
114 | case BlendMode.Screen: return SKBlendMode.Screen;
115 | case BlendMode.Overlay: return SKBlendMode.Overlay;
116 | case BlendMode.Darken: return SKBlendMode.Darken;
117 | case BlendMode.Lighten: return SKBlendMode.Lighten;
118 | case BlendMode.ColorDodge: return SKBlendMode.ColorDodge;
119 | case BlendMode.ColorBurn: return SKBlendMode.ColorBurn;
120 | case BlendMode.HardLight: return SKBlendMode.HardLight;
121 | case BlendMode.SoftLight: return SKBlendMode.SoftLight;
122 | case BlendMode.Difference: return SKBlendMode.Difference;
123 | case BlendMode.Exclusion: return SKBlendMode.Exclusion;
124 | case BlendMode.Multiply: return SKBlendMode.Multiply;
125 | case BlendMode.Hue: return SKBlendMode.Hue;
126 | case BlendMode.Saturation: return SKBlendMode.Saturation;
127 | case BlendMode.Color: return SKBlendMode.Color;
128 | case BlendMode.Luminosity: return SKBlendMode.Luminosity;
129 | }
130 | throw new InvalidEnumArgumentException("Invalid BlendMode " + blendMode);
131 | }
132 |
133 | public RenderPaintStyle Style { set { SKPaint.Style = ToSKPaintStyle(value); } }
134 | public UInt32 Color { set { SKPaint.Color = value; } }
135 | public void LinearGradient(float sx, float sy,
136 | float ex, float ey,
137 | UInt32[] colors,
138 | float[] stops)
139 | {
140 | var skColors = new SKColor[colors.Length];
141 | for (int i = 0; i < colors.Length; ++i)
142 | {
143 | skColors[i] = colors[i];
144 | }
145 | SKPaint.Shader = SKShader.CreateLinearGradient(new SKPoint(sx, sy),
146 | new SKPoint(ex, ey),
147 | skColors,
148 | stops,
149 | SKShaderTileMode.Clamp);
150 | }
151 | public void RadialGradient(float cx, float cy,
152 | float radius,
153 | UInt32[] colors,
154 | float[] stops)
155 | {
156 | var skColors = new SKColor[colors.Length];
157 | for (int i = 0; i < colors.Length; ++i)
158 | {
159 | skColors[i] = colors[i];
160 | }
161 | SKPaint.Shader = SKShader.CreateRadialGradient(new SKPoint(cx, cy),
162 | radius,
163 | skColors,
164 | stops,
165 | SKShaderTileMode.Clamp);
166 | }
167 | public float Thickness { set { SKPaint.StrokeWidth = value; } }
168 | public StrokeJoin Join { set { SKPaint.StrokeJoin = ToSKStrokeJoin(value); } }
169 | public StrokeCap Cap { set { SKPaint.StrokeCap = ToSKStrokeCap(value); } }
170 | public BlendMode BlendMode { set { SKPaint.BlendMode = ToSKBlendMode(value); } }
171 |
172 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.StyleDelegate))]
173 | static void StyleCallback(IntPtr @ref, int style)
174 | {
175 | var renderPaint = RiveAPI.CastNativeRef(@ref);
176 | renderPaint.Style = (RenderPaintStyle)style;
177 | }
178 |
179 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.ColorDelegate))]
180 | static void ColorCallback(IntPtr @ref, UInt32 color)
181 | {
182 | var renderPaint = RiveAPI.CastNativeRef(@ref);
183 | renderPaint.Color = color;
184 | }
185 |
186 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.LinearGradientDelegate))]
187 | static void LinearGradientCallback(IntPtr @ref,
188 | float sx, float sy,
189 | float ex, float ey,
190 | IntPtr colorsArray, IntPtr stopsArray, int n)
191 | {
192 | var renderPaint = RiveAPI.CastNativeRef(@ref);
193 | var colors = new UInt32[n];
194 | RiveAPI.CopyU32Array(colorsArray, colors, n);
195 | var stops = new float[n];
196 | Marshal.Copy(stopsArray, stops, 0, n);
197 | renderPaint.LinearGradient(sx, sy, ex, ey, colors, stops);
198 | }
199 |
200 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.RadialGradientDelegate))]
201 | static void RadialGradientCallback(IntPtr @ref,
202 | float cx, float cy,
203 | float radius,
204 | IntPtr colorsArray, IntPtr stopsArray, int n)
205 | {
206 | var renderPaint = RiveAPI.CastNativeRef(@ref);
207 | var colors = new UInt32[n];
208 | RiveAPI.CopyU32Array(colorsArray, colors, n);
209 | var stops = new float[n];
210 | Marshal.Copy(stopsArray, stops, 0, n);
211 | renderPaint.RadialGradient(cx, cy, radius, colors, stops);
212 | }
213 |
214 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.ThicknessDelegate))]
215 | static void ThicknessCallback(IntPtr @ref, float thickness)
216 | {
217 | var renderPaint = RiveAPI.CastNativeRef(@ref);
218 | renderPaint.Thickness = thickness;
219 | }
220 |
221 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.JoinDelegate))]
222 | static void JoinCallback(IntPtr @ref, int join)
223 | {
224 | var renderPaint = RiveAPI.CastNativeRef(@ref);
225 | renderPaint.Join = (StrokeJoin)join;
226 | }
227 |
228 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.CapDelegate))]
229 | static void CapCallback(IntPtr @ref, int cap)
230 | {
231 | var renderPaint = RiveAPI.CastNativeRef(@ref);
232 | renderPaint.Cap = (StrokeCap)cap;
233 | }
234 |
235 | [MonoPInvokeCallback(typeof(RenderPaintDelegates.BlendModeDelegate))]
236 | static void BlendModeCallback(IntPtr @ref, int blendMode)
237 | {
238 | var renderPaint = RiveAPI.CastNativeRef(@ref);
239 | renderPaint.BlendMode = (BlendMode)blendMode;
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/RiveSharpSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.2.32516.85
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Goldens", "Goldens\Goldens.csproj", "{F4CB71FC-C826-448C-873A-B2F49F735716}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Viewer", "samples\Viewer\Viewer.csproj", "{AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StateMachineInputs", "samples\StateMachineInputs\StateMachineInputs.csproj", "{2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RiveSharp", "RiveSharp\RiveSharp.csproj", "{7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RiveSharp.Views.UWP", "RiveSharp.Views.UWP\RiveSharp.Views.UWP.csproj", "{F68F58D4-868B-49A2-A22F-6C9E076EA4AD}"
15 | EndProject
16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rive", "native\rive.vcxproj", "{FB609D7C-E797-9E0D-9084-84107C9A1A0F}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{23670E97-A31A-4C2F-8877-B91EE57B050E}"
19 | ProjectSection(SolutionItems) = preProject
20 | .editorconfig = .editorconfig
21 | EndProjectSection
22 | EndProject
23 | Global
24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
25 | Debug|Any CPU = Debug|Any CPU
26 | Debug|ARM = Debug|ARM
27 | Debug|ARM64 = Debug|ARM64
28 | Debug|x64 = Debug|x64
29 | Debug|x86 = Debug|x86
30 | Release|Any CPU = Release|Any CPU
31 | Release|ARM = Release|ARM
32 | Release|ARM64 = Release|ARM64
33 | Release|x64 = Release|x64
34 | Release|x86 = Release|x86
35 | EndGlobalSection
36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
37 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|ARM.ActiveCfg = Debug|Any CPU
40 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|ARM.Build.0 = Debug|Any CPU
41 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|ARM64.ActiveCfg = Debug|Any CPU
42 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|ARM64.Build.0 = Debug|Any CPU
43 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|x64.ActiveCfg = Debug|Any CPU
44 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|x64.Build.0 = Debug|Any CPU
45 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|x86.ActiveCfg = Debug|Any CPU
46 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Debug|x86.Build.0 = Debug|Any CPU
47 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|ARM.ActiveCfg = Release|Any CPU
50 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|ARM.Build.0 = Release|Any CPU
51 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|ARM64.ActiveCfg = Release|Any CPU
52 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|ARM64.Build.0 = Release|Any CPU
53 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|x64.ActiveCfg = Release|Any CPU
54 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|x64.Build.0 = Release|Any CPU
55 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|x86.ActiveCfg = Release|Any CPU
56 | {F4CB71FC-C826-448C-873A-B2F49F735716}.Release|x86.Build.0 = Release|Any CPU
57 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|Any CPU.ActiveCfg = Debug|x64
58 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|Any CPU.Build.0 = Debug|x64
59 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|Any CPU.Deploy.0 = Debug|x64
60 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM.ActiveCfg = Debug|ARM
61 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM.Build.0 = Debug|ARM
62 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM.Deploy.0 = Debug|ARM
63 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM64.ActiveCfg = Debug|ARM64
64 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM64.Build.0 = Debug|ARM64
65 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|ARM64.Deploy.0 = Debug|ARM64
66 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x64.ActiveCfg = Debug|x64
67 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x64.Build.0 = Debug|x64
68 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x64.Deploy.0 = Debug|x64
69 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x86.ActiveCfg = Debug|x86
70 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x86.Build.0 = Debug|x86
71 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Debug|x86.Deploy.0 = Debug|x86
72 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|Any CPU.ActiveCfg = Release|x64
73 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|Any CPU.Build.0 = Release|x64
74 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|Any CPU.Deploy.0 = Release|x64
75 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM.ActiveCfg = Release|ARM
76 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM.Build.0 = Release|ARM
77 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM.Deploy.0 = Release|ARM
78 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM64.ActiveCfg = Release|ARM64
79 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM64.Build.0 = Release|ARM64
80 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|ARM64.Deploy.0 = Release|ARM64
81 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x64.ActiveCfg = Release|x64
82 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x64.Build.0 = Release|x64
83 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x64.Deploy.0 = Release|x64
84 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x86.ActiveCfg = Release|x86
85 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x86.Build.0 = Release|x86
86 | {AC0578B4-F64B-4854-A62F-2B7A31CBEFAA}.Release|x86.Deploy.0 = Release|x86
87 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|Any CPU.ActiveCfg = Debug|x64
88 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|Any CPU.Build.0 = Debug|x64
89 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|Any CPU.Deploy.0 = Debug|x64
90 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM.ActiveCfg = Debug|ARM
91 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM.Build.0 = Debug|ARM
92 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM.Deploy.0 = Debug|ARM
93 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM64.ActiveCfg = Debug|ARM64
94 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM64.Build.0 = Debug|ARM64
95 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|ARM64.Deploy.0 = Debug|ARM64
96 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x64.ActiveCfg = Debug|x64
97 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x64.Build.0 = Debug|x64
98 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x64.Deploy.0 = Debug|x64
99 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x86.ActiveCfg = Debug|x86
100 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x86.Build.0 = Debug|x86
101 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Debug|x86.Deploy.0 = Debug|x86
102 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|Any CPU.ActiveCfg = Release|x64
103 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|Any CPU.Build.0 = Release|x64
104 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|Any CPU.Deploy.0 = Release|x64
105 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM.ActiveCfg = Release|ARM
106 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM.Build.0 = Release|ARM
107 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM.Deploy.0 = Release|ARM
108 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM64.ActiveCfg = Release|ARM64
109 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM64.Build.0 = Release|ARM64
110 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|ARM64.Deploy.0 = Release|ARM64
111 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x64.ActiveCfg = Release|x64
112 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x64.Build.0 = Release|x64
113 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x64.Deploy.0 = Release|x64
114 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x86.ActiveCfg = Release|x86
115 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x86.Build.0 = Release|x86
116 | {2D8E223F-13A7-47EC-A7BA-A86032F4A6C7}.Release|x86.Deploy.0 = Release|x86
117 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
118 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|Any CPU.Build.0 = Debug|Any CPU
119 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|ARM.ActiveCfg = Debug|Any CPU
120 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|ARM.Build.0 = Debug|Any CPU
121 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|ARM64.ActiveCfg = Debug|Any CPU
122 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|ARM64.Build.0 = Debug|Any CPU
123 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|x64.ActiveCfg = Debug|Any CPU
124 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|x64.Build.0 = Debug|Any CPU
125 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|x86.ActiveCfg = Debug|Any CPU
126 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Debug|x86.Build.0 = Debug|Any CPU
127 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|Any CPU.ActiveCfg = Release|Any CPU
128 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|Any CPU.Build.0 = Release|Any CPU
129 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|ARM.ActiveCfg = Release|Any CPU
130 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|ARM.Build.0 = Release|Any CPU
131 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|ARM64.ActiveCfg = Release|Any CPU
132 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|ARM64.Build.0 = Release|Any CPU
133 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|x64.ActiveCfg = Release|Any CPU
134 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|x64.Build.0 = Release|Any CPU
135 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|x86.ActiveCfg = Release|Any CPU
136 | {7A1048DC-D6E5-4DBF-B9EA-2321D0EE0C66}.Release|x86.Build.0 = Release|Any CPU
137 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
138 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
139 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|ARM.ActiveCfg = Debug|ARM
140 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|ARM.Build.0 = Debug|ARM
141 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|ARM64.ActiveCfg = Debug|ARM64
142 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|ARM64.Build.0 = Debug|ARM64
143 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|x64.ActiveCfg = Debug|x64
144 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|x64.Build.0 = Debug|x64
145 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|x86.ActiveCfg = Debug|x86
146 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Debug|x86.Build.0 = Debug|x86
147 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
148 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|Any CPU.Build.0 = Release|Any CPU
149 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|ARM.ActiveCfg = Release|ARM
150 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|ARM.Build.0 = Release|ARM
151 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|ARM64.ActiveCfg = Release|ARM64
152 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|ARM64.Build.0 = Release|ARM64
153 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|x64.ActiveCfg = Release|x64
154 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|x64.Build.0 = Release|x64
155 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|x86.ActiveCfg = Release|x86
156 | {F68F58D4-868B-49A2-A22F-6C9E076EA4AD}.Release|x86.Build.0 = Release|x86
157 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|Any CPU.ActiveCfg = Debug|x64
158 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|Any CPU.Build.0 = Debug|x64
159 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|ARM.ActiveCfg = Debug|x64
160 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|ARM.Build.0 = Debug|x64
161 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|ARM64.ActiveCfg = Debug|x64
162 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|ARM64.Build.0 = Debug|x64
163 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|x64.ActiveCfg = Debug|x64
164 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|x64.Build.0 = Debug|x64
165 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|x86.ActiveCfg = Debug|Win32
166 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Debug|x86.Build.0 = Debug|Win32
167 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|Any CPU.ActiveCfg = Release|x64
168 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|Any CPU.Build.0 = Release|x64
169 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|ARM.ActiveCfg = Release|x64
170 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|ARM.Build.0 = Release|x64
171 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|ARM64.ActiveCfg = Release|x64
172 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|ARM64.Build.0 = Release|x64
173 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|x64.ActiveCfg = Release|x64
174 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|x64.Build.0 = Release|x64
175 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|x86.ActiveCfg = Release|Win32
176 | {FB609D7C-E797-9E0D-9084-84107C9A1A0F}.Release|x86.Build.0 = Release|Win32
177 | EndGlobalSection
178 | GlobalSection(SolutionProperties) = preSolution
179 | HideSolutionNode = FALSE
180 | EndGlobalSection
181 | GlobalSection(ExtensibilityGlobals) = postSolution
182 | SolutionGuid = {817F84FF-91E0-44C9-B49A-7F1BE3C9883D}
183 | EndGlobalSection
184 | EndGlobal
185 |
--------------------------------------------------------------------------------
/RiveSharp/RiveAPI.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Rive
2 |
3 | using SkiaSharp;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Net.Mime;
7 | using System.Runtime.InteropServices;
8 | using System.Text;
9 |
10 | namespace RiveSharp
11 | {
12 | [AttributeUsage(AttributeTargets.Method)]
13 | internal sealed class MonoPInvokeCallbackAttribute : Attribute
14 | {
15 | public MonoPInvokeCallbackAttribute(Type type)
16 | {
17 | Type = type;
18 | }
19 |
20 | public Type Type { get; private set; }
21 | }
22 |
23 | internal class RiveAPI
24 | {
25 | private const string Library = "rive";
26 |
27 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
28 | public static extern void CopySKPointArray(IntPtr sourceArray, [Out] SKPoint[] destination, Int32 count);
29 |
30 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
31 | public static extern void CopyU32Array(IntPtr sourceArray, [Out] UInt32[] destination, Int32 count);
32 |
33 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
34 | public static extern void CopyU16Array(IntPtr sourceArray, [Out] UInt16[] destination, Int32 count);
35 |
36 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
37 | public static extern unsafe void Mat2D_Multiply(Mat2D a, Mat2D b, Mat2D* c);
38 |
39 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
40 | public static extern unsafe void Mat2D_MultiplyVec2D(Mat2D a, Vec2D b, Vec2D* c);
41 |
42 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
43 | public static extern unsafe SByte Mat2D_Invert(Mat2D a, Mat2D* b);
44 |
45 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
46 | public static extern void Factory_RegisterDelegates(FactoryDelegates delegates);
47 |
48 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
49 | public static extern void Renderer_RegisterDelegates(RendererDelegates delegates);
50 |
51 | [StructLayout(LayoutKind.Sequential)]
52 | public struct ComputeAlignmentArgs
53 | {
54 | public Int32 Fit;
55 | public float AlignX;
56 | public float AlignY;
57 | public AABB Frame;
58 | public AABB Content;
59 | public Mat2D Matrix;
60 | }
61 |
62 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
63 | public static unsafe extern void Renderer_ComputeAlignment(ComputeAlignmentArgs* args);
64 |
65 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
66 | public static extern void RenderImage_RegisterDelegates(RenderImageDelegates delegates);
67 |
68 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
69 | public static extern void RenderPaint_RegisterDelegates(RenderPaintDelegates delegates);
70 |
71 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
72 | public static extern void RenderPath_RegisterDelegates(RenderPathDelegates delegates);
73 |
74 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
75 | public static extern IntPtr Scene_New(IntPtr factoryPtr);
76 |
77 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
78 | public static extern void Scene_Delete(IntPtr scene);
79 |
80 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
81 | public static extern SByte Scene_LoadFile(IntPtr scene, [In] byte[] fileBytes, int length);
82 |
83 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
84 | public static extern SByte Scene_LoadArtboard(IntPtr scene, string name);
85 |
86 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
87 | public static extern SByte Scene_LoadStateMachine(IntPtr scene, string name);
88 |
89 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
90 | public static extern SByte Scene_LoadAnimation(IntPtr scene, string name);
91 |
92 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
93 | public static extern SByte Scene_SetBool(IntPtr scene, string name, Int32 value);
94 |
95 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
96 | public static extern SByte Scene_SetNumber(IntPtr scene, string name, float value);
97 |
98 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
99 | public static extern SByte Scene_FireTrigger(IntPtr scene, string name);
100 |
101 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
102 | public static extern Single Scene_Width(IntPtr scene);
103 |
104 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
105 | public static extern Single Scene_Height(IntPtr scene);
106 |
107 | [DllImport(Library, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
108 | public static extern Int32 Scene_Name(IntPtr scene, [Out] char[] charArray);
109 |
110 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
111 | public static extern Int32 Scene_Loop(IntPtr scene);
112 |
113 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
114 | public static extern SByte Scene_IsTranslucent(IntPtr scene);
115 |
116 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
117 | public static extern Single Scene_DurationSeconds(IntPtr scene);
118 |
119 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
120 | public static extern SByte Scene_AdvanceAndApply(IntPtr scene, float elapsedSeconds);
121 |
122 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
123 | public static extern void Scene_Draw(IntPtr scene, IntPtr renderer);
124 |
125 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
126 | public static extern void Scene_PointerDown(IntPtr scene, Vec2D pos);
127 |
128 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
129 | public static extern void Scene_PointerMove(IntPtr scene, Vec2D pos);
130 |
131 | [DllImport(Library, CallingConvention = CallingConvention.Cdecl)]
132 | public static extern void Scene_PointerUp(IntPtr scene, Vec2D pos);
133 |
134 | public static IntPtr CreateNativeRef(Object obj)
135 | {
136 | return GCHandle.ToIntPtr(GCHandle.Alloc(obj));
137 | }
138 |
139 | public static T CastNativeRef(IntPtr @ref)
140 | {
141 | return (T)GCHandle.FromIntPtr(@ref).Target;
142 | }
143 |
144 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
145 | public unsafe delegate void ReleaseNativeRefDelegate(IntPtr ptr);
146 |
147 | [MonoPInvokeCallback(typeof(ReleaseNativeRefDelegate))]
148 | public static void ReleaseNativeRefCallback(IntPtr @ref)
149 | {
150 | GCHandle.FromIntPtr(@ref).Free();
151 | }
152 | }
153 |
154 | [StructLayout(LayoutKind.Sequential)]
155 | internal unsafe struct FactoryDelegates
156 | {
157 | public RiveAPI.ReleaseNativeRefDelegate Release;
158 |
159 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
160 | public unsafe delegate IntPtr MakeRenderPathDelegate(IntPtr @ref,
161 | IntPtr ptsArray, // SKPoint[nPts]
162 | Int32 nPts,
163 | IntPtr verbsArray, // byte[nVerbs]
164 | Int32 nVerbs,
165 | Int32 fillRule);
166 | public MakeRenderPathDelegate MakeRenderPath;
167 |
168 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
169 | public unsafe delegate IntPtr MakeEmptyObjectDelegate(IntPtr @ref);
170 | public MakeEmptyObjectDelegate MakeEmptyRenderPath;
171 | public MakeEmptyObjectDelegate MakeRenderPaint;
172 |
173 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
174 | public unsafe delegate IntPtr DecodeImageDelegate(IntPtr @ref, IntPtr bytesArray, Int32 nBytes);
175 | public DecodeImageDelegate DecodeImage;
176 | }
177 |
178 | [StructLayout(LayoutKind.Sequential)]
179 | internal unsafe struct RendererDelegates
180 | {
181 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
182 | public unsafe delegate void SaveDelegate(IntPtr @ref);
183 | public SaveDelegate Save;
184 |
185 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
186 | public unsafe delegate void RestoreDelegate(IntPtr @ref);
187 | public RestoreDelegate Restore;
188 |
189 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
190 | public unsafe delegate void TransformDelegate(IntPtr @ref,
191 | float x1, float y1,
192 | float x2, float y2,
193 | float tx, float ty);
194 | public TransformDelegate Transform;
195 |
196 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
197 | public unsafe delegate void DrawPathDelegate(IntPtr @ref, IntPtr pathRef, IntPtr paintRef);
198 | public DrawPathDelegate DrawPath;
199 |
200 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
201 | public unsafe delegate void ClipPathDelegate(IntPtr @ref, IntPtr pathPtr);
202 | public ClipPathDelegate ClipPath;
203 |
204 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
205 | public unsafe delegate void DrawImageDelegate(IntPtr @ref,
206 | IntPtr imageRef,
207 | Int32 blendMode,
208 | float opacity);
209 | public DrawImageDelegate DrawImage;
210 |
211 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
212 | public unsafe delegate void DrawImageMeshDelegate(IntPtr @ref,
213 | IntPtr imageRef,
214 | IntPtr vertexArray, // SKPoint[nVertices]
215 | IntPtr uvArray, // SKPoint[nVertices]
216 | Int32 nVertices,
217 | IntPtr indexArray, // UInt16[nIndices]
218 | Int32 nIndices,
219 | Int32 blendMode,
220 | float opacity);
221 | public DrawImageMeshDelegate DrawImageMesh;
222 | }
223 |
224 | [StructLayout(LayoutKind.Sequential)]
225 | internal unsafe struct RenderImageDelegates
226 | {
227 | public RiveAPI.ReleaseNativeRefDelegate Release;
228 |
229 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
230 | public unsafe delegate Int32 WidthHeightDelegate(IntPtr @ref);
231 | public WidthHeightDelegate Width;
232 | public WidthHeightDelegate Height;
233 | }
234 |
235 | [StructLayout(LayoutKind.Sequential)]
236 | internal unsafe struct RenderPaintDelegates
237 | {
238 | public RiveAPI.ReleaseNativeRefDelegate Release;
239 |
240 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
241 | public unsafe delegate void StyleDelegate(IntPtr @ref, Int32 style);
242 | public StyleDelegate Style;
243 |
244 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
245 | public unsafe delegate void ColorDelegate(IntPtr @ref, UInt32 color);
246 | public ColorDelegate Color;
247 |
248 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
249 | public unsafe delegate void LinearGradientDelegate(IntPtr @ref,
250 | float sx, float sy,
251 | float ex, float ey,
252 | IntPtr colorsArray, // UInt32[n]
253 | IntPtr stopsArray, // float[n]
254 | Int32 n);
255 | public LinearGradientDelegate LinearGradient;
256 |
257 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
258 | public unsafe delegate void RadialGradientDelegate(IntPtr @ref,
259 | float cx, float cy,
260 | float radius,
261 | IntPtr colorsArray, // UInt32[n]
262 | IntPtr stopsArray, // float[n]
263 | Int32 n);
264 | public RadialGradientDelegate RadialGradient;
265 |
266 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
267 | public unsafe delegate void ThicknessDelegate(IntPtr @ref, float thickness);
268 | public ThicknessDelegate Thickness;
269 |
270 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
271 | public unsafe delegate void JoinDelegate(IntPtr @ref, Int32 join);
272 | public JoinDelegate Join;
273 |
274 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
275 | public unsafe delegate void CapDelegate(IntPtr @ref, Int32 cap);
276 | public CapDelegate Cap;
277 |
278 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
279 | public unsafe delegate void BlendModeDelegate(IntPtr @ref, Int32 blendMode);
280 | public BlendModeDelegate BlendMode;
281 | }
282 |
283 | [StructLayout(LayoutKind.Sequential)]
284 | internal unsafe struct RenderPathDelegates
285 | {
286 | public RiveAPI.ReleaseNativeRefDelegate Release;
287 |
288 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
289 | public unsafe delegate void ResetDelegate(IntPtr ptr);
290 | public ResetDelegate Reset;
291 |
292 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
293 | public unsafe delegate void AddRenderPathDelegate(IntPtr ptr,
294 | IntPtr path,
295 | float x1, float y1,
296 | float x2, float y2,
297 | float tx, float ty);
298 | public AddRenderPathDelegate AddRenderPath;
299 |
300 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
301 | public unsafe delegate void FillRuleDelegate(IntPtr ptr, int rule);
302 | public FillRuleDelegate FillRule;
303 |
304 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
305 | public unsafe delegate void MoveToDelegate(IntPtr ptr, float x, float y);
306 | public MoveToDelegate MoveTo;
307 |
308 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
309 | public unsafe delegate void LineToDelegate(IntPtr ptr, float x, float y);
310 | public LineToDelegate LineTo;
311 |
312 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
313 | public unsafe delegate void QuadToDelegate(IntPtr ptr,
314 | float os, float oy,
315 | float x, float y);
316 | public QuadToDelegate QuadTo;
317 |
318 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
319 | public unsafe delegate void CubicToDelegate(IntPtr ptr,
320 | float ox, float oy,
321 | float ix, float iy,
322 | float x, float y);
323 | public CubicToDelegate CubicTo;
324 |
325 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
326 | public unsafe delegate void CloseDelegate(IntPtr ptr);
327 | public CloseDelegate Close;
328 | }
329 | }
330 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories
2 | root = true
3 |
4 | # Generated code
5 | [*{_AssemblyInfo.cs,.g.cs}]
6 | generated_code = true
7 |
8 | # All files
9 | [*]
10 |
11 | # Copyright
12 | file_header_template = Copyright 2022 Rive
13 |
14 | #### Core EditorConfig Options ####
15 |
16 | # Encoding
17 | charset = utf-8
18 |
19 | # Indentation and spacing
20 | tab_width = 4
21 | indent_size = 4
22 | indent_style = space
23 |
24 | # New line preferences
25 | end_of_line = lf
26 | trim_trailing_whitespace = true
27 | insert_final_newline = true
28 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
29 | dotnet_style_coalesce_expression = true:warning
30 | dotnet_style_null_propagation = true:warning
31 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
32 | dotnet_style_prefer_auto_properties = true:silent
33 | dotnet_style_object_initializer = true:warning
34 | dotnet_style_collection_initializer = true:warning
35 | dotnet_style_prefer_simplified_boolean_expressions = true:warning
36 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
37 | dotnet_style_prefer_conditional_expression_over_return = true:silent
38 | dotnet_style_explicit_tuple_names = true:warning
39 | dotnet_style_prefer_inferred_tuple_names = true:warning
40 | dotnet_style_prefer_compound_assignment = true:warning
41 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
42 | dotnet_style_namespace_match_folder = true:warning
43 | dotnet_style_prefer_simplified_interpolation = true:warning
44 | dotnet_style_readonly_field = true:warning
45 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
46 | dotnet_style_predefined_type_for_member_access = true:silent
47 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
48 | dotnet_style_allow_multiple_blank_lines_experimental = true:silent
49 | dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
50 | dotnet_code_quality_unused_parameters = all:suggestion
51 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
52 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
53 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
54 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
55 | dotnet_style_qualification_for_field = true:silent
56 | dotnet_style_qualification_for_property = true:silent
57 | dotnet_style_qualification_for_method = true:silent
58 | dotnet_style_qualification_for_event = true:silent
59 |
60 | #### Build files ####
61 |
62 | # Solution files
63 | [*.{sln,slnx}]
64 | tab_width = 4
65 | indent_size = 4
66 | indent_style = tab
67 |
68 | # Configuration files
69 | [*.{json,xml,yml,config,runsettings}]
70 | indent_size = 2
71 |
72 | # MSBuild files
73 | [*.{slnf,props,targets,projitems,csproj,shproj}]
74 | indent_size = 2
75 |
76 | #### Source files ####
77 |
78 | # Markdown files
79 | [*.md]
80 | indent_size = 2
81 | insert_final_newline = true
82 |
83 | # C# files
84 | [*.cs]
85 |
86 | #### .NET Coding Conventions ####
87 |
88 | # this. and Me. preferences
89 | dotnet_style_qualification_for_event = true:silent
90 | dotnet_style_qualification_for_field = true:silent
91 | dotnet_style_qualification_for_method = true:silent
92 | dotnet_style_qualification_for_property = true:silent
93 |
94 | # Language keywords vs BCL types preferences
95 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
96 | dotnet_style_predefined_type_for_member_access = true:silent
97 |
98 | # Parentheses preferences
99 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
100 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
101 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
102 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
103 |
104 | # Modifier preferences
105 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
106 |
107 | # Expression-level preferences
108 | csharp_style_deconstructed_variable_declaration = true:warning
109 | csharp_style_inlined_variable_declaration = true:warning
110 | csharp_style_throw_expression = true:warning
111 | dotnet_style_coalesce_expression = true:warning
112 | dotnet_style_collection_initializer = true:warning
113 | dotnet_style_explicit_tuple_names = true:warning
114 | dotnet_style_null_propagation = true:warning
115 | dotnet_style_object_initializer = true:warning
116 | dotnet_style_prefer_auto_properties = true:silent
117 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
118 | dotnet_style_prefer_conditional_expression_over_return = true:silent
119 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
120 | dotnet_style_prefer_inferred_tuple_names = true:warning
121 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
122 |
123 | # Field preferences
124 | dotnet_style_readonly_field = true:warning
125 |
126 | #### C# Coding Conventions ####
127 |
128 | # var preferences
129 | csharp_style_var_elsewhere = true:silent
130 | csharp_style_var_for_built_in_types = true:silent
131 | csharp_style_var_when_type_is_apparent = true:warning
132 |
133 | # Expression-bodied members
134 | csharp_style_expression_bodied_accessors = false:silent
135 | csharp_style_expression_bodied_constructors = false:silent
136 | csharp_style_expression_bodied_indexers = false:silent
137 | csharp_style_expression_bodied_lambdas = true:silent
138 | csharp_style_expression_bodied_methods = false:silent
139 | csharp_style_expression_bodied_operators = false:silent
140 | csharp_style_expression_bodied_properties = false:silent
141 |
142 | # Pattern matching preferences
143 | csharp_style_pattern_matching_over_as_with_null_check = true:silent
144 | csharp_style_pattern_matching_over_is_with_cast_check = true:silent
145 |
146 | # Null-checking preferences
147 | csharp_style_conditional_delegate_call = true:warning
148 |
149 | # Modifier preferences
150 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
151 |
152 | # Code-block preferences
153 | csharp_prefer_braces = true:warning
154 |
155 | # Expression-level preferences
156 | csharp_prefer_simple_default_expression = true:warning
157 | csharp_style_pattern_local_over_anonymous_function = true:warning
158 |
159 | #### C# Formatting Rules ####
160 |
161 | # New line preferences
162 | csharp_new_line_before_catch = true
163 | csharp_new_line_before_else = true
164 | csharp_new_line_before_finally = true
165 | csharp_new_line_before_members_in_anonymous_types = true
166 | csharp_new_line_before_members_in_object_initializers = true
167 | csharp_new_line_before_open_brace = all
168 | csharp_new_line_between_query_expression_clauses = true
169 |
170 | # Indentation preferences
171 | csharp_indent_block_contents = true
172 | csharp_indent_braces = false
173 | csharp_indent_case_contents = true
174 | csharp_indent_case_contents_when_block = false
175 | csharp_indent_labels = no_change
176 | csharp_indent_switch_labels = true
177 |
178 | # Space preferences
179 | csharp_space_after_cast = false
180 | csharp_space_after_colon_in_inheritance_clause = true
181 | csharp_space_after_comma = true
182 | csharp_space_after_dot = false
183 | csharp_space_after_keywords_in_control_flow_statements = true
184 | csharp_space_after_semicolon_in_for_statement = true
185 | csharp_space_around_binary_operators = before_and_after
186 | csharp_space_around_declaration_statements = false
187 | csharp_space_before_colon_in_inheritance_clause = true
188 | csharp_space_before_comma = false
189 | csharp_space_before_dot = false
190 | csharp_space_before_open_square_brackets = false
191 | csharp_space_before_semicolon_in_for_statement = false
192 | csharp_space_between_empty_square_brackets = false
193 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
194 | csharp_space_between_method_call_name_and_opening_parenthesis = false
195 | csharp_space_between_method_call_parameter_list_parentheses = false
196 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
197 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
198 | csharp_space_between_method_declaration_parameter_list_parentheses = false
199 | csharp_space_between_parentheses = false
200 | csharp_space_between_square_brackets = false
201 |
202 | # Wrapping preferences
203 | csharp_preserve_single_line_blocks = true
204 | csharp_preserve_single_line_statements = true
205 |
206 | # Naming Symbols
207 |
208 | # constant_fields - Define constant fields
209 | dotnet_naming_symbols.constant_fields.applicable_kinds = field
210 | dotnet_naming_symbols.constant_fields.required_modifiers = const
211 | # non_private_readonly_fields - Define public, internal and protected readonly fields
212 | dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, internal, protected
213 | dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
214 | dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
215 | # static_readonly_fields - Define static and readonly fields
216 | dotnet_naming_symbols.static_readonly_fields.applicable_kinds = field
217 | dotnet_naming_symbols.static_readonly_fields.required_modifiers = static, readonly
218 | # private_readonly_fields - Define private readonly fields
219 | dotnet_naming_symbols.private_readonly_fields.applicable_accessibilities = private
220 | dotnet_naming_symbols.private_readonly_fields.applicable_kinds = field
221 | dotnet_naming_symbols.private_readonly_fields.required_modifiers = readonly
222 | # public_internal_fields - Define public and internal fields
223 | dotnet_naming_symbols.public_internal_protected_fields.applicable_accessibilities = public, internal, protected
224 | dotnet_naming_symbols.public_internal_protected_fields.applicable_kinds = field
225 | # private_protected_fields - Define private and protected fields
226 | dotnet_naming_symbols.private_protected_fields.applicable_accessibilities = private, protected
227 | dotnet_naming_symbols.private_protected_fields.applicable_kinds = field
228 | # public_symbols - Define any public symbol
229 | dotnet_naming_symbols.public_symbols.applicable_accessibilities = public, internal, protected, protected_internal
230 | dotnet_naming_symbols.public_symbols.applicable_kinds = method, property, event, delegate
231 | # parameters - Defines any parameter
232 | dotnet_naming_symbols.parameters.applicable_kinds = parameter
233 | # non_interface_types - Defines class, struct, enum and delegate types
234 | dotnet_naming_symbols.non_interface_types.applicable_kinds = class, struct, enum, delegate
235 | # interface_types - Defines interfaces
236 | dotnet_naming_symbols.interface_types.applicable_kinds = interface
237 |
238 | # Naming Styles
239 |
240 | # camel_case - Define the camelCase style
241 | dotnet_naming_style.camel_case.capitalization = camel_case
242 | # pascal_case - Define the Pascal_case style
243 | dotnet_naming_style.pascal_case.capitalization = pascal_case
244 | # first_upper - The first character must start with an upper-case character
245 | dotnet_naming_style.first_upper.capitalization = first_word_upper
246 | # prefix_interface_interface_with_i - Interfaces must be PascalCase and the first character of an interface must be an 'I'
247 | dotnet_naming_style.prefix_interface_interface_with_i.capitalization = pascal_case
248 | dotnet_naming_style.prefix_interface_interface_with_i.required_prefix = I
249 |
250 | # Naming Rules
251 |
252 | # Async
253 | dotnet_naming_rule.async_methods_end_in_async.severity = warning
254 | dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods
255 | dotnet_naming_rule.async_methods_end_in_async.style = end_in_async
256 |
257 | dotnet_naming_symbols.any_async_methods.applicable_kinds = method
258 | dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
259 | dotnet_naming_symbols.any_async_methods.required_modifiers = async
260 |
261 | dotnet_naming_style.end_in_async.required_suffix = Async
262 | dotnet_naming_style.end_in_async.capitalization = pascal_case
263 |
264 | # Constant fields must be PascalCase
265 | dotnet_naming_rule.constant_fields_must_be_pascal_case.severity = warning
266 | dotnet_naming_rule.constant_fields_must_be_pascal_case.symbols = constant_fields
267 | dotnet_naming_rule.constant_fields_must_be_pascal_case.style = pascal_case
268 | # Public, internal and protected readonly fields must be PascalCase
269 | dotnet_naming_rule.non_private_readonly_fields_must_be_pascal_case.severity = warning
270 | dotnet_naming_rule.non_private_readonly_fields_must_be_pascal_case.symbols = non_private_readonly_fields
271 | dotnet_naming_rule.non_private_readonly_fields_must_be_pascal_case.style = pascal_case
272 | # Static readonly fields must be PascalCase
273 | dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.severity = warning
274 | dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.symbols = static_readonly_fields
275 | dotnet_naming_rule.static_readonly_fields_must_be_pascal_case.style = pascal_case
276 | # Private readonly fields must be camelCase
277 | dotnet_naming_rule.private_readonly_fields_must_be_camel_case.severity = warning
278 | dotnet_naming_rule.private_readonly_fields_must_be_camel_case.symbols = private_readonly_fields
279 | dotnet_naming_rule.private_readonly_fields_must_be_camel_case.style = camel_case
280 | # Public and internal fields must be PascalCase
281 | dotnet_naming_rule.public_internal_protected_fields_must_be_pascal_case.severity = warning
282 | dotnet_naming_rule.public_internal_protected_fields_must_be_pascal_case.symbols = public_internal_protected_fields
283 | dotnet_naming_rule.public_internal_protected_fields_must_be_pascal_case.style = pascal_case
284 | # Private and protected fields must be camelCase
285 | dotnet_naming_rule.private_fields_must_be_camel_case.severity = warning
286 | dotnet_naming_rule.private_fields_must_be_camel_case.symbols = private_protected_fields
287 | dotnet_naming_rule.private_fields_must_be_camel_case.style = prefix_private_field_with_underscore
288 | # Public members must be capitalized
289 | dotnet_naming_rule.public_members_must_be_capitalized.severity = warning
290 | dotnet_naming_rule.public_members_must_be_capitalized.symbols = public_symbols
291 | dotnet_naming_rule.public_members_must_be_capitalized.style = first_upper
292 | # Parameters must be camelCase
293 | dotnet_naming_rule.parameters_must_be_camel_case.severity = warning
294 | dotnet_naming_rule.parameters_must_be_camel_case.symbols = parameters
295 | dotnet_naming_rule.parameters_must_be_camel_case.style = camel_case
296 | # Class, struct, enum and delegates must be PascalCase
297 | dotnet_naming_rule.non_interface_types_must_be_pascal_case.severity = warning
298 | dotnet_naming_rule.non_interface_types_must_be_pascal_case.symbols = non_interface_types
299 | dotnet_naming_rule.non_interface_types_must_be_pascal_case.style = pascal_case
300 | # Interfaces must be PascalCase and start with an 'I'
301 | dotnet_naming_rule.interface_types_must_be_prefixed_with_i.severity = warning
302 | dotnet_naming_rule.interface_types_must_be_prefixed_with_i.symbols = interface_types
303 | dotnet_naming_rule.interface_types_must_be_prefixed_with_i.style = prefix_interface_interface_with_i
304 | # prefix_private_field_with_underscore - Private fields must be prefixed with _
305 | dotnet_naming_style.prefix_private_field_with_underscore.capitalization = camel_case
306 | dotnet_naming_style.prefix_private_field_with_underscore.required_prefix = _
307 |
308 | # .NET Code Analysis
309 |
310 | dotnet_diagnostic.CA1001.severity = warning
311 | dotnet_diagnostic.CA1009.severity = warning
312 | dotnet_diagnostic.CA1016.severity = warning
313 | dotnet_diagnostic.CA1033.severity = warning
314 | dotnet_diagnostic.CA1049.severity = warning
315 | dotnet_diagnostic.CA1060.severity = warning
316 | dotnet_diagnostic.CA1061.severity = warning
317 | dotnet_diagnostic.CA1063.severity = warning
318 | dotnet_diagnostic.CA1065.severity = warning
319 | dotnet_diagnostic.CA1301.severity = warning
320 | dotnet_diagnostic.CA1400.severity = warning
321 | dotnet_diagnostic.CA1401.severity = warning
322 | dotnet_diagnostic.CA1403.severity = warning
323 | dotnet_diagnostic.CA1404.severity = warning
324 | dotnet_diagnostic.CA1405.severity = warning
325 | dotnet_diagnostic.CA1410.severity = warning
326 | dotnet_diagnostic.CA1415.severity = warning
327 | dotnet_diagnostic.CA1821.severity = warning
328 | dotnet_diagnostic.CA1900.severity = warning
329 | dotnet_diagnostic.CA1901.severity = warning
330 | dotnet_diagnostic.CA2002.severity = warning
331 | dotnet_diagnostic.CA2100.severity = warning
332 | dotnet_diagnostic.CA2101.severity = warning
333 | dotnet_diagnostic.CA2108.severity = warning
334 | dotnet_diagnostic.CA2111.severity = warning
335 | dotnet_diagnostic.CA2112.severity = warning
336 | dotnet_diagnostic.CA2114.severity = warning
337 | dotnet_diagnostic.CA2116.severity = warning
338 | dotnet_diagnostic.CA2117.severity = warning
339 | dotnet_diagnostic.CA2122.severity = warning
340 | dotnet_diagnostic.CA2123.severity = warning
341 | dotnet_diagnostic.CA2124.severity = warning
342 | dotnet_diagnostic.CA2126.severity = warning
343 | dotnet_diagnostic.CA2131.severity = warning
344 | dotnet_diagnostic.CA2132.severity = warning
345 | dotnet_diagnostic.CA2133.severity = warning
346 | dotnet_diagnostic.CA2134.severity = warning
347 | dotnet_diagnostic.CA2137.severity = warning
348 | dotnet_diagnostic.CA2138.severity = warning
349 | dotnet_diagnostic.CA2140.severity = warning
350 | dotnet_diagnostic.CA2141.severity = warning
351 | dotnet_diagnostic.CA2146.severity = warning
352 | dotnet_diagnostic.CA2147.severity = warning
353 | dotnet_diagnostic.CA2149.severity = warning
354 | dotnet_diagnostic.CA2200.severity = warning
355 | dotnet_diagnostic.CA2202.severity = warning
356 | dotnet_diagnostic.CA2207.severity = warning
357 | dotnet_diagnostic.CA2212.severity = warning
358 | dotnet_diagnostic.CA2213.severity = warning
359 | dotnet_diagnostic.CA2214.severity = warning
360 | dotnet_diagnostic.CA2216.severity = warning
361 | dotnet_diagnostic.CA2220.severity = warning
362 | dotnet_diagnostic.CA2229.severity = warning
363 | dotnet_diagnostic.CA2231.severity = warning
364 | dotnet_diagnostic.CA2232.severity = warning
365 | dotnet_diagnostic.CA2235.severity = warning
366 | dotnet_diagnostic.CA2236.severity = warning
367 | dotnet_diagnostic.CA2237.severity = warning
368 | dotnet_diagnostic.CA2238.severity = warning
369 | dotnet_diagnostic.CA2240.severity = warning
370 | dotnet_diagnostic.CA2241.severity = warning
371 | dotnet_diagnostic.CA2242.severity = warning
372 |
373 | # StyleCop Code Analysis
374 |
375 | # Closing parenthesis should be spaced correctly: "foo()!"
376 | dotnet_diagnostic.SA1009.severity = none
377 |
378 | # Hide warnings when using the new() expression from C# 9.
379 | dotnet_diagnostic.SA1000.severity = none
380 |
381 | dotnet_diagnostic.SA1011.severity = none
382 | dotnet_diagnostic.SA1101.severity = none
383 |
384 | # Hide warnings when accessing properties without "this".
385 | dotnet_diagnostic.SA1101.severity = none
386 | dotnet_diagnostic.SA1118.severity = none
387 | dotnet_diagnostic.SA1200.severity = none
388 | dotnet_diagnostic.SA1201.severity = none
389 | dotnet_diagnostic.SA1202.severity = none
390 | dotnet_diagnostic.SA1309.severity = none
391 | dotnet_diagnostic.SA1310.severity = none
392 |
393 | # Hide warnings for record parameters.
394 | dotnet_diagnostic.SA1313.severity = none
395 |
396 | # TypeParameterNamesMustBeginWithT: We do have a few templates that don't start with T. We need to double check that changing this is not a breaking change. If not, we can re-enable this.
397 | dotnet_diagnostic.SA1314.severity = none
398 |
399 | # UseTrailingCommasInMultiLineInitializers: This would also mean a lot of changes at the end of all multiline initializers. It's also debatable if we want this or not.
400 | dotnet_diagnostic.SA1413.severity = none
401 |
402 | dotnet_diagnostic.SA1600.severity = none
403 | dotnet_diagnostic.SA1602.severity = none
404 | dotnet_diagnostic.SA1611.severity = none
405 |
406 | # DocumentationTextMustEndWithAPeriod: Let's enable this rule back when we shift to WinUI3 (v8.x). If we do it now, it would mean more than 400 file changes.
407 | dotnet_diagnostic.SA1629.severity = none
408 |
409 | dotnet_diagnostic.SA1633.severity = none
410 | dotnet_diagnostic.SA1634.severity = none
411 | dotnet_diagnostic.SA1652.severity = none
412 | csharp_using_directive_placement = outside_namespace:silent
413 | csharp_prefer_simple_using_statement = true:warning
414 | csharp_style_namespace_declarations = file_scoped:warning
415 | csharp_style_expression_bodied_local_functions = false:silent
416 | csharp_style_prefer_null_check_over_type_check = true:warning
417 | csharp_style_prefer_local_over_anonymous_function = true:warning
418 | csharp_style_prefer_index_operator = true:warning
419 | csharp_style_prefer_range_operator = true:warning
420 | csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
421 | csharp_style_prefer_tuple_swap = true:warning
422 | csharp_style_unused_value_assignment_preference = discard_variable:warning
423 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
424 | csharp_prefer_static_local_function = true:warning
425 | csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
426 | csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
427 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
428 | csharp_style_prefer_pattern_matching = true:silent
429 | csharp_style_prefer_switch_expression = true:warning
430 | csharp_style_prefer_not_pattern = true:warning
431 | csharp_style_prefer_extended_property_pattern = true:warning
432 |
433 | # Require file header
434 | dotnet_diagnostic.IDE0073.severity = warning
435 | csharp_style_prefer_utf8_string_literals = true:warning
436 | csharp_style_prefer_top_level_statements = true:silent
437 | csharp_style_prefer_method_group_conversion = true:silent
438 |
--------------------------------------------------------------------------------
/native/RiveSharpInterop.cpp:
--------------------------------------------------------------------------------
1 | #include "rive/animation/state_machine_input_instance.hpp"
2 | #include "rive/factory.hpp"
3 | #include "utils/factory_utils.hpp"
4 | #include "rive/file.hpp"
5 | #include "rive/animation/animation.hpp"
6 | #include "rive/animation/linear_animation_instance.hpp"
7 | #include "rive/animation/linear_animation.hpp"
8 | #include "rive/animation/state_machine_instance.hpp"
9 | #include "rive/artboard.hpp"
10 | #include "rive/renderer.hpp"
11 |
12 | using namespace rive;
13 |
14 | #if 0
15 | // Message box utility since we don't have a console in UWP for printfs.
16 | #include
17 | #include
18 | static void msgbox(const char* format, ...) {
19 | std::vector msg;
20 | va_list args, args_copy;
21 |
22 | va_start(args, format);
23 | va_copy(args_copy, args);
24 |
25 | int len = vsnprintf(nullptr, 0, format, args);
26 | if (len > 0) {
27 | msg.resize(len + 1);
28 | vsnprintf(msg.data(), msg.size(), format, args_copy);
29 | MessageBoxA(NULL, msg.data(), "This is a cool message from Rive!", 0);
30 | }
31 |
32 | va_end(args_copy);
33 | va_end(args);
34 | }
35 | #endif
36 |
37 | #ifndef WASM
38 | #define RIVE_DLL(RET) extern "C" __declspec(dllexport) RET __cdecl
39 | #else
40 | #define RIVE_DLL(RET) \
41 | extern "C" __attribute__((visibility("default"))) RET __cdecl
42 | #endif
43 |
44 | // Native P/Invoke functions may only return "blittable" types. To protect from
45 | // inadvertently returning an invalid type, we explicitly enumerate valid return
46 | // types here. See:
47 | // https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types
48 | #define RIVE_DLL_VOID RIVE_DLL(void)
49 | #define RIVE_DLL_INT8_BOOL RIVE_DLL(int8_t)
50 | #define RIVE_DLL_INT32 RIVE_DLL(int32_t)
51 | #define RIVE_DLL_FLOAT RIVE_DLL(float)
52 | #define RIVE_DLL_INTPTR RIVE_DLL(intptr_t)
53 |
54 | // Reverse P/Invoke Function pointers back into managed code are also __cdecl
55 | // and may also only return blittable types.
56 | #define RIVE_DELEGATE_VOID(NAME, ...) void(__cdecl * NAME)(__VA_ARGS__)
57 | #define RIVE_DELEGATE_INTPTR(NAME, ...) intptr_t(__cdecl* NAME)(__VA_ARGS__)
58 | #define RIVE_DELEGATE_INT32(NAME, ...) int32_t(__cdecl* NAME)(__VA_ARGS__)
59 |
60 | ////////////////////////////////////////////////////////////////////////////////////////////////////
61 |
62 | RIVE_DLL_VOID CopySKPointArray(intptr_t sourceArray,
63 | Vec2D* destination,
64 | int32_t count)
65 | {
66 | const Vec2D* source = reinterpret_cast(sourceArray);
67 | memcpy(destination, source, count * sizeof(Vec2D));
68 | }
69 |
70 | RIVE_DLL_VOID CopyU32Array(intptr_t sourceArray,
71 | uint32_t* destination,
72 | int32_t count)
73 | {
74 | const uint32_t* source = reinterpret_cast(sourceArray);
75 | memcpy(destination, source, count * sizeof(uint32_t));
76 | }
77 |
78 | RIVE_DLL_VOID CopyU16Array(intptr_t sourceArray,
79 | uint16_t* destination,
80 | int32_t count)
81 | {
82 | const uint16_t* source = reinterpret_cast(sourceArray);
83 | memcpy(destination, source, count * sizeof(uint16_t));
84 | }
85 |
86 | ////////////////////////////////////////////////////////////////////////////////////////////////////
87 |
88 | RIVE_DLL_VOID Mat2D_Multiply(Mat2D a, Mat2D b, Mat2D* out) { *out = a * b; }
89 | RIVE_DLL_VOID Mat2D_MultiplyVec2D(Mat2D a, Vec2D b, Vec2D* out)
90 | {
91 | *out = a * b;
92 | }
93 | RIVE_DLL_INT8_BOOL Mat2D_Invert(Mat2D a, Mat2D* out) { return a.invert(out); }
94 |
95 | ////////////////////////////////////////////////////////////////////////////////////////////////////
96 |
97 | class RenderPathSharp : public RenderPath
98 | {
99 | public:
100 | struct Delegates
101 | {
102 | RIVE_DELEGATE_VOID(release, intptr_t ref);
103 | RIVE_DELEGATE_VOID(rewind, intptr_t ref);
104 | RIVE_DELEGATE_VOID(addRenderPath,
105 | intptr_t ref,
106 | intptr_t path,
107 | float,
108 | float,
109 | float,
110 | float,
111 | float,
112 | float);
113 | RIVE_DELEGATE_VOID(fillRule, intptr_t ref, int rule);
114 | RIVE_DELEGATE_VOID(moveTo, intptr_t ref, float x, float y);
115 | RIVE_DELEGATE_VOID(lineTo, intptr_t ref, float x, float y);
116 | RIVE_DELEGATE_VOID(quadTo,
117 | intptr_t ref,
118 | float ox,
119 | float oy,
120 | float x,
121 | float y);
122 | RIVE_DELEGATE_VOID(cubicTo,
123 | intptr_t ref,
124 | float ox,
125 | float oy,
126 | float ix,
127 | float iy,
128 | float x,
129 | float y);
130 | RIVE_DELEGATE_VOID(close, intptr_t ref);
131 | };
132 |
133 | static Delegates s_delegates;
134 |
135 | RenderPathSharp(intptr_t managedRef) : m_ref(managedRef) {}
136 | RenderPathSharp(const RenderPathSharp&) = delete;
137 | RenderPathSharp& operator=(const RenderPathSharp&) = delete;
138 | ~RenderPathSharp() { s_delegates.release(m_ref); };
139 |
140 | void rewind() override { s_delegates.rewind(m_ref); }
141 | void fillRule(FillRule value) override
142 | {
143 | s_delegates.fillRule(m_ref, (int)value);
144 | }
145 | void addRenderPath(RenderPath* path, const Mat2D& m) override
146 | {
147 | s_delegates.addRenderPath(m_ref,
148 | static_cast(path)->m_ref,
149 | m.xx(),
150 | m.xy(),
151 | m.yx(),
152 | m.yy(),
153 | m.tx(),
154 | m.ty());
155 | }
156 | void moveTo(float x, float y) override { s_delegates.moveTo(m_ref, x, y); }
157 | void lineTo(float x, float y) override { s_delegates.lineTo(m_ref, x, y); }
158 | void cubicTo(float ox, float oy, float ix, float iy, float x, float y)
159 | override
160 | {
161 | s_delegates.cubicTo(m_ref, ox, oy, ix, iy, x, y);
162 | }
163 | void close() override { s_delegates.close(m_ref); }
164 |
165 | // not an override, but needed for makeRenderPath
166 | void quadTo(float ox, float oy, float x, float y)
167 | {
168 | s_delegates.quadTo(m_ref, ox, oy, x, y);
169 | }
170 |
171 | const intptr_t m_ref;
172 | };
173 |
174 | RenderPathSharp::Delegates RenderPathSharp::s_delegates{};
175 |
176 | RIVE_DLL_VOID RenderPath_RegisterDelegates(RenderPathSharp::Delegates delegates)
177 | {
178 | RenderPathSharp::s_delegates = delegates;
179 | }
180 |
181 | ////////////////////////////////////////////////////////////////////////////////////////////////////
182 |
183 | class RenderImageSharp : public RenderImage
184 | {
185 | public:
186 | struct Delegates
187 | {
188 | RIVE_DELEGATE_VOID(release, intptr_t ref);
189 | RIVE_DELEGATE_INT32(width, intptr_t ref);
190 | RIVE_DELEGATE_INT32(height, intptr_t ref);
191 | };
192 |
193 | static Delegates s_delegates;
194 |
195 | RenderImageSharp(intptr_t managedRef) : m_ref(managedRef)
196 | {
197 | m_Width = s_delegates.width(m_ref);
198 | m_Height = s_delegates.height(m_ref);
199 | }
200 | RenderImageSharp(const RenderImageSharp&) = delete;
201 | RenderImageSharp& operator=(const RenderImageSharp&) = delete;
202 | ~RenderImageSharp() { s_delegates.release(m_ref); };
203 |
204 | const intptr_t m_ref;
205 | };
206 |
207 | RenderImageSharp::Delegates RenderImageSharp::s_delegates{};
208 |
209 | RIVE_DLL_VOID RenderImage_RegisterDelegates(
210 | RenderImageSharp::Delegates delegates)
211 | {
212 | RenderImageSharp::s_delegates = delegates;
213 | }
214 |
215 | ////////////////////////////////////////////////////////////////////////////////////////////////////
216 |
217 | class RenderPaintSharp : public RenderPaint
218 | {
219 | public:
220 | struct Delegates
221 | {
222 | RIVE_DELEGATE_VOID(release, intptr_t ref);
223 | RIVE_DELEGATE_VOID(style, intptr_t ref, int style);
224 | RIVE_DELEGATE_VOID(color, intptr_t ref, uint32_t color);
225 | RIVE_DELEGATE_VOID(linearGradient,
226 | intptr_t ref,
227 | float sx,
228 | float sy,
229 | float ex,
230 | float ey,
231 | const uint32_t colors[],
232 | const float stops[],
233 | int count);
234 | RIVE_DELEGATE_VOID(radialGradient,
235 | intptr_t ref,
236 | float cx,
237 | float cy,
238 | float radius,
239 | const uint32_t colors[],
240 | const float stops[],
241 | int count);
242 | RIVE_DELEGATE_VOID(thickness, intptr_t ref, float thickness);
243 | RIVE_DELEGATE_VOID(join, intptr_t ref, int join);
244 | RIVE_DELEGATE_VOID(cap, intptr_t ref, int cap);
245 | RIVE_DELEGATE_VOID(blendMode, intptr_t ref, int blendMode);
246 | };
247 |
248 | static Delegates s_delegates;
249 |
250 | RenderPaintSharp(intptr_t managedRef) : m_ref(managedRef) {}
251 | RenderPaintSharp(const RenderPaintSharp&) = delete;
252 | RenderPaintSharp& operator=(const RenderPaintSharp&) = delete;
253 | ~RenderPaintSharp() { s_delegates.release(m_ref); };
254 |
255 | struct Shader : public RenderShader
256 | {
257 | virtual void apply(intptr_t) const = 0;
258 | };
259 |
260 | struct LinearGradientShader : public Shader
261 | {
262 | LinearGradientShader(float sx,
263 | float sy,
264 | float ex,
265 | float ey,
266 | const uint32_t colors[],
267 | const float stops[],
268 | int n) :
269 | sx(sx),
270 | sy(sy),
271 | ex(ex),
272 | ey(ey),
273 | colors(colors, colors + n),
274 | stops(stops, stops + n)
275 | {}
276 | void apply(intptr_t ref) const override
277 | {
278 | s_delegates.linearGradient(ref,
279 | sx,
280 | sy,
281 | ex,
282 | ey,
283 | colors.data(),
284 | stops.data(),
285 | (int)colors.size());
286 | }
287 | const float sx, sy;
288 | const float ex, ey;
289 | const std::vector colors;
290 | const std::vector stops;
291 | };
292 |
293 | struct RadialGradientShader : public Shader
294 | {
295 | RadialGradientShader(float cx,
296 | float cy,
297 | float radius,
298 | const uint32_t colors[],
299 | const float stops[],
300 | int n) :
301 | cx(cx),
302 | cy(cy),
303 | radius(radius),
304 | colors(colors, colors + n),
305 | stops(stops, stops + n)
306 | {}
307 | void apply(intptr_t ref) const override
308 | {
309 | s_delegates.radialGradient(ref,
310 | cx,
311 | cy,
312 | radius,
313 | colors.data(),
314 | stops.data(),
315 | (int)colors.size());
316 | }
317 | const float cx, cy;
318 | const float radius;
319 | const std::vector colors;
320 | const std::vector stops;
321 | };
322 |
323 | void style(RenderPaintStyle style) override
324 | {
325 | s_delegates.style(m_ref, (int)style);
326 | }
327 | void color(uint32_t value) override { s_delegates.color(m_ref, value); }
328 | void thickness(float value) override
329 | {
330 | s_delegates.thickness(m_ref, value);
331 | }
332 | void join(StrokeJoin value) override
333 | {
334 | s_delegates.join(m_ref, (int)value);
335 | }
336 | void cap(StrokeCap value) override { s_delegates.cap(m_ref, (int)value); }
337 | void blendMode(BlendMode value) override
338 | {
339 | s_delegates.blendMode(m_ref, (int)value);
340 | }
341 | void shader(rcp shader) override
342 | {
343 | ((Shader*)shader.get())->apply(m_ref);
344 | }
345 | void invalidateStroke() override {}
346 |
347 | const intptr_t m_ref;
348 | };
349 |
350 | RenderPaintSharp::Delegates RenderPaintSharp::s_delegates{};
351 |
352 | RIVE_DLL_VOID RenderPaint_RegisterDelegates(
353 | RenderPaintSharp::Delegates delegates)
354 | {
355 | RenderPaintSharp::s_delegates = delegates;
356 | }
357 |
358 | ////////////////////////////////////////////////////////////////////////////////////////////////////
359 |
360 | class RendererSharp : public Renderer
361 | {
362 | public:
363 | struct Delegates
364 | {
365 | RIVE_DELEGATE_VOID(save, intptr_t ref);
366 | RIVE_DELEGATE_VOID(restore, intptr_t ref);
367 | RIVE_DELEGATE_VOID(transform,
368 | intptr_t ref,
369 | float,
370 | float,
371 | float,
372 | float,
373 | float,
374 | float);
375 | RIVE_DELEGATE_VOID(drawPath,
376 | intptr_t ref,
377 | intptr_t path,
378 | intptr_t paint);
379 | RIVE_DELEGATE_VOID(clipPath, intptr_t ref, intptr_t path);
380 | RIVE_DELEGATE_VOID(drawImage,
381 | intptr_t ref,
382 | intptr_t image,
383 | int blendMode,
384 | float opacity);
385 | RIVE_DELEGATE_VOID(drawImageMesh,
386 | intptr_t ref,
387 | intptr_t image,
388 | const float* vertices,
389 | const float* texcoords,
390 | int vertexCount,
391 | const uint16_t* indices,
392 | int indexCount,
393 | int blendMode,
394 | float opacity);
395 | };
396 |
397 | static Delegates s_delegates;
398 |
399 | RendererSharp(intptr_t managedRef) : m_ref(managedRef) {}
400 | RendererSharp(const RendererSharp&) = delete;
401 | RendererSharp& operator=(const RendererSharp&) = delete;
402 |
403 | void save() override { s_delegates.save(m_ref); }
404 | void restore() override { s_delegates.restore(m_ref); }
405 | void transform(const Mat2D& m) override
406 | {
407 | s_delegates
408 | .transform(m_ref, m.xx(), m.xy(), m.yx(), m.yy(), m.tx(), m.ty());
409 | }
410 | void drawPath(RenderPath* path, RenderPaint* paint) override
411 | {
412 | s_delegates.drawPath(m_ref,
413 | static_cast(path)->m_ref,
414 | static_cast(paint)->m_ref);
415 | }
416 | void clipPath(RenderPath* path) override
417 | {
418 | s_delegates.clipPath(m_ref, static_cast(path)->m_ref);
419 | }
420 | void drawImage(const RenderImage* image,
421 | BlendMode blendMode,
422 | float opacity) override
423 | {
424 | s_delegates.drawImage(
425 | m_ref,
426 | static_cast(image)->m_ref,
427 | (int)blendMode,
428 | opacity);
429 | }
430 | void drawImageMesh(const RenderImage* image,
431 | rcp vertices_f32,
432 | rcp uvCoords_f32,
433 | rcp indices_u16,
434 | uint32_t vertexCount,
435 | uint32_t indexCount,
436 | BlendMode blendMode,
437 | float opacity) override
438 | {
439 | // We need our buffers and counts to agree.
440 | assert(vertices_f32->sizeInBytes() == vertexCount * sizeof(Vec2D));
441 | assert(uvCoords_f32->sizeInBytes() == vertexCount * sizeof(Vec2D));
442 | assert(indices_u16->sizeInBytes() == indexCount * sizeof(uint16_t));
443 |
444 | // The local matrix is ignored for SkCanvas::drawVertices, so we have to
445 | // manually scale the UVs to match Skia's convention.
446 | float w = (float)image->width();
447 | float h = (float)image->height();
448 | int n = vertexCount * 2;
449 | const float* uvs =
450 | static_cast(uvCoords_f32.get())->f32s();
451 | std::vector denormUVs(n);
452 | for (int i = 0; i < n; i += 2)
453 | {
454 | denormUVs[i] = uvs[i] * w;
455 | denormUVs[i + 1] = uvs[i + 1] * h;
456 | }
457 |
458 | s_delegates.drawImageMesh(
459 | m_ref,
460 | static_cast(image)->m_ref,
461 | static_cast(vertices_f32.get())->f32s(),
462 | denormUVs.data(),
463 | vertexCount,
464 | static_cast(indices_u16.get())->u16s(),
465 | indexCount,
466 | (int)blendMode,
467 | opacity);
468 | }
469 |
470 | private:
471 | intptr_t m_ref;
472 | };
473 |
474 | RendererSharp::Delegates RendererSharp::s_delegates{};
475 |
476 | RIVE_DLL_VOID Renderer_RegisterDelegates(RendererSharp::Delegates delegates)
477 | {
478 | RendererSharp::s_delegates = delegates;
479 | }
480 |
481 | struct ComputeAlignmentArgs
482 | {
483 | int32_t fit;
484 | float alignX;
485 | float alignY;
486 | AABB frame;
487 | AABB content;
488 | Mat2D matrix;
489 | };
490 |
491 | RIVE_DLL_VOID Renderer_ComputeAlignment(ComputeAlignmentArgs* args)
492 | {
493 | args->matrix = computeAlignment((Fit)args->fit,
494 | Alignment(args->alignX, args->alignY),
495 | args->frame,
496 | args->content);
497 | }
498 |
499 | ////////////////////////////////////////////////////////////////////////////////////////////////////
500 |
501 | class FactorySharp : public Factory
502 | {
503 | public:
504 | struct Delegates
505 | {
506 | RIVE_DELEGATE_VOID(release, intptr_t ref);
507 | RIVE_DELEGATE_INTPTR(makeRenderPath,
508 | intptr_t ref,
509 | intptr_t ptsArray, // Vec2D/SkPoint[nPts]
510 | int nPts,
511 | intptr_t verbsArray, // uint8_t/PathVerb[nPts]
512 | int nVerbs,
513 | int fillRule);
514 | RIVE_DELEGATE_INTPTR(makeEmptyRenderPath, intptr_t ref);
515 | RIVE_DELEGATE_INTPTR(makeRenderPaint, intptr_t ref);
516 | RIVE_DELEGATE_INTPTR(decodeImage,
517 | intptr_t ref,
518 | intptr_t bytesArray,
519 | int nBytes);
520 | };
521 |
522 | static Delegates s_delegates;
523 |
524 | FactorySharp(intptr_t managedRef) : m_ref(managedRef) {}
525 | ~FactorySharp() { s_delegates.release(m_ref); }
526 |
527 | rcp makeRenderBuffer(RenderBufferType type,
528 | RenderBufferFlags flags,
529 | size_t sizeInBytes) override
530 | {
531 | return make_rcp(type, flags, sizeInBytes);
532 | }
533 |
534 | rcp makeLinearGradient(float sx,
535 | float sy,
536 | float ex,
537 | float ey,
538 | const ColorInt colors[], // [count]
539 | const float stops[], // [count]
540 | size_t count) override
541 | {
542 | return rcp(
543 | new RenderPaintSharp::LinearGradientShader(sx,
544 | sy,
545 | ex,
546 | ey,
547 | colors,
548 | stops,
549 | (int)count));
550 | }
551 |
552 | rcp makeRadialGradient(float cx,
553 | float cy,
554 | float radius,
555 | const ColorInt colors[], // [count]
556 | const float stops[], // [count]
557 | size_t count) override
558 | {
559 | return rcp(
560 | new RenderPaintSharp::RadialGradientShader(cx,
561 | cy,
562 | radius,
563 | colors,
564 | stops,
565 | (int)count));
566 | }
567 |
568 | rcp makeRenderPath(RawPath& rawPath, FillRule fillRule) override
569 | {
570 | return make_rcp(s_delegates.makeRenderPath(
571 | m_ref,
572 | reinterpret_cast(rawPath.points().data()),
573 | rawPath.points().size(),
574 | reinterpret_cast(rawPath.verbs().data()),
575 | rawPath.verbs().size(),
576 | (int)fillRule));
577 | }
578 |
579 | rcp makeEmptyRenderPath() override
580 | {
581 | return make_rcp(
582 | s_delegates.makeEmptyRenderPath(m_ref));
583 | }
584 |
585 | rcp makeRenderPaint() override
586 | {
587 | return make_rcp(s_delegates.makeRenderPaint(m_ref));
588 | }
589 |
590 | rcp decodeImage(Span bytes) override
591 | {
592 | intptr_t managedRef =
593 | s_delegates.decodeImage(m_ref,
594 | reinterpret_cast(bytes.data()),
595 | bytes.count());
596 | return managedRef ? make_rcp(managedRef) : nullptr;
597 | }
598 |
599 | const intptr_t m_ref;
600 | };
601 |
602 | FactorySharp::Delegates FactorySharp::s_delegates{};
603 |
604 | RIVE_DLL_VOID Factory_RegisterDelegates(FactorySharp::Delegates delegates)
605 | {
606 | FactorySharp::s_delegates = delegates;
607 | }
608 |
609 | ////////////////////////////////////////////////////////////////////////////////////////////////////
610 |
611 | class NativeScene
612 | {
613 | public:
614 | NativeScene(std::unique_ptr factory) :
615 | m_Factory(std::move(factory))
616 | {}
617 |
618 | bool loadFile(const uint8_t* fileBytes, int length)
619 | {
620 | m_Scene.reset();
621 | m_Artboard.reset();
622 | m_File = File::import(Span(fileBytes, length),
623 | m_Factory.get());
624 | return m_File != nullptr;
625 | }
626 |
627 | bool loadArtboard(const char* name)
628 | {
629 | m_Scene.reset();
630 | if (m_File)
631 | {
632 | m_Artboard = (name && name[0]) ? m_File->artboardNamed(name)
633 | : m_File->artboardDefault();
634 | }
635 | return m_Artboard != nullptr;
636 | }
637 |
638 | bool loadStateMachine(const char* name)
639 | {
640 | if (m_Artboard)
641 | {
642 | m_Scene = (name && name[0]) ? m_Artboard->stateMachineNamed(name)
643 | : m_Artboard->stateMachineAt(0);
644 | }
645 | return m_Scene != nullptr;
646 | }
647 |
648 | bool loadAnimation(const char* name)
649 | {
650 | if (m_Artboard)
651 | {
652 | m_Scene = (name && name[0]) ? m_Artboard->animationNamed(name)
653 | : m_Artboard->animationAt(0);
654 | }
655 | return m_Scene != nullptr;
656 | }
657 |
658 | bool setBool(const char* name, bool value)
659 | {
660 | if (SMIBool * input; m_Scene && (input = m_Scene->getBool(name)))
661 | {
662 | input->value(value);
663 | return true;
664 | }
665 | return false;
666 | }
667 |
668 | bool setNumber(const char* name, float value)
669 | {
670 | if (SMINumber * input; m_Scene && (input = m_Scene->getNumber(name)))
671 | {
672 | input->value(value);
673 | return true;
674 | }
675 | return false;
676 | }
677 |
678 | bool fireTrigger(const char* name)
679 | {
680 | if (SMITrigger * input; m_Scene && (input = m_Scene->getTrigger(name)))
681 | {
682 | input->fire();
683 | return true;
684 | }
685 | return false;
686 | }
687 |
688 | Scene* scene() { return m_Scene.get(); }
689 |
690 | private:
691 | std::unique_ptr m_Factory;
692 | std::unique_ptr m_File;
693 | std::unique_ptr m_Artboard;
694 | std::unique_ptr m_Scene;
695 | };
696 |
697 | RIVE_DLL_INTPTR Scene_New(intptr_t managedFactory)
698 | {
699 | return reinterpret_cast(
700 | new NativeScene(std::make_unique(managedFactory)));
701 | }
702 |
703 | RIVE_DLL_VOID Scene_Delete(intptr_t ref)
704 | {
705 | delete reinterpret_cast(ref);
706 | }
707 |
708 | RIVE_DLL_INT8_BOOL Scene_LoadFile(intptr_t ref,
709 | const uint8_t* fileBytes,
710 | int length)
711 | {
712 | return reinterpret_cast(ref)->loadFile(fileBytes, length);
713 | }
714 |
715 | RIVE_DLL_INT8_BOOL Scene_LoadArtboard(intptr_t ref, const char* name)
716 | {
717 | return reinterpret_cast(ref)->loadArtboard(name);
718 | }
719 |
720 | RIVE_DLL_INT8_BOOL Scene_LoadStateMachine(intptr_t ref, const char* name)
721 | {
722 | return reinterpret_cast(ref)->loadStateMachine(name);
723 | }
724 |
725 | RIVE_DLL_INT8_BOOL Scene_LoadAnimation(intptr_t ref, const char* name)
726 | {
727 | return reinterpret_cast(ref)->loadAnimation(name);
728 | }
729 |
730 | RIVE_DLL_INT8_BOOL Scene_SetBool(intptr_t ref, const char* name, int32_t value)
731 | {
732 | return reinterpret_cast(ref)->setBool(name, value);
733 | }
734 |
735 | RIVE_DLL_INT8_BOOL Scene_SetNumber(intptr_t ref, const char* name, float value)
736 | {
737 | return reinterpret_cast(ref)->setNumber(name, value);
738 | }
739 |
740 | RIVE_DLL_INT8_BOOL Scene_FireTrigger(intptr_t ref, const char* name)
741 | {
742 | return reinterpret_cast(ref)->fireTrigger(name);
743 | }
744 |
745 | RIVE_DLL_FLOAT Scene_Width(intptr_t ref)
746 | {
747 | if (Scene* scene = reinterpret_cast(ref)->scene())
748 | {
749 | return scene->width();
750 | }
751 | return 0;
752 | }
753 |
754 | RIVE_DLL_FLOAT Scene_Height(intptr_t ref)
755 | {
756 | if (Scene* scene = reinterpret_cast(ref)->scene())
757 | {
758 | return scene->height();
759 | }
760 | return 0;
761 | }
762 |
763 | RIVE_DLL_INT32 Scene_Name(intptr_t ref, char* charArray)
764 | {
765 | if (Scene* scene = reinterpret_cast(ref)->scene())
766 | {
767 | const std::string& name = scene->name();
768 | int32_t numChars = name.length();
769 | if (charArray)
770 | {
771 | memcpy(charArray, name.c_str(), numChars);
772 | }
773 | return numChars;
774 | }
775 | return 0;
776 | }
777 |
778 | RIVE_DLL_INT32 Scene_Loop(intptr_t ref)
779 | {
780 | if (Scene* scene = reinterpret_cast(ref)->scene())
781 | {
782 | return (int)reinterpret_cast(ref)->scene()->loop();
783 | }
784 | return 0;
785 | }
786 |
787 | RIVE_DLL_INT8_BOOL Scene_IsTranslucent(intptr_t ref)
788 | {
789 | if (Scene* scene = reinterpret_cast(ref)->scene())
790 | {
791 | return reinterpret_cast(ref)->scene()->isTranslucent();
792 | }
793 | return 0;
794 | }
795 |
796 | RIVE_DLL_FLOAT Scene_DurationSeconds(intptr_t ref)
797 | {
798 | if (Scene* scene = reinterpret_cast(ref)->scene())
799 | {
800 | return scene->durationSeconds();
801 | }
802 | return 0;
803 | }
804 |
805 | RIVE_DLL_INT8_BOOL Scene_AdvanceAndApply(intptr_t ref, float elapsedSeconds)
806 | {
807 | if (Scene* scene = reinterpret_cast(ref)->scene())
808 | {
809 | return scene->advanceAndApply(elapsedSeconds);
810 | }
811 | return false;
812 | }
813 |
814 | RIVE_DLL_VOID Scene_Draw(intptr_t ref, intptr_t renderer)
815 | {
816 | if (Scene* scene = reinterpret_cast(ref)->scene())
817 | {
818 | RendererSharp nativeRenderer(renderer);
819 | return scene->draw(&nativeRenderer);
820 | }
821 | }
822 |
823 | RIVE_DLL_VOID Scene_PointerDown(intptr_t ref, Vec2D pos)
824 | {
825 | if (Scene* scene = reinterpret_cast(ref)->scene())
826 | {
827 | scene->pointerDown(pos);
828 | }
829 | }
830 |
831 | RIVE_DLL_VOID Scene_PointerMove(intptr_t ref, Vec2D pos)
832 | {
833 | if (Scene* scene = reinterpret_cast(ref)->scene())
834 | {
835 | scene->pointerMove(pos);
836 | }
837 | }
838 |
839 | RIVE_DLL_VOID Scene_PointerUp(intptr_t ref, Vec2D pos)
840 | {
841 | if (Scene* scene = reinterpret_cast(ref)->scene())
842 | {
843 | scene->pointerUp(pos);
844 | }
845 | }
846 |
--------------------------------------------------------------------------------