diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..34c32cc
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+## [0.0.1] - 2020-07-08 16:29:36
+
+- Loading Rive 2 files.
+- Use a Rive widget to display them.
+- Drive animations with SimpleAnimation or make your own from RiveAnimationController.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..aec1d17
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Rive
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bc3d347
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+# Rive
+[Flutter package](https://pub.dev/packages/rive) for Rive 2.
+
+## Bring Your Apps and Games to Life with Real-Time Animation
+[Rive](https://rive.app/) is a real-time interactive design tool that allows you to design, animate, and immediately integrate your assets into any platform thanks to our open source runtimes.
+
+## Add to pubspec.yaml
+```yaml
+dependencies:
+ rive: ^0.0.1
+```
+
+## Example
+See how to use it in [example](example/).
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..823aaa5
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,122 @@
+analyzer:
+ strong-mode:
+ implicit-casts: false
+ implicit-dynamic: false
+ errors:
+ unused_import: error
+
+linter:
+ rules:
+ - always_put_required_named_parameters_first
+ - always_require_non_null_named_parameters
+ - annotate_overrides
+ # - avoid_annotating_with_dynamic
+ - avoid_bool_literals_in_conditional_expressions
+ - avoid_catches_without_on_clauses
+ - avoid_catching_errors
+ - avoid_classes_with_only_static_members
+ - avoid_double_and_int_checks
+ - avoid_empty_else
+ - avoid_field_initializers_in_const_classes
+ - avoid_implementing_value_types
+ - avoid_init_to_null
+ - avoid_js_rounded_ints
+ - avoid_null_checks_in_equality_operators
+ - avoid_relative_lib_imports
+ - avoid_return_types_on_setters
+ - avoid_returning_null
+ - avoid_returning_null_for_future
+ - avoid_returning_null_for_void
+ - avoid_returning_this
+ - avoid_setters_without_getters
+ - avoid_shadowing_type_parameters
+ - avoid_single_cascade_in_expression_statements
+ - avoid_slow_async_io
+ - avoid_types_as_parameter_names
+ - avoid_unused_constructor_parameters
+ - avoid_void_async
+ - await_only_futures
+ - camel_case_types
+ - cancel_subscriptions
+ - close_sinks
+ - constant_identifier_names
+ - control_flow_in_finally
+ - curly_braces_in_flow_control_structures
+ - directives_ordering
+ - empty_catches
+ - empty_constructor_bodies
+ - empty_statements
+ - file_names
+ - hash_and_equals
+ - implementation_imports
+# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
+ - iterable_contains_unrelated_type
+ - join_return_with_assignment
+ - library_names
+ - library_prefixes
+ - lines_longer_than_80_chars
+ - list_remove_unrelated_type
+# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
+ - no_adjacent_strings_in_list
+ - no_duplicate_case_values
+ - non_constant_identifier_names
+ - null_closures
+ - one_member_abstracts
+ - only_throw_errors
+ - overridden_fields
+ - package_api_docs
+ - package_names
+ - package_prefixed_library_names
+ - parameter_assignments
+ - prefer_adjacent_string_concatenation
+ - prefer_asserts_in_initializer_lists
+ - prefer_collection_literals
+ - prefer_conditional_assignment
+ - prefer_const_constructors
+ - prefer_const_constructors_in_immutables
+ - prefer_const_declarations
+ - prefer_const_literals_to_create_immutables
+ - prefer_constructors_over_static_methods
+ - prefer_contains
+ - prefer_equal_for_default_values
+ - prefer_final_fields
+ - prefer_final_in_for_each
+ - prefer_foreach
+ - prefer_function_declarations_over_variables
+ - prefer_initializing_formals
+ - prefer_is_empty
+ - prefer_is_not_empty
+ - prefer_iterable_whereType
+ # - prefer_mixin
+ - prefer_null_aware_operators
+ - prefer_typing_uninitialized_variables
+ - prefer_void_to_null
+ - recursive_getters
+ - slash_for_doc_comments
+ - sort_pub_dependencies
+ - sort_unnamed_constructors_first
+ - test_types_in_equals
+ - throw_in_finally
+ - type_annotate_public_apis
+ - type_init_formals
+ - unawaited_futures
+ - unnecessary_await_in_return
+ - unnecessary_brace_in_string_interps
+ - unnecessary_const
+ - unnecessary_getters_setters
+ - unnecessary_lambdas
+ - unnecessary_new
+ - unnecessary_null_aware_assignments
+ - unnecessary_null_in_if_null_operators
+ - unnecessary_overrides
+ - unnecessary_parenthesis
+ - unnecessary_statements
+ - unnecessary_this
+ - unrelated_type_equality_checks
+ - use_full_hex_values_for_flutter_colors
+ - use_rethrow_when_possible
+ - use_setters_to_change_properties
+ - use_string_buffers
+ - use_to_and_as_if_applicable
+ - valid_regexps
+ - void_checks
diff --git a/example/.gitignore b/example/.gitignore
new file mode 100644
index 0000000..f3c2053
--- /dev/null
+++ b/example/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Exceptions to above rules.
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
diff --git a/example/.metadata b/example/.metadata
new file mode 100644
index 0000000..cfa9183
--- /dev/null
+++ b/example/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: 456d80b9ddd74b4b5ca3b77bbfb70ab0e05d3fa8
+ channel: dev
+
+project_type: app
diff --git a/example/README.md b/example/README.md
new file mode 100644
index 0000000..1045679
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,16 @@
+# rive_example
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
+
+For help getting started with Flutter, view our
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/example/android/.gitignore b/example/android/.gitignore
new file mode 100644
index 0000000..bc2100d
--- /dev/null
+++ b/example/android/.gitignore
@@ -0,0 +1,7 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
new file mode 100644
index 0000000..251d759
--- /dev/null
+++ b/example/android/app/build.gradle
@@ -0,0 +1,63 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 28
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.rive_example"
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..2796d8f
--- /dev/null
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..47b3954
--- /dev/null
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/kotlin/com/example/rive_example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/rive_example/MainActivity.kt
new file mode 100644
index 0000000..f0aa16f
--- /dev/null
+++ b/example/android/app/src/main/kotlin/com/example/rive_example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.rive_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..1f83a33
--- /dev/null
+++ b/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..2796d8f
--- /dev/null
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
new file mode 100644
index 0000000..3100ad2
--- /dev/null
+++ b/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.3.50'
+ repositories {
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
new file mode 100644
index 0000000..38c8d45
--- /dev/null
+++ b/example/android/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.jvmargs=-Xmx1536M
+android.enableR8=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..296b146
--- /dev/null
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
diff --git a/example/android/settings.gradle b/example/android/settings.gradle
new file mode 100644
index 0000000..d3b6a40
--- /dev/null
+++ b/example/android/settings.gradle
@@ -0,0 +1,15 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/example/assets/blue_artboard.riv b/example/assets/blue_artboard.riv
new file mode 100644
index 0000000..53252c8
Binary files /dev/null and b/example/assets/blue_artboard.riv differ
diff --git a/example/assets/colors_juice.riv b/example/assets/colors_juice.riv
new file mode 100644
index 0000000..4231d67
Binary files /dev/null and b/example/assets/colors_juice.riv differ
diff --git a/example/assets/cubic_work.riv b/example/assets/cubic_work.riv
new file mode 100644
index 0000000..8e85833
Binary files /dev/null and b/example/assets/cubic_work.riv differ
diff --git a/example/assets/draworderanimation_3.riv b/example/assets/draworderanimation_3.riv
new file mode 100644
index 0000000..29ea0ac
Binary files /dev/null and b/example/assets/draworderanimation_3.riv differ
diff --git a/example/assets/jet_fighter.riv b/example/assets/jet_fighter.riv
new file mode 100644
index 0000000..2cbbae7
Binary files /dev/null and b/example/assets/jet_fighter.riv differ
diff --git a/example/assets/ping_pong.riv b/example/assets/ping_pong.riv
new file mode 100644
index 0000000..0a513b8
Binary files /dev/null and b/example/assets/ping_pong.riv differ
diff --git a/example/assets/tape_deck.riv b/example/assets/tape_deck.riv
new file mode 100644
index 0000000..96fcaa6
Binary files /dev/null and b/example/assets/tape_deck.riv differ
diff --git a/example/assets/web_&_desktop_2.riv b/example/assets/web_&_desktop_2.riv
new file mode 100644
index 0000000..09329cb
Binary files /dev/null and b/example/assets/web_&_desktop_2.riv differ
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
new file mode 100644
index 0000000..e96ef60
--- /dev/null
+++ b/example/ios/.gitignore
@@ -0,0 +1,32 @@
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 0000000..6b4c0f7
--- /dev/null
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 8.0
+
+
diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig
new file mode 100644
index 0000000..592ceee
--- /dev/null
+++ b/example/ios/Flutter/Debug.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig
new file mode 100644
index 0000000..592ceee
--- /dev/null
+++ b/example/ios/Flutter/Release.xcconfig
@@ -0,0 +1 @@
+#include "Generated.xcconfig"
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..4f54eeb
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,503 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 97C146F11CF9000F007C117D /* Supporting Files */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 97C146F11CF9000F007C117D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 97C146E61CF9000F007C117D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1020;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Thin Binary";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ };
+ 9740EEB61CF901F6004384FC /* Run Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Run Script";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C146FB1CF9000F007C117D /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C147001CF9000F007C117D /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 249021D3217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Profile;
+ };
+ 249021D4217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.riveExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.riveExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.example.riveExample;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147031CF9000F007C117D /* Debug */,
+ 97C147041CF9000F007C117D /* Release */,
+ 249021D3217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ 249021D4217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..a28140c
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000..f9b0d7c
--- /dev/null
+++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift
new file mode 100644
index 0000000..70693e4
--- /dev/null
+++ b/example/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..d36b1fa
--- /dev/null
+++ b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,122 @@
+{
+ "images" : [
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "83.5x83.5",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-83.5x83.5@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "Icon-App-1024x1024@1x.png",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 0000000..dc9ada4
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100644
index 0000000..28c6bf0
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100644
index 0000000..2ccbfd9
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100644
index 0000000..f091b6b
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100644
index 0000000..4cde121
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100644
index 0000000..d0ef06e
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100644
index 0000000..dcdc230
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100644
index 0000000..2ccbfd9
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100644
index 0000000..c8f9ed8
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100644
index 0000000..a6d6b86
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100644
index 0000000..a6d6b86
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100644
index 0000000..75b2d16
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100644
index 0000000..c4df70d
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100644
index 0000000..6a84f41
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100644
index 0000000..d0e1f58
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 0000000..0bedcf2
--- /dev/null
+++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100644
index 0000000..89c2725
--- /dev/null
+++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -0,0 +1,5 @@
+# Launch Screen Assets
+
+You can customize the launch screen with your own desired assets by replacing the image files in this directory.
+
+You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f2e259c
--- /dev/null
+++ b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f3c2851
--- /dev/null
+++ b/example/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
new file mode 100644
index 0000000..ec3815f
--- /dev/null
+++ b/example/ios/Runner/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ rive_example
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 0000000..308a2a5
--- /dev/null
+++ b/example/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
diff --git a/example/lib/main.dart b/example/lib/main.dart
new file mode 100644
index 0000000..88729b6
--- /dev/null
+++ b/example/lib/main.dart
@@ -0,0 +1,84 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:rive/rive.dart';
+
+void main() {
+ runApp(MyApp());
+}
+
+class MyApp extends StatefulWidget {
+ @override
+ _MyAppState createState() => _MyAppState();
+}
+
+class _MyAppState extends State with SingleTickerProviderStateMixin {
+ @override
+ Widget build(BuildContext context) {
+ return const MaterialApp(
+ home: MyHomePage(),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({Key key}) : super(key: key);
+
+ @override
+ _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State {
+ void _togglePlay() {
+ setState(() => _controller.isActive = !_controller.isActive);
+ }
+
+ /// We track if the animation is playing by whether or not the controller is
+ /// running.
+ bool get isPlaying => _controller?.isActive ?? false;
+
+ Artboard _riveArtboard;
+ RiveAnimationController _controller;
+ @override
+ void initState() {
+ super.initState();
+
+ // Load the animation file from the bundle, note that you could also
+ // download this. The RiveFile just expects a list of bytes.
+ rootBundle.load('assets/colors_juice.riv').then(
+ (data) async {
+ var file = RiveFile();
+ // Load the RiveFile from the binary data.
+ var success = file.import(data);
+ if (success) {
+ // The artboard is the root of the animation and is what gets drawn
+ // into the Rive widget.
+ var artboard = file.mainArtboard;
+ // Add a controller to play back a known animation on the main/default
+ // artboard.We store a reference to it so we can toggle playback.
+ artboard.addController(
+ _controller = SimpleAnimation('walk'),
+ );
+ setState(() => _riveArtboard = artboard);
+ }
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Center(
+ child: _riveArtboard == null
+ ? const SizedBox()
+ : Rive(artboard: _riveArtboard),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: _togglePlay,
+ tooltip: isPlaying ? 'Pause' : 'Play',
+ child: Icon(
+ isPlaying ? Icons.pause : Icons.play_arrow,
+ ),
+ ),
+ );
+ }
+}
diff --git a/example/macos/.gitignore b/example/macos/.gitignore
new file mode 100644
index 0000000..d2fd377
--- /dev/null
+++ b/example/macos/.gitignore
@@ -0,0 +1,6 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/xcuserdata/
diff --git a/example/macos/Flutter/Flutter-Debug.xcconfig b/example/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 0000000..c2efd0b
--- /dev/null
+++ b/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1 @@
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/example/macos/Flutter/Flutter-Release.xcconfig b/example/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 0000000..c2efd0b
--- /dev/null
+++ b/example/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1 @@
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift
new file mode 100644
index 0000000..cccf817
--- /dev/null
+++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -0,0 +1,10 @@
+//
+// Generated file. Do not edit.
+//
+
+import FlutterMacOS
+import Foundation
+
+
+func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+}
diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..d85789b
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,596 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; };
+ 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; };
+ D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */,
+ 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */,
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
+ 33CC10ED2044A3C60003C045 /* rive_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "rive_example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
+ 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D73912F022F37F9E000D13A0 /* App.framework in Frameworks */,
+ 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* rive_example.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ D73912EF22F37F9E000D13A0 /* App.framework */,
+ 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */,
+ );
+ path = Flutter;
+ sourceTree = "";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* rive_example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "The Flutter Authors";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..ac06267
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/macos/Runner/AppDelegate.swift b/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 0000000..d53ef64
--- /dev/null
+++ b/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..a2ec33f
--- /dev/null
+++ b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 0000000..3c4935a
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 0000000..ed4cc16
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 0000000..483be61
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 0000000..bcbf36d
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 0000000..9c0a652
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 0000000..e71a726
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 0000000..8a31fe2
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ
diff --git a/example/macos/Runner/Base.lproj/MainMenu.xib b/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 0000000..537341a
--- /dev/null
+++ b/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 0000000..37afbe8
--- /dev/null
+++ b/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = rive_example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = com.example.riveExample
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2020 com.example. All rights reserved.
diff --git a/example/macos/Runner/Configs/Debug.xcconfig b/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 0000000..36b0fd9
--- /dev/null
+++ b/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/example/macos/Runner/Configs/Release.xcconfig b/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 0000000..dff4f49
--- /dev/null
+++ b/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/example/macos/Runner/Configs/Warnings.xcconfig b/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 0000000..42bcbf4
--- /dev/null
+++ b/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 0000000..dddb8a3
--- /dev/null
+++ b/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.network.server
+
+
+
diff --git a/example/macos/Runner/Info.plist b/example/macos/Runner/Info.plist
new file mode 100644
index 0000000..4789daa
--- /dev/null
+++ b/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/example/macos/Runner/MainFlutterWindow.swift b/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 0000000..2722837
--- /dev/null
+++ b/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+
diff --git a/example/pubspec.lock b/example/pubspec.lock
new file mode 100644
index 0000000..82c9d2b
--- /dev/null
+++ b/example/pubspec.lock
@@ -0,0 +1,160 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.4.2"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ charcode:
+ dependency: transitive
+ description:
+ name: charcode
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.3"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.14.13"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ graphs:
+ dependency: transitive
+ description:
+ name: graphs
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.8"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.8"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.7.0"
+ rive:
+ dependency: "direct main"
+ description:
+ path: ".."
+ relative: true
+ source: path
+ version: "0.0.1"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.7.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.9.5"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.5"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.17"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.8"
+sdks:
+ dart: ">=2.9.0-14.0.dev <3.0.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
new file mode 100644
index 0000000..9454133
--- /dev/null
+++ b/example/pubspec.yaml
@@ -0,0 +1,25 @@
+name: rive_example
+description: A new Flutter project.
+
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+version: 1.0.0+1
+
+environment:
+ sdk: ">=2.7.0 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ rive:
+ path: ../
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+flutter:
+ uses-material-design: true
+
+ assets:
+ - assets/
diff --git a/example/web/favicon.png b/example/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
Binary files /dev/null and b/example/web/favicon.png differ
diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
Binary files /dev/null and b/example/web/icons/Icon-192.png differ
diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
Binary files /dev/null and b/example/web/icons/Icon-512.png differ
diff --git a/example/web/index.html b/example/web/index.html
new file mode 100644
index 0000000..4fe6fac
--- /dev/null
+++ b/example/web/index.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rive_example
+
+
+
+
+
+
+
+
diff --git a/example/web/manifest.json b/example/web/manifest.json
new file mode 100644
index 0000000..1113c75
--- /dev/null
+++ b/example/web/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "rive_example",
+ "short_name": "rive_example",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/lib/rive.dart b/lib/rive.dart
new file mode 100644
index 0000000..d9393ee
--- /dev/null
+++ b/lib/rive.dart
@@ -0,0 +1,6 @@
+export 'package:rive/src/rive_file.dart';
+export 'package:rive/src/rive.dart';
+export 'package:rive/src/rive_core/rive_animation_controller.dart';
+export 'package:rive/src/controllers/simple_controller.dart';
+export 'package:rive/src/controllers/simple_controller.dart';
+export 'package:rive/src/rive_core/artboard.dart';
diff --git a/lib/src/animation_list.dart b/lib/src/animation_list.dart
new file mode 100644
index 0000000..cbf095c
--- /dev/null
+++ b/lib/src/animation_list.dart
@@ -0,0 +1,20 @@
+import 'dart:collection';
+import 'package:rive/src/rive_core/animation/animation.dart';
+
+// TODO: figure out how to make this cleaner.
+class AnimationList extends ListBase {
+ final List _values = [];
+ List get values => _values;
+
+ @override
+ int get length => _values.length;
+
+ @override
+ set length(int value) => _values.length = value;
+
+ @override
+ Animation operator [](int index) => _values[index];
+
+ @override
+ void operator []=(int index, Animation value) => _values[index] = value;
+}
diff --git a/lib/src/container_children.dart b/lib/src/container_children.dart
new file mode 100644
index 0000000..cfe9c75
--- /dev/null
+++ b/lib/src/container_children.dart
@@ -0,0 +1,20 @@
+import 'dart:collection';
+import 'package:rive/src/rive_core/component.dart';
+
+// TODO: figure out how to make this cleaner.
+class ContainerChildren extends ListBase {
+ final List _values = [];
+ List get values => _values;
+
+ @override
+ int get length => _values.length;
+
+ @override
+ set length(int value) => _values.length = value;
+
+ @override
+ Component operator [](int index) => _values[index];
+
+ @override
+ void operator []=(int index, Component value) => _values[index] = value;
+}
diff --git a/lib/src/controllers/simple_controller.dart b/lib/src/controllers/simple_controller.dart
new file mode 100644
index 0000000..62d3e49
--- /dev/null
+++ b/lib/src/controllers/simple_controller.dart
@@ -0,0 +1,85 @@
+import 'package:rive/src/rive_core/animation/linear_animation.dart';
+import 'package:rive/src/rive_core/animation/loop.dart';
+import 'package:rive/src/rive_core/rive_animation_controller.dart';
+import 'package:rive/src/runtime_artboard.dart';
+
+/// A simple [RiveAnimationController] that plays back a LinearAnimation defined
+/// by an artist. All playback parameters (looping, speed, keyframes) are artist
+/// defined in the Rive editor.
+class SimpleAnimation extends RiveAnimationController {
+ LinearAnimation _animation;
+ double _time = 0;
+ int _direction = 1;
+ final String animationName;
+ SimpleAnimation(this.animationName);
+
+ @override
+ bool init(RuntimeArtboard artboard) {
+ _animation = artboard.animations.firstWhere(
+ (animation) => animation.name == animationName,
+ orElse: () => null,
+ ) as LinearAnimation;
+ isActive = true;
+ return _animation != null;
+ }
+
+ @override
+ void apply(RuntimeArtboard artboard, double elapsedSeconds) {
+ _animation.apply(_time, coreContext: artboard);
+ _time += elapsedSeconds * _animation.speed * _direction;
+
+ double frames = _time * _animation.fps;
+
+ var start = _animation.enableWorkArea ? _animation.workStart : 0;
+ var end =
+ _animation.enableWorkArea ? _animation.workEnd : _animation.duration;
+ var range = end - start;
+
+ switch (_animation.loop) {
+ case Loop.oneShot:
+ if (frames > end) {
+ isActive = false;
+ frames = end.toDouble();
+ _time = frames / _animation.fps;
+ }
+ break;
+ case Loop.loop:
+ if (frames >= end) {
+ frames = _time * _animation.fps;
+ frames = start + (frames - start) % range;
+ _time = frames / _animation.fps;
+ }
+ break;
+ case Loop.pingPong:
+ // ignore: literal_only_boolean_expressions
+ while (true) {
+ if (_direction == 1 && frames >= end) {
+ _direction = -1;
+ frames = end + (end - frames);
+ _time = frames / _animation.fps;
+ } else if (_direction == -1 && frames < start) {
+ _direction = 1;
+ frames = start + (start - frames);
+ _time = frames / _animation.fps;
+ } else {
+ // we're within the range, we can stop fixing. We do this in a
+ // loop to fix conditions when time has advanced so far that we've
+ // ping-ponged back and forth a few times in a single frame. We
+ // want to accomodate for this in cases where animations are not
+ // advanced on regular intervals.
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ @override
+ void dispose() {}
+
+ @override
+ void onActivate() {}
+
+ @override
+ void onDeactivate() {}
+}
diff --git a/lib/src/core/core.dart b/lib/src/core/core.dart
new file mode 100644
index 0000000..28ac56b
--- /dev/null
+++ b/lib/src/core/core.dart
@@ -0,0 +1,33 @@
+export 'package:rive/src/fractional/fractional.dart';
+export 'package:rive/src/animation_list.dart';
+export 'package:rive/src/container_children.dart';
+export 'package:rive/src/drawable_list.dart';
+export 'package:rive/src/runtime_artboard.dart';
+export 'package:rive/src/generated/rive_core_context.dart';
+
+
+typedef PropertyChangeCallback = void Function(dynamic from, dynamic to);
+typedef BatchAddCallback = void Function();
+
+
+abstract class Core {
+ covariant T context;
+ int get coreType;
+ int id;
+ Set get coreTypes => {};
+
+ void onAddedDirty();
+ void onAdded();
+ void onRemoved();
+}
+
+abstract class CoreContext{
+ Core makeCoreInstance(int typeKey);
+ T resolve(int id);
+ void markDependencyOrderDirty();
+ bool markDependenciesDirty(covariant Core rootObject);
+ void removeObject(T object);
+ T addObject(T object);
+ void markNeedsAdvance();
+ void dirty(void Function() dirt);
+}
diff --git a/lib/src/core/field_types/core_bool_type.dart b/lib/src/core/field_types/core_bool_type.dart
new file mode 100644
index 0000000..8c5b8e5
--- /dev/null
+++ b/lib/src/core/field_types/core_bool_type.dart
@@ -0,0 +1,11 @@
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+
+class CoreBoolType extends CoreFieldType {
+ @override
+ bool deserialize(BinaryReader reader) => reader.readInt8() == 1;
+
+ @override
+ bool lerp(bool from, bool to, double f) => from;
+}
diff --git a/lib/src/core/field_types/core_double_type.dart b/lib/src/core/field_types/core_double_type.dart
new file mode 100644
index 0000000..8722d30
--- /dev/null
+++ b/lib/src/core/field_types/core_double_type.dart
@@ -0,0 +1,12 @@
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+class CoreDoubleType extends CoreFieldType {
+ @override
+ double deserialize(BinaryReader reader) => reader.buffer.lengthInBytes == 4
+ ? reader.readFloat32()
+ : reader.readFloat64();
+
+ @override
+ double lerp(double from, double to, double f) => from + (to - from) * f;
+}
diff --git a/lib/src/core/field_types/core_field_type.dart b/lib/src/core/field_types/core_field_type.dart
new file mode 100644
index 0000000..c9e3f7d
--- /dev/null
+++ b/lib/src/core/field_types/core_field_type.dart
@@ -0,0 +1,6 @@
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+abstract class CoreFieldType {
+ T deserialize(BinaryReader reader);
+ T lerp(T from, T to, double f);
+}
diff --git a/lib/src/core/field_types/core_fractional_index_type.dart b/lib/src/core/field_types/core_fractional_index_type.dart
new file mode 100644
index 0000000..9ecb79a
--- /dev/null
+++ b/lib/src/core/field_types/core_fractional_index_type.dart
@@ -0,0 +1,18 @@
+
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+
+class CoreFractionalIndexType extends CoreFieldType {
+ @override
+ FractionalIndex deserialize(BinaryReader reader) {
+ var numerator = reader.readVarInt();
+ var denominator = reader.readVarInt();
+ return FractionalIndex(numerator, denominator);
+ }
+
+ @override
+ FractionalIndex lerp(FractionalIndex from, FractionalIndex to, double f) =>
+ from;
+}
diff --git a/lib/src/core/field_types/core_int_type.dart b/lib/src/core/field_types/core_int_type.dart
new file mode 100644
index 0000000..056a0f0
--- /dev/null
+++ b/lib/src/core/field_types/core_int_type.dart
@@ -0,0 +1,11 @@
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+
+class CoreIntType extends CoreFieldType {
+ @override
+ int deserialize(BinaryReader reader) => reader.readVarInt();
+
+ @override
+ int lerp(int from, int to, double f) => (from + (to - from) * f).round();
+}
diff --git a/lib/src/core/field_types/core_string_type.dart b/lib/src/core/field_types/core_string_type.dart
new file mode 100644
index 0000000..1599a9c
--- /dev/null
+++ b/lib/src/core/field_types/core_string_type.dart
@@ -0,0 +1,10 @@
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+
+class CoreStringType extends CoreFieldType {
+ @override
+ String deserialize(BinaryReader reader) => reader.readString();
+
+ @override
+ String lerp(String from, String to, double f) => from;
+}
diff --git a/lib/src/drawable_list.dart b/lib/src/drawable_list.dart
new file mode 100644
index 0000000..7d5c21f
--- /dev/null
+++ b/lib/src/drawable_list.dart
@@ -0,0 +1,23 @@
+import 'dart:collection';
+
+import 'package:rive/src/rive_core/drawable.dart';
+
+// TODO: figure out how to make this cleaner.
+class DrawableList extends ListBase {
+ final List _values = [];
+ List get values => _values;
+
+ @override
+ int get length => _values.length;
+
+ @override
+ set length(int value) => _values.length = value;
+
+ @override
+ Drawable operator [](int index) => _values[index];
+
+ @override
+ void operator []=(int index, Drawable value) => _values[index] = value;
+
+ void sortDrawables() => sort((a, b) => a.drawOrder.compareTo(b.drawOrder));
+}
diff --git a/lib/src/fractional/fractional.dart b/lib/src/fractional/fractional.dart
new file mode 100644
index 0000000..ce5bd6e
--- /dev/null
+++ b/lib/src/fractional/fractional.dart
@@ -0,0 +1,226 @@
+import 'dart:collection';
+
+const _minIndex = FractionalIndex.min();
+const _maxIndex = FractionalIndex.max();
+
+abstract class FractionallyIndexedList extends ListBase {
+ final List _values;
+ FractionalIndex orderOf(T value);
+ List get values => _values;
+
+ @override
+ int get length => _values.length;
+
+ @override
+ set length(int value) => _values.length = value;
+
+ @override
+ T operator [](int index) => _values[index];
+
+ @override
+ void operator []=(int index, T value) => _values[index] = value;
+
+ FractionallyIndexedList({
+ List values,
+ bool initOrder = true,
+ }) : _values = values ?? [] {
+ if (_values.isEmpty || !initOrder) {
+ return;
+ }
+ // Otherwise spread them evenly across our range using 1/2 as the midpoint.
+ int mid = _values.length ~/ 2;
+ var midIndex = const FractionalIndex(1, 2);
+ setOrderOf(_values[mid], midIndex);
+
+ var lastIndex = midIndex;
+ for (int i = mid + 1; i < _values.length; i++) {
+ var index = FractionalIndex.between(lastIndex, _maxIndex);
+ setOrderOf(_values[i], index);
+ lastIndex = index;
+ }
+
+ lastIndex = midIndex;
+ for (int i = mid - 1; i >= 0; i--) {
+ var index = FractionalIndex.between(_minIndex, lastIndex);
+ setOrderOf(_values[i], index);
+ lastIndex = index;
+ }
+ }
+
+ FractionallyIndexedList.raw(List values) : _values = values ?? [];
+
+ void setOrderOf(T value, FractionalIndex order);
+
+ /// Set the fractional indices to match the current order of the items. This
+ /// is a pretty heavy operation as it could change the fractional index of
+ /// every item in the list. Should be used sparingly for cases that really
+ /// require it.
+ void setFractionalIndices() {
+ var previousIndex = _minIndex;
+ for (final item in _values) {
+ var index = FractionalIndex.between(previousIndex, _maxIndex);
+ setOrderOf(item, index);
+ previousIndex = index;
+ }
+ }
+
+ int _compareIndex(T a, T b) {
+ return orderOf(a).compareTo(orderOf(b));
+ }
+
+ void sortFractional() => _values.sort(_compareIndex);
+
+ bool validateFractional([FractionalIndex minimum]) {
+ var previousIndex = minimum ?? _minIndex;
+
+ bool wasValid = true;
+ for (final item in _values) {
+ var order = orderOf(item);
+ if (order == null) {
+ wasValid = false;
+ continue;
+ }
+ if (order.compareTo(previousIndex) > 0) {
+ previousIndex = order;
+ }
+ }
+ if (wasValid) {
+ return true;
+ }
+
+ for (final item in _values) {
+ if (orderOf(item) == null) {
+ var index = FractionalIndex.between(previousIndex, _maxIndex);
+ setOrderOf(item, index);
+ previousIndex = index;
+ }
+ }
+ return false;
+ }
+
+ @override
+ void add(T item) {
+ assert(!contains(item));
+ _values.add(item);
+ }
+
+ @override
+ bool remove(Object element) => _values.remove(element);
+
+ void append(T item) {
+ assert(!contains(item));
+ var previousIndex = _values.isEmpty ? _minIndex : orderOf(_values.last);
+ setOrderOf(item, FractionalIndex.between(previousIndex, _maxIndex));
+ _values.add(item);
+ }
+
+ /// Gets the next fractional index safely, most of the other methods here
+ /// assume the index list is valid, this one does not. It'll find the best
+ /// next index. It's meant to be used to help implementations patch up their
+ /// lists as necessary.
+ FractionalIndex get nextFractionalIndex {
+ var previousIndex = _minIndex;
+ for (final item in _values) {
+ var order = orderOf(item);
+ if (order == null) {
+ continue;
+ }
+ if (order.compareTo(previousIndex) > 0) {
+ previousIndex = order;
+ }
+ }
+ return FractionalIndex.between(previousIndex, _maxIndex);
+ }
+
+ void prepend(T item) {
+ assert(!contains(item));
+ var firstIndex = _values.isEmpty ? _maxIndex : orderOf(_values.first);
+ setOrderOf(item, FractionalIndex.between(_minIndex, firstIndex));
+ _values.add(item);
+ }
+
+ void moveToEnd(T item) {
+ var previousIndex = _values.isEmpty ? _minIndex : orderOf(_values.last);
+ setOrderOf(item, FractionalIndex.between(previousIndex, _maxIndex));
+ }
+
+ void moveToStart(T item) {
+ var firstIndex = _values.isEmpty ? _maxIndex : orderOf(_values.first);
+ setOrderOf(item, FractionalIndex.between(_minIndex, firstIndex));
+ }
+
+ void move(T item, {T before, T after}) {
+ setOrderOf(
+ item,
+ FractionalIndex.between(before != null ? orderOf(before) : _minIndex,
+ after != null ? orderOf(after) : _maxIndex));
+ }
+}
+
+class FractionalIndex {
+ final int numerator;
+ final int denominator;
+
+ const FractionalIndex(this.numerator, this.denominator)
+ : assert(numerator < denominator);
+
+ const FractionalIndex.min()
+ : numerator = 0,
+ denominator = 1;
+ const FractionalIndex.max()
+ : numerator = 1,
+ denominator = 1;
+
+ int compareTo(FractionalIndex other) {
+ return numerator * other.denominator - denominator * other.numerator;
+ }
+
+ FractionalIndex combine(FractionalIndex other) {
+ return FractionalIndex(
+ numerator + other.numerator, denominator + other.denominator);
+ }
+
+ factory FractionalIndex.between(FractionalIndex a, FractionalIndex b) {
+ return FractionalIndex(
+ a.numerator + b.numerator, a.denominator + b.denominator)
+ .reduce();
+ }
+
+ FractionalIndex reduce() {
+ int x = numerator, y = denominator;
+ while (y != 0) {
+ int t = y;
+ y = x % y;
+ x = t;
+ }
+ return FractionalIndex(numerator ~/ x, denominator ~/ x);
+ }
+
+ bool operator <(FractionalIndex other) {
+ return compareTo(other) < 0;
+ }
+
+ bool operator >(FractionalIndex other) {
+ return compareTo(other) > 0;
+ }
+
+ @override
+ bool operator ==(Object other) =>
+ other is FractionalIndex &&
+ other.numerator == numerator &&
+ other.denominator == denominator;
+
+ @override
+ int get hashCode => szudzik(numerator, denominator);
+
+ @override
+ String toString() => '$numerator/$denominator';
+}
+
+/// Szudzik's function for hashing two ints together
+int szudzik(int a, int b) {
+ // a and b must be >= 0
+ int x = a.abs();
+ int y = b.abs();
+ return x >= y ? x * x + x + y : x + y * y;
+}
diff --git a/lib/src/generated/animation/animation_base.dart b/lib/src/generated/animation/animation_base.dart
new file mode 100644
index 0000000..60ebe7f
--- /dev/null
+++ b/lib/src/generated/animation/animation_base.dart
@@ -0,0 +1,34 @@
+/// Core automatically generated
+/// lib/src/generated/animation/animation_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class AnimationBase extends Core {
+ static const int typeKey = 27;
+ @override
+ int get coreType => AnimationBase.typeKey;
+ @override
+ Set get coreTypes => {AnimationBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Name field with key 55.
+ String _name;
+ static const int namePropertyKey = 55;
+
+ /// Name of the animation.
+ String get name => _name;
+
+ /// Change the [_name] field value.
+ /// [nameChanged] will be invoked only if the field's value has changed.
+ set name(String value) {
+ if (_name == value) {
+ return;
+ }
+ String from = _name;
+ _name = value;
+ nameChanged(from, value);
+ }
+
+ void nameChanged(String from, String to);
+}
diff --git a/lib/src/generated/animation/cubic_interpolator_base.dart b/lib/src/generated/animation/cubic_interpolator_base.dart
new file mode 100644
index 0000000..a3ebd40
--- /dev/null
+++ b/lib/src/generated/animation/cubic_interpolator_base.dart
@@ -0,0 +1,89 @@
+/// Core automatically generated
+/// lib/src/generated/animation/cubic_interpolator_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class CubicInterpolatorBase extends Core {
+ static const int typeKey = 28;
+ @override
+ int get coreType => CubicInterpolatorBase.typeKey;
+ @override
+ Set get coreTypes => {CubicInterpolatorBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// X1 field with key 63.
+ double _x1 = 0.42;
+ static const int x1PropertyKey = 63;
+ double get x1 => _x1;
+
+ /// Change the [_x1] field value.
+ /// [x1Changed] will be invoked only if the field's value has changed.
+ set x1(double value) {
+ if (_x1 == value) {
+ return;
+ }
+ double from = _x1;
+ _x1 = value;
+ x1Changed(from, value);
+ }
+
+ void x1Changed(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Y1 field with key 64.
+ double _y1 = 0;
+ static const int y1PropertyKey = 64;
+ double get y1 => _y1;
+
+ /// Change the [_y1] field value.
+ /// [y1Changed] will be invoked only if the field's value has changed.
+ set y1(double value) {
+ if (_y1 == value) {
+ return;
+ }
+ double from = _y1;
+ _y1 = value;
+ y1Changed(from, value);
+ }
+
+ void y1Changed(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// X2 field with key 65.
+ double _x2 = 0.58;
+ static const int x2PropertyKey = 65;
+ double get x2 => _x2;
+
+ /// Change the [_x2] field value.
+ /// [x2Changed] will be invoked only if the field's value has changed.
+ set x2(double value) {
+ if (_x2 == value) {
+ return;
+ }
+ double from = _x2;
+ _x2 = value;
+ x2Changed(from, value);
+ }
+
+ void x2Changed(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Y2 field with key 66.
+ double _y2 = 1;
+ static const int y2PropertyKey = 66;
+ double get y2 => _y2;
+
+ /// Change the [_y2] field value.
+ /// [y2Changed] will be invoked only if the field's value has changed.
+ set y2(double value) {
+ if (_y2 == value) {
+ return;
+ }
+ double from = _y2;
+ _y2 = value;
+ y2Changed(from, value);
+ }
+
+ void y2Changed(double from, double to);
+}
diff --git a/lib/src/generated/animation/keyed_object_base.dart b/lib/src/generated/animation/keyed_object_base.dart
new file mode 100644
index 0000000..9baa2ec
--- /dev/null
+++ b/lib/src/generated/animation/keyed_object_base.dart
@@ -0,0 +1,34 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyed_object_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class KeyedObjectBase extends Core {
+ static const int typeKey = 25;
+ @override
+ int get coreType => KeyedObjectBase.typeKey;
+ @override
+ Set get coreTypes => {KeyedObjectBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// ObjectId field with key 51.
+ int _objectId;
+ static const int objectIdPropertyKey = 51;
+
+ /// Identifier used to track the object that is keyed.
+ int get objectId => _objectId;
+
+ /// Change the [_objectId] field value.
+ /// [objectIdChanged] will be invoked only if the field's value has changed.
+ set objectId(int value) {
+ if (_objectId == value) {
+ return;
+ }
+ int from = _objectId;
+ _objectId = value;
+ objectIdChanged(from, value);
+ }
+
+ void objectIdChanged(int from, int to);
+}
diff --git a/lib/src/generated/animation/keyed_property_base.dart b/lib/src/generated/animation/keyed_property_base.dart
new file mode 100644
index 0000000..0d1361c
--- /dev/null
+++ b/lib/src/generated/animation/keyed_property_base.dart
@@ -0,0 +1,35 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyed_property_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class KeyedPropertyBase extends Core {
+ static const int typeKey = 26;
+ @override
+ int get coreType => KeyedPropertyBase.typeKey;
+ @override
+ Set get coreTypes => {KeyedPropertyBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// PropertyKey field with key 53.
+ int _propertyKey;
+ static const int propertyKeyPropertyKey = 53;
+
+ /// The property type that is keyed.
+ int get propertyKey => _propertyKey;
+
+ /// Change the [_propertyKey] field value.
+ /// [propertyKeyChanged] will be invoked only if the field's value has
+ /// changed.
+ set propertyKey(int value) {
+ if (_propertyKey == value) {
+ return;
+ }
+ int from = _propertyKey;
+ _propertyKey = value;
+ propertyKeyChanged(from, value);
+ }
+
+ void propertyKeyChanged(int from, int to);
+}
diff --git a/lib/src/generated/animation/keyframe_base.dart b/lib/src/generated/animation/keyframe_base.dart
new file mode 100644
index 0000000..1d123cf
--- /dev/null
+++ b/lib/src/generated/animation/keyframe_base.dart
@@ -0,0 +1,79 @@
+/// Core automatically generated lib/src/generated/animation/keyframe_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class KeyFrameBase extends Core {
+ static const int typeKey = 29;
+ @override
+ int get coreType => KeyFrameBase.typeKey;
+ @override
+ Set get coreTypes => {KeyFrameBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Frame field with key 67.
+ int _frame;
+ static const int framePropertyKey = 67;
+
+ /// Timecode as frame number can be converted to time by dividing by animation
+ /// fps.
+ int get frame => _frame;
+
+ /// Change the [_frame] field value.
+ /// [frameChanged] will be invoked only if the field's value has changed.
+ set frame(int value) {
+ if (_frame == value) {
+ return;
+ }
+ int from = _frame;
+ _frame = value;
+ frameChanged(from, value);
+ }
+
+ void frameChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// InterpolationType field with key 68.
+ int _interpolationType;
+ static const int interpolationTypePropertyKey = 68;
+
+ /// The type of interpolation index in KeyframeInterpolation applied to this
+ /// keyframe.
+ int get interpolationType => _interpolationType;
+
+ /// Change the [_interpolationType] field value.
+ /// [interpolationTypeChanged] will be invoked only if the field's value has
+ /// changed.
+ set interpolationType(int value) {
+ if (_interpolationType == value) {
+ return;
+ }
+ int from = _interpolationType;
+ _interpolationType = value;
+ interpolationTypeChanged(from, value);
+ }
+
+ void interpolationTypeChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// InterpolatorId field with key 69.
+ int _interpolatorId;
+ static const int interpolatorIdPropertyKey = 69;
+
+ /// The id of the custom interpolator used when interpolation is Cubic.
+ int get interpolatorId => _interpolatorId;
+
+ /// Change the [_interpolatorId] field value.
+ /// [interpolatorIdChanged] will be invoked only if the field's value has
+ /// changed.
+ set interpolatorId(int value) {
+ if (_interpolatorId == value) {
+ return;
+ }
+ int from = _interpolatorId;
+ _interpolatorId = value;
+ interpolatorIdChanged(from, value);
+ }
+
+ void interpolatorIdChanged(int from, int to);
+}
diff --git a/lib/src/generated/animation/keyframe_color_base.dart b/lib/src/generated/animation/keyframe_color_base.dart
new file mode 100644
index 0000000..a0e97b7
--- /dev/null
+++ b/lib/src/generated/animation/keyframe_color_base.dart
@@ -0,0 +1,33 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyframe_color_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/animation/keyframe_base.dart';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+
+abstract class KeyFrameColorBase extends KeyFrame {
+ static const int typeKey = 37;
+ @override
+ int get coreType => KeyFrameColorBase.typeKey;
+ @override
+ Set get coreTypes => {KeyFrameColorBase.typeKey, KeyFrameBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Value field with key 88.
+ int _value;
+ static const int valuePropertyKey = 88;
+ int get value => _value;
+
+ /// Change the [_value] field value.
+ /// [valueChanged] will be invoked only if the field's value has changed.
+ set value(int value) {
+ if (_value == value) {
+ return;
+ }
+ int from = _value;
+ _value = value;
+ valueChanged(from, value);
+ }
+
+ void valueChanged(int from, int to);
+}
diff --git a/lib/src/generated/animation/keyframe_double_base.dart b/lib/src/generated/animation/keyframe_double_base.dart
new file mode 100644
index 0000000..7598695
--- /dev/null
+++ b/lib/src/generated/animation/keyframe_double_base.dart
@@ -0,0 +1,33 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyframe_double_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/animation/keyframe_base.dart';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+
+abstract class KeyFrameDoubleBase extends KeyFrame {
+ static const int typeKey = 30;
+ @override
+ int get coreType => KeyFrameDoubleBase.typeKey;
+ @override
+ Set get coreTypes => {KeyFrameDoubleBase.typeKey, KeyFrameBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Value field with key 70.
+ double _value;
+ static const int valuePropertyKey = 70;
+ double get value => _value;
+
+ /// Change the [_value] field value.
+ /// [valueChanged] will be invoked only if the field's value has changed.
+ set value(double value) {
+ if (_value == value) {
+ return;
+ }
+ double from = _value;
+ _value = value;
+ valueChanged(from, value);
+ }
+
+ void valueChanged(double from, double to);
+}
diff --git a/lib/src/generated/animation/keyframe_draw_order_base.dart b/lib/src/generated/animation/keyframe_draw_order_base.dart
new file mode 100644
index 0000000..9fc13ae
--- /dev/null
+++ b/lib/src/generated/animation/keyframe_draw_order_base.dart
@@ -0,0 +1,15 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyframe_draw_order_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/animation/keyframe_base.dart';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+
+abstract class KeyFrameDrawOrderBase extends KeyFrame {
+ static const int typeKey = 32;
+ @override
+ int get coreType => KeyFrameDrawOrderBase.typeKey;
+ @override
+ Set get coreTypes =>
+ {KeyFrameDrawOrderBase.typeKey, KeyFrameBase.typeKey};
+}
diff --git a/lib/src/generated/animation/keyframe_draw_order_value_base.dart b/lib/src/generated/animation/keyframe_draw_order_value_base.dart
new file mode 100644
index 0000000..905d7d0
--- /dev/null
+++ b/lib/src/generated/animation/keyframe_draw_order_value_base.dart
@@ -0,0 +1,56 @@
+/// Core automatically generated
+/// lib/src/generated/animation/keyframe_draw_order_value_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class KeyFrameDrawOrderValueBase
+ extends Core {
+ static const int typeKey = 33;
+ @override
+ int get coreType => KeyFrameDrawOrderValueBase.typeKey;
+ @override
+ Set get coreTypes => {KeyFrameDrawOrderValueBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// DrawableId field with key 77.
+ int _drawableId;
+ static const int drawableIdPropertyKey = 77;
+
+ /// The id of the Drawable this KeyFrameDrawOrderValue's value is for.
+ int get drawableId => _drawableId;
+
+ /// Change the [_drawableId] field value.
+ /// [drawableIdChanged] will be invoked only if the field's value has changed.
+ set drawableId(int value) {
+ if (_drawableId == value) {
+ return;
+ }
+ int from = _drawableId;
+ _drawableId = value;
+ drawableIdChanged(from, value);
+ }
+
+ void drawableIdChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// Value field with key 78.
+ int _value;
+ static const int valuePropertyKey = 78;
+
+ /// The draw order value to apply to the Drawable.
+ int get value => _value;
+
+ /// Change the [_value] field value.
+ /// [valueChanged] will be invoked only if the field's value has changed.
+ set value(int value) {
+ if (_value == value) {
+ return;
+ }
+ int from = _value;
+ _value = value;
+ valueChanged(from, value);
+ }
+
+ void valueChanged(int from, int to);
+}
diff --git a/lib/src/generated/animation/linear_animation_base.dart b/lib/src/generated/animation/linear_animation_base.dart
new file mode 100644
index 0000000..de2b23d
--- /dev/null
+++ b/lib/src/generated/animation/linear_animation_base.dart
@@ -0,0 +1,164 @@
+/// Core automatically generated
+/// lib/src/generated/animation/linear_animation_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/animation/animation_base.dart';
+import 'package:rive/src/rive_core/animation/animation.dart';
+
+abstract class LinearAnimationBase extends Animation {
+ static const int typeKey = 31;
+ @override
+ int get coreType => LinearAnimationBase.typeKey;
+ @override
+ Set get coreTypes =>
+ {LinearAnimationBase.typeKey, AnimationBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Fps field with key 56.
+ int _fps = 60;
+ static const int fpsPropertyKey = 56;
+
+ /// Frames per second used to quantize keyframe times to discrete values that
+ /// match this rate.
+ int get fps => _fps;
+
+ /// Change the [_fps] field value.
+ /// [fpsChanged] will be invoked only if the field's value has changed.
+ set fps(int value) {
+ if (_fps == value) {
+ return;
+ }
+ int from = _fps;
+ _fps = value;
+ fpsChanged(from, value);
+ }
+
+ void fpsChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// Duration field with key 57.
+ int _duration = 60;
+ static const int durationPropertyKey = 57;
+
+ /// Duration expressed in number of frames.
+ int get duration => _duration;
+
+ /// Change the [_duration] field value.
+ /// [durationChanged] will be invoked only if the field's value has changed.
+ set duration(int value) {
+ if (_duration == value) {
+ return;
+ }
+ int from = _duration;
+ _duration = value;
+ durationChanged(from, value);
+ }
+
+ void durationChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// Speed field with key 58.
+ double _speed = 1;
+ static const int speedPropertyKey = 58;
+
+ /// Playback speed multiplier.
+ double get speed => _speed;
+
+ /// Change the [_speed] field value.
+ /// [speedChanged] will be invoked only if the field's value has changed.
+ set speed(double value) {
+ if (_speed == value) {
+ return;
+ }
+ double from = _speed;
+ _speed = value;
+ speedChanged(from, value);
+ }
+
+ void speedChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// LoopValue field with key 59.
+ int _loopValue = 0;
+ static const int loopValuePropertyKey = 59;
+
+ /// Loop value option matches Loop enumeration.
+ int get loopValue => _loopValue;
+
+ /// Change the [_loopValue] field value.
+ /// [loopValueChanged] will be invoked only if the field's value has changed.
+ set loopValue(int value) {
+ if (_loopValue == value) {
+ return;
+ }
+ int from = _loopValue;
+ _loopValue = value;
+ loopValueChanged(from, value);
+ }
+
+ void loopValueChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// WorkStart field with key 60.
+ int _workStart;
+ static const int workStartPropertyKey = 60;
+
+ /// Start of the work area in frames.
+ int get workStart => _workStart;
+
+ /// Change the [_workStart] field value.
+ /// [workStartChanged] will be invoked only if the field's value has changed.
+ set workStart(int value) {
+ if (_workStart == value) {
+ return;
+ }
+ int from = _workStart;
+ _workStart = value;
+ workStartChanged(from, value);
+ }
+
+ void workStartChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// WorkEnd field with key 61.
+ int _workEnd;
+ static const int workEndPropertyKey = 61;
+
+ /// End of the work area in frames.
+ int get workEnd => _workEnd;
+
+ /// Change the [_workEnd] field value.
+ /// [workEndChanged] will be invoked only if the field's value has changed.
+ set workEnd(int value) {
+ if (_workEnd == value) {
+ return;
+ }
+ int from = _workEnd;
+ _workEnd = value;
+ workEndChanged(from, value);
+ }
+
+ void workEndChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// EnableWorkArea field with key 62.
+ bool _enableWorkArea = false;
+ static const int enableWorkAreaPropertyKey = 62;
+
+ /// Whether or not the work area is enabled.
+ bool get enableWorkArea => _enableWorkArea;
+
+ /// Change the [_enableWorkArea] field value.
+ /// [enableWorkAreaChanged] will be invoked only if the field's value has
+ /// changed.
+ set enableWorkArea(bool value) {
+ if (_enableWorkArea == value) {
+ return;
+ }
+ bool from = _enableWorkArea;
+ _enableWorkArea = value;
+ enableWorkAreaChanged(from, value);
+ }
+
+ void enableWorkAreaChanged(bool from, bool to);
+}
diff --git a/lib/src/generated/artboard_base.dart b/lib/src/generated/artboard_base.dart
new file mode 100644
index 0000000..b8f3754
--- /dev/null
+++ b/lib/src/generated/artboard_base.dart
@@ -0,0 +1,144 @@
+/// Core automatically generated lib/src/generated/artboard_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+
+abstract class ArtboardBase extends ContainerComponent {
+ static const int typeKey = 1;
+ @override
+ int get coreType => ArtboardBase.typeKey;
+ @override
+ Set get coreTypes => {
+ ArtboardBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Width field with key 7.
+ double _width;
+ static const int widthPropertyKey = 7;
+
+ /// Width of the artboard.
+ double get width => _width;
+
+ /// Change the [_width] field value.
+ /// [widthChanged] will be invoked only if the field's value has changed.
+ set width(double value) {
+ if (_width == value) {
+ return;
+ }
+ double from = _width;
+ _width = value;
+ widthChanged(from, value);
+ }
+
+ void widthChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Height field with key 8.
+ double _height;
+ static const int heightPropertyKey = 8;
+
+ /// Height of the artboard.
+ double get height => _height;
+
+ /// Change the [_height] field value.
+ /// [heightChanged] will be invoked only if the field's value has changed.
+ set height(double value) {
+ if (_height == value) {
+ return;
+ }
+ double from = _height;
+ _height = value;
+ heightChanged(from, value);
+ }
+
+ void heightChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// X field with key 9.
+ double _x;
+ static const int xPropertyKey = 9;
+
+ /// X coordinate in editor world space.
+ double get x => _x;
+
+ /// Change the [_x] field value.
+ /// [xChanged] will be invoked only if the field's value has changed.
+ set x(double value) {
+ if (_x == value) {
+ return;
+ }
+ double from = _x;
+ _x = value;
+ xChanged(from, value);
+ }
+
+ void xChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Y field with key 10.
+ double _y;
+ static const int yPropertyKey = 10;
+
+ /// Y coordinate in editor world space.
+ double get y => _y;
+
+ /// Change the [_y] field value.
+ /// [yChanged] will be invoked only if the field's value has changed.
+ set y(double value) {
+ if (_y == value) {
+ return;
+ }
+ double from = _y;
+ _y = value;
+ yChanged(from, value);
+ }
+
+ void yChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// OriginX field with key 11.
+ double _originX;
+ static const int originXPropertyKey = 11;
+
+ /// Origin x in normalized coordinates (0 = center, -1 = left, 1 = right).
+ double get originX => _originX;
+
+ /// Change the [_originX] field value.
+ /// [originXChanged] will be invoked only if the field's value has changed.
+ set originX(double value) {
+ if (_originX == value) {
+ return;
+ }
+ double from = _originX;
+ _originX = value;
+ originXChanged(from, value);
+ }
+
+ void originXChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// OriginY field with key 12.
+ double _originY;
+ static const int originYPropertyKey = 12;
+
+ /// Origin y in normalized coordinates (0 = center, -1 = left, 1 = right).
+ double get originY => _originY;
+
+ /// Change the [_originY] field value.
+ /// [originYChanged] will be invoked only if the field's value has changed.
+ set originY(double value) {
+ if (_originY == value) {
+ return;
+ }
+ double from = _originY;
+ _originY = value;
+ originYChanged(from, value);
+ }
+
+ void originYChanged(double from, double to);
+}
diff --git a/lib/src/generated/backboard_base.dart b/lib/src/generated/backboard_base.dart
new file mode 100644
index 0000000..45ffb07
--- /dev/null
+++ b/lib/src/generated/backboard_base.dart
@@ -0,0 +1,12 @@
+/// Core automatically generated lib/src/generated/backboard_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class BackboardBase extends Core {
+ static const int typeKey = 23;
+ @override
+ int get coreType => BackboardBase.typeKey;
+ @override
+ Set get coreTypes => {BackboardBase.typeKey};
+}
diff --git a/lib/src/generated/component_base.dart b/lib/src/generated/component_base.dart
new file mode 100644
index 0000000..8988b8b
--- /dev/null
+++ b/lib/src/generated/component_base.dart
@@ -0,0 +1,55 @@
+/// Core automatically generated lib/src/generated/component_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/core/core.dart';
+
+abstract class ComponentBase extends Core {
+ static const int typeKey = 10;
+ @override
+ int get coreType => ComponentBase.typeKey;
+ @override
+ Set get coreTypes => {ComponentBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// Name field with key 4.
+ String _name;
+ static const int namePropertyKey = 4;
+
+ /// Non-unique identifier, used to give friendly names to elements in the
+ /// hierarchy. Runtimes provide an API for finding components by this [name].
+ String get name => _name;
+
+ /// Change the [_name] field value.
+ /// [nameChanged] will be invoked only if the field's value has changed.
+ set name(String value) {
+ if (_name == value) {
+ return;
+ }
+ String from = _name;
+ _name = value;
+ nameChanged(from, value);
+ }
+
+ void nameChanged(String from, String to);
+
+ /// --------------------------------------------------------------------------
+ /// ParentId field with key 5.
+ int _parentId;
+ static const int parentIdPropertyKey = 5;
+
+ /// Identifier used to track parent ContainerComponent.
+ int get parentId => _parentId;
+
+ /// Change the [_parentId] field value.
+ /// [parentIdChanged] will be invoked only if the field's value has changed.
+ set parentId(int value) {
+ if (_parentId == value) {
+ return;
+ }
+ int from = _parentId;
+ _parentId = value;
+ parentIdChanged(from, value);
+ }
+
+ void parentIdChanged(int from, int to);
+}
diff --git a/lib/src/generated/container_component_base.dart b/lib/src/generated/container_component_base.dart
new file mode 100644
index 0000000..ce108d9
--- /dev/null
+++ b/lib/src/generated/container_component_base.dart
@@ -0,0 +1,15 @@
+/// Core automatically generated
+/// lib/src/generated/container_component_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/rive_core/component.dart';
+
+abstract class ContainerComponentBase extends Component {
+ static const int typeKey = 11;
+ @override
+ int get coreType => ContainerComponentBase.typeKey;
+ @override
+ Set get coreTypes =>
+ {ContainerComponentBase.typeKey, ComponentBase.typeKey};
+}
diff --git a/lib/src/generated/drawable_base.dart b/lib/src/generated/drawable_base.dart
new file mode 100644
index 0000000..24d72e1
--- /dev/null
+++ b/lib/src/generated/drawable_base.dart
@@ -0,0 +1,59 @@
+/// Core automatically generated lib/src/generated/drawable_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/rive_core/node.dart';
+
+abstract class DrawableBase extends Node {
+ static const int typeKey = 13;
+ @override
+ int get coreType => DrawableBase.typeKey;
+ @override
+ Set get coreTypes => {
+ DrawableBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// DrawOrder field with key 22.
+ int _drawOrder;
+ static const int drawOrderPropertyKey = 22;
+ int get drawOrder => _drawOrder;
+
+ /// Change the [_drawOrder] field value.
+ /// [drawOrderChanged] will be invoked only if the field's value has changed.
+ set drawOrder(int value) {
+ if (_drawOrder == value) {
+ return;
+ }
+ int from = _drawOrder;
+ _drawOrder = value;
+ drawOrderChanged(from, value);
+ }
+
+ void drawOrderChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// BlendModeValue field with key 23.
+ int _blendModeValue = 3;
+ static const int blendModeValuePropertyKey = 23;
+ int get blendModeValue => _blendModeValue;
+
+ /// Change the [_blendModeValue] field value.
+ /// [blendModeValueChanged] will be invoked only if the field's value has
+ /// changed.
+ set blendModeValue(int value) {
+ if (_blendModeValue == value) {
+ return;
+ }
+ int from = _blendModeValue;
+ _blendModeValue = value;
+ blendModeValueChanged(from, value);
+ }
+
+ void blendModeValueChanged(int from, int to);
+}
diff --git a/lib/src/generated/node_base.dart b/lib/src/generated/node_base.dart
new file mode 100644
index 0000000..5054c00
--- /dev/null
+++ b/lib/src/generated/node_base.dart
@@ -0,0 +1,129 @@
+/// Core automatically generated lib/src/generated/node_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+
+abstract class NodeBase extends ContainerComponent {
+ static const int typeKey = 2;
+ @override
+ int get coreType => NodeBase.typeKey;
+ @override
+ Set get coreTypes =>
+ {NodeBase.typeKey, ContainerComponentBase.typeKey, ComponentBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// X field with key 13.
+ double _x = 0;
+ static const int xPropertyKey = 13;
+ double get x => _x;
+
+ /// Change the [_x] field value.
+ /// [xChanged] will be invoked only if the field's value has changed.
+ set x(double value) {
+ if (_x == value) {
+ return;
+ }
+ double from = _x;
+ _x = value;
+ xChanged(from, value);
+ }
+
+ void xChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Y field with key 14.
+ double _y = 0;
+ static const int yPropertyKey = 14;
+ double get y => _y;
+
+ /// Change the [_y] field value.
+ /// [yChanged] will be invoked only if the field's value has changed.
+ set y(double value) {
+ if (_y == value) {
+ return;
+ }
+ double from = _y;
+ _y = value;
+ yChanged(from, value);
+ }
+
+ void yChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Rotation field with key 15.
+ double _rotation = 0;
+ static const int rotationPropertyKey = 15;
+ double get rotation => _rotation;
+
+ /// Change the [_rotation] field value.
+ /// [rotationChanged] will be invoked only if the field's value has changed.
+ set rotation(double value) {
+ if (_rotation == value) {
+ return;
+ }
+ double from = _rotation;
+ _rotation = value;
+ rotationChanged(from, value);
+ }
+
+ void rotationChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// ScaleX field with key 16.
+ double _scaleX = 1;
+ static const int scaleXPropertyKey = 16;
+ double get scaleX => _scaleX;
+
+ /// Change the [_scaleX] field value.
+ /// [scaleXChanged] will be invoked only if the field's value has changed.
+ set scaleX(double value) {
+ if (_scaleX == value) {
+ return;
+ }
+ double from = _scaleX;
+ _scaleX = value;
+ scaleXChanged(from, value);
+ }
+
+ void scaleXChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// ScaleY field with key 17.
+ double _scaleY = 1;
+ static const int scaleYPropertyKey = 17;
+ double get scaleY => _scaleY;
+
+ /// Change the [_scaleY] field value.
+ /// [scaleYChanged] will be invoked only if the field's value has changed.
+ set scaleY(double value) {
+ if (_scaleY == value) {
+ return;
+ }
+ double from = _scaleY;
+ _scaleY = value;
+ scaleYChanged(from, value);
+ }
+
+ void scaleYChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Opacity field with key 18.
+ double _opacity = 1;
+ static const int opacityPropertyKey = 18;
+ double get opacity => _opacity;
+
+ /// Change the [_opacity] field value.
+ /// [opacityChanged] will be invoked only if the field's value has changed.
+ set opacity(double value) {
+ if (_opacity == value) {
+ return;
+ }
+ double from = _opacity;
+ _opacity = value;
+ opacityChanged(from, value);
+ }
+
+ void opacityChanged(double from, double to);
+}
diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart
new file mode 100644
index 0000000..fd73615
--- /dev/null
+++ b/lib/src/generated/rive_core_context.dart
@@ -0,0 +1,951 @@
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/core/field_types/core_bool_type.dart';
+import 'package:rive/src/core/field_types/core_double_type.dart';
+import 'package:rive/src/core/field_types/core_field_type.dart';
+import 'package:rive/src/core/field_types/core_int_type.dart';
+import 'package:rive/src/core/field_types/core_string_type.dart';
+import 'package:rive/src/generated/animation/animation_base.dart';
+import 'package:rive/src/generated/animation/cubic_interpolator_base.dart';
+import 'package:rive/src/generated/animation/keyed_object_base.dart';
+import 'package:rive/src/generated/animation/keyed_property_base.dart';
+import 'package:rive/src/generated/animation/keyframe_base.dart';
+import 'package:rive/src/generated/animation/keyframe_color_base.dart';
+import 'package:rive/src/generated/animation/keyframe_double_base.dart';
+import 'package:rive/src/generated/animation/keyframe_draw_order_base.dart';
+import 'package:rive/src/generated/animation/keyframe_draw_order_value_base.dart';
+import 'package:rive/src/generated/animation/linear_animation_base.dart';
+import 'package:rive/src/generated/artboard_base.dart';
+import 'package:rive/src/generated/backboard_base.dart';
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/drawable_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart';
+import 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart';
+import 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart';
+import 'package:rive/src/generated/shapes/ellipse_base.dart';
+import 'package:rive/src/generated/shapes/paint/fill_base.dart';
+import 'package:rive/src/generated/shapes/paint/gradient_stop_base.dart';
+import 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';
+import 'package:rive/src/generated/shapes/paint/radial_gradient_base.dart';
+import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
+import 'package:rive/src/generated/shapes/paint/solid_color_base.dart';
+import 'package:rive/src/generated/shapes/paint/stroke_base.dart';
+import 'package:rive/src/generated/shapes/parametric_path_base.dart';
+import 'package:rive/src/generated/shapes/path_composer_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/generated/shapes/points_path_base.dart';
+import 'package:rive/src/generated/shapes/rectangle_base.dart';
+import 'package:rive/src/generated/shapes/shape_base.dart';
+import 'package:rive/src/generated/shapes/straight_vertex_base.dart';
+import 'package:rive/src/generated/shapes/triangle_base.dart';
+import 'package:rive/src/rive_core/animation/animation.dart';
+import 'package:rive/src/rive_core/animation/cubic_interpolator.dart';
+import 'package:rive/src/rive_core/animation/keyed_object.dart';
+import 'package:rive/src/rive_core/animation/keyed_property.dart';
+import 'package:rive/src/rive_core/animation/keyframe_color.dart';
+import 'package:rive/src/rive_core/animation/keyframe_double.dart';
+import 'package:rive/src/rive_core/animation/keyframe_draw_order.dart';
+import 'package:rive/src/rive_core/animation/keyframe_draw_order_value.dart';
+import 'package:rive/src/rive_core/animation/linear_animation.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+import 'package:rive/src/rive_core/backboard.dart';
+import 'package:rive/src/rive_core/node.dart';
+import 'package:rive/src/rive_core/shapes/cubic_asymmetric_vertex.dart';
+import 'package:rive/src/rive_core/shapes/cubic_detached_vertex.dart';
+import 'package:rive/src/rive_core/shapes/cubic_mirrored_vertex.dart';
+import 'package:rive/src/rive_core/shapes/ellipse.dart';
+import 'package:rive/src/rive_core/shapes/paint/fill.dart';
+import 'package:rive/src/rive_core/shapes/paint/gradient_stop.dart';
+import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart';
+import 'package:rive/src/rive_core/shapes/paint/radial_gradient.dart';
+import 'package:rive/src/rive_core/shapes/paint/solid_color.dart';
+import 'package:rive/src/rive_core/shapes/paint/stroke.dart';
+import 'package:rive/src/rive_core/shapes/path_composer.dart';
+import 'package:rive/src/rive_core/shapes/points_path.dart';
+import 'package:rive/src/rive_core/shapes/rectangle.dart';
+import 'package:rive/src/rive_core/shapes/shape.dart';
+import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
+import 'package:rive/src/rive_core/shapes/triangle.dart';
+
+class RiveCoreContext {
+ static Core makeCoreInstance(int typeKey) {
+ switch (typeKey) {
+ case KeyedObjectBase.typeKey:
+ return KeyedObject();
+ case KeyedPropertyBase.typeKey:
+ return KeyedProperty();
+ case AnimationBase.typeKey:
+ return Animation();
+ case CubicInterpolatorBase.typeKey:
+ return CubicInterpolator();
+ case KeyFrameDoubleBase.typeKey:
+ return KeyFrameDouble();
+ case KeyFrameColorBase.typeKey:
+ return KeyFrameColor();
+ case LinearAnimationBase.typeKey:
+ return LinearAnimation();
+ case KeyFrameDrawOrderBase.typeKey:
+ return KeyFrameDrawOrder();
+ case KeyFrameDrawOrderValueBase.typeKey:
+ return KeyFrameDrawOrderValue();
+ case LinearGradientBase.typeKey:
+ return LinearGradient();
+ case RadialGradientBase.typeKey:
+ return RadialGradient();
+ case StrokeBase.typeKey:
+ return Stroke();
+ case SolidColorBase.typeKey:
+ return SolidColor();
+ case GradientStopBase.typeKey:
+ return GradientStop();
+ case FillBase.typeKey:
+ return Fill();
+ case NodeBase.typeKey:
+ return Node();
+ case ShapeBase.typeKey:
+ return Shape();
+ case StraightVertexBase.typeKey:
+ return StraightVertex();
+ case CubicAsymmetricVertexBase.typeKey:
+ return CubicAsymmetricVertex();
+ case PointsPathBase.typeKey:
+ return PointsPath();
+ case RectangleBase.typeKey:
+ return Rectangle();
+ case CubicMirroredVertexBase.typeKey:
+ return CubicMirroredVertex();
+ case TriangleBase.typeKey:
+ return Triangle();
+ case EllipseBase.typeKey:
+ return Ellipse();
+ case PathComposerBase.typeKey:
+ return PathComposer();
+ case CubicDetachedVertexBase.typeKey:
+ return CubicDetachedVertex();
+ case ArtboardBase.typeKey:
+ return Artboard();
+ case BackboardBase.typeKey:
+ return Backboard();
+ default:
+ return null;
+ }
+ }
+
+ static void setObjectProperty(Core object, int propertyKey, Object value) {
+ switch (propertyKey) {
+ case KeyedObjectBase.objectIdPropertyKey:
+ if (object is KeyedObjectBase && value is int) {
+ object.objectId = value;
+ }
+ break;
+ case KeyedPropertyBase.propertyKeyPropertyKey:
+ if (object is KeyedPropertyBase && value is int) {
+ object.propertyKey = value;
+ }
+ break;
+ case AnimationBase.namePropertyKey:
+ if (object is AnimationBase && value is String) {
+ object.name = value;
+ }
+ break;
+ case CubicInterpolatorBase.x1PropertyKey:
+ if (object is CubicInterpolatorBase && value is double) {
+ object.x1 = value;
+ }
+ break;
+ case CubicInterpolatorBase.y1PropertyKey:
+ if (object is CubicInterpolatorBase && value is double) {
+ object.y1 = value;
+ }
+ break;
+ case CubicInterpolatorBase.x2PropertyKey:
+ if (object is CubicInterpolatorBase && value is double) {
+ object.x2 = value;
+ }
+ break;
+ case CubicInterpolatorBase.y2PropertyKey:
+ if (object is CubicInterpolatorBase && value is double) {
+ object.y2 = value;
+ }
+ break;
+ case KeyFrameBase.framePropertyKey:
+ if (object is KeyFrameBase && value is int) {
+ object.frame = value;
+ }
+ break;
+ case KeyFrameBase.interpolationTypePropertyKey:
+ if (object is KeyFrameBase && value is int) {
+ object.interpolationType = value;
+ }
+ break;
+ case KeyFrameBase.interpolatorIdPropertyKey:
+ if (object is KeyFrameBase) {
+ if (value is int) {
+ object.interpolatorId = value;
+ } else if (value == null) {
+ object.interpolatorId = null;
+ }
+ }
+ break;
+ case KeyFrameDoubleBase.valuePropertyKey:
+ if (object is KeyFrameDoubleBase && value is double) {
+ object.value = value;
+ }
+ break;
+ case KeyFrameColorBase.valuePropertyKey:
+ if (object is KeyFrameColorBase && value is int) {
+ object.value = value;
+ }
+ break;
+ case LinearAnimationBase.fpsPropertyKey:
+ if (object is LinearAnimationBase && value is int) {
+ object.fps = value;
+ }
+ break;
+ case LinearAnimationBase.durationPropertyKey:
+ if (object is LinearAnimationBase && value is int) {
+ object.duration = value;
+ }
+ break;
+ case LinearAnimationBase.speedPropertyKey:
+ if (object is LinearAnimationBase && value is double) {
+ object.speed = value;
+ }
+ break;
+ case LinearAnimationBase.loopValuePropertyKey:
+ if (object is LinearAnimationBase && value is int) {
+ object.loopValue = value;
+ }
+ break;
+ case LinearAnimationBase.workStartPropertyKey:
+ if (object is LinearAnimationBase && value is int) {
+ object.workStart = value;
+ }
+ break;
+ case LinearAnimationBase.workEndPropertyKey:
+ if (object is LinearAnimationBase && value is int) {
+ object.workEnd = value;
+ }
+ break;
+ case LinearAnimationBase.enableWorkAreaPropertyKey:
+ if (object is LinearAnimationBase && value is bool) {
+ object.enableWorkArea = value;
+ }
+ break;
+ case KeyFrameDrawOrderValueBase.drawableIdPropertyKey:
+ if (object is KeyFrameDrawOrderValueBase && value is int) {
+ object.drawableId = value;
+ }
+ break;
+ case KeyFrameDrawOrderValueBase.valuePropertyKey:
+ if (object is KeyFrameDrawOrderValueBase && value is int) {
+ object.value = value;
+ }
+ break;
+ case ComponentBase.namePropertyKey:
+ if (object is ComponentBase && value is String) {
+ object.name = value;
+ }
+ break;
+ case ComponentBase.parentIdPropertyKey:
+ if (object is ComponentBase && value is int) {
+ object.parentId = value;
+ }
+ break;
+ case ShapePaintBase.isVisiblePropertyKey:
+ if (object is ShapePaintBase && value is bool) {
+ object.isVisible = value;
+ }
+ break;
+ case LinearGradientBase.startXPropertyKey:
+ if (object is LinearGradientBase && value is double) {
+ object.startX = value;
+ }
+ break;
+ case LinearGradientBase.startYPropertyKey:
+ if (object is LinearGradientBase && value is double) {
+ object.startY = value;
+ }
+ break;
+ case LinearGradientBase.endXPropertyKey:
+ if (object is LinearGradientBase && value is double) {
+ object.endX = value;
+ }
+ break;
+ case LinearGradientBase.endYPropertyKey:
+ if (object is LinearGradientBase && value is double) {
+ object.endY = value;
+ }
+ break;
+ case LinearGradientBase.opacityPropertyKey:
+ if (object is LinearGradientBase && value is double) {
+ object.opacity = value;
+ }
+ break;
+ case StrokeBase.thicknessPropertyKey:
+ if (object is StrokeBase && value is double) {
+ object.thickness = value;
+ }
+ break;
+ case StrokeBase.capPropertyKey:
+ if (object is StrokeBase && value is int) {
+ object.cap = value;
+ }
+ break;
+ case StrokeBase.joinPropertyKey:
+ if (object is StrokeBase && value is int) {
+ object.join = value;
+ }
+ break;
+ case StrokeBase.transformAffectsStrokePropertyKey:
+ if (object is StrokeBase && value is bool) {
+ object.transformAffectsStroke = value;
+ }
+ break;
+ case SolidColorBase.colorValuePropertyKey:
+ if (object is SolidColorBase && value is int) {
+ object.colorValue = value;
+ }
+ break;
+ case GradientStopBase.colorValuePropertyKey:
+ if (object is GradientStopBase && value is int) {
+ object.colorValue = value;
+ }
+ break;
+ case GradientStopBase.positionPropertyKey:
+ if (object is GradientStopBase && value is double) {
+ object.position = value;
+ }
+ break;
+ case FillBase.fillRulePropertyKey:
+ if (object is FillBase && value is int) {
+ object.fillRule = value;
+ }
+ break;
+ case NodeBase.xPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.x = value;
+ }
+ break;
+ case NodeBase.yPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.y = value;
+ }
+ break;
+ case NodeBase.rotationPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.rotation = value;
+ }
+ break;
+ case NodeBase.scaleXPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.scaleX = value;
+ }
+ break;
+ case NodeBase.scaleYPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.scaleY = value;
+ }
+ break;
+ case NodeBase.opacityPropertyKey:
+ if (object is NodeBase && value is double) {
+ object.opacity = value;
+ }
+ break;
+ case DrawableBase.drawOrderPropertyKey:
+ if (object is DrawableBase && value is int) {
+ object.drawOrder = value;
+ }
+ break;
+ case DrawableBase.blendModeValuePropertyKey:
+ if (object is DrawableBase && value is int) {
+ object.blendModeValue = value;
+ }
+ break;
+ case PathVertexBase.xPropertyKey:
+ if (object is PathVertexBase && value is double) {
+ object.x = value;
+ }
+ break;
+ case PathVertexBase.yPropertyKey:
+ if (object is PathVertexBase && value is double) {
+ object.y = value;
+ }
+ break;
+ case StraightVertexBase.radiusPropertyKey:
+ if (object is StraightVertexBase && value is double) {
+ object.radius = value;
+ }
+ break;
+ case CubicAsymmetricVertexBase.rotationPropertyKey:
+ if (object is CubicAsymmetricVertexBase && value is double) {
+ object.rotation = value;
+ }
+ break;
+ case CubicAsymmetricVertexBase.inDistancePropertyKey:
+ if (object is CubicAsymmetricVertexBase && value is double) {
+ object.inDistance = value;
+ }
+ break;
+ case CubicAsymmetricVertexBase.outDistancePropertyKey:
+ if (object is CubicAsymmetricVertexBase && value is double) {
+ object.outDistance = value;
+ }
+ break;
+ case PointsPathBase.isClosedPropertyKey:
+ if (object is PointsPathBase && value is bool) {
+ object.isClosed = value;
+ }
+ break;
+ case ParametricPathBase.widthPropertyKey:
+ if (object is ParametricPathBase && value is double) {
+ object.width = value;
+ }
+ break;
+ case ParametricPathBase.heightPropertyKey:
+ if (object is ParametricPathBase && value is double) {
+ object.height = value;
+ }
+ break;
+ case RectangleBase.cornerRadiusPropertyKey:
+ if (object is RectangleBase && value is double) {
+ object.cornerRadius = value;
+ }
+ break;
+ case CubicMirroredVertexBase.rotationPropertyKey:
+ if (object is CubicMirroredVertexBase && value is double) {
+ object.rotation = value;
+ }
+ break;
+ case CubicMirroredVertexBase.distancePropertyKey:
+ if (object is CubicMirroredVertexBase && value is double) {
+ object.distance = value;
+ }
+ break;
+ case CubicDetachedVertexBase.inRotationPropertyKey:
+ if (object is CubicDetachedVertexBase && value is double) {
+ object.inRotation = value;
+ }
+ break;
+ case CubicDetachedVertexBase.inDistancePropertyKey:
+ if (object is CubicDetachedVertexBase && value is double) {
+ object.inDistance = value;
+ }
+ break;
+ case CubicDetachedVertexBase.outRotationPropertyKey:
+ if (object is CubicDetachedVertexBase && value is double) {
+ object.outRotation = value;
+ }
+ break;
+ case CubicDetachedVertexBase.outDistancePropertyKey:
+ if (object is CubicDetachedVertexBase && value is double) {
+ object.outDistance = value;
+ }
+ break;
+ case ArtboardBase.widthPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.width = value;
+ }
+ break;
+ case ArtboardBase.heightPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.height = value;
+ }
+ break;
+ case ArtboardBase.xPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.x = value;
+ }
+ break;
+ case ArtboardBase.yPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.y = value;
+ }
+ break;
+ case ArtboardBase.originXPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.originX = value;
+ }
+ break;
+ case ArtboardBase.originYPropertyKey:
+ if (object is ArtboardBase && value is double) {
+ object.originY = value;
+ }
+ break;
+ }
+ }
+
+ static CoreFieldType intType = CoreIntType();
+ static CoreFieldType stringType = CoreStringType();
+ static CoreFieldType doubleType = CoreDoubleType();
+ static CoreFieldType colorType = CoreIntType();
+ static CoreFieldType boolType = CoreBoolType();
+ static CoreFieldType coreType(int propertyKey) {
+ switch (propertyKey) {
+ case KeyedObjectBase.objectIdPropertyKey:
+ case KeyedPropertyBase.propertyKeyPropertyKey:
+ case KeyFrameBase.framePropertyKey:
+ case KeyFrameBase.interpolationTypePropertyKey:
+ case KeyFrameBase.interpolatorIdPropertyKey:
+ case LinearAnimationBase.fpsPropertyKey:
+ case LinearAnimationBase.durationPropertyKey:
+ case LinearAnimationBase.loopValuePropertyKey:
+ case LinearAnimationBase.workStartPropertyKey:
+ case LinearAnimationBase.workEndPropertyKey:
+ case KeyFrameDrawOrderValueBase.drawableIdPropertyKey:
+ case KeyFrameDrawOrderValueBase.valuePropertyKey:
+ case ComponentBase.parentIdPropertyKey:
+ case StrokeBase.capPropertyKey:
+ case StrokeBase.joinPropertyKey:
+ case FillBase.fillRulePropertyKey:
+ case DrawableBase.drawOrderPropertyKey:
+ case DrawableBase.blendModeValuePropertyKey:
+ return intType;
+ case AnimationBase.namePropertyKey:
+ case ComponentBase.namePropertyKey:
+ return stringType;
+ case CubicInterpolatorBase.x1PropertyKey:
+ case CubicInterpolatorBase.y1PropertyKey:
+ case CubicInterpolatorBase.x2PropertyKey:
+ case CubicInterpolatorBase.y2PropertyKey:
+ case KeyFrameDoubleBase.valuePropertyKey:
+ case LinearAnimationBase.speedPropertyKey:
+ case LinearGradientBase.startXPropertyKey:
+ case LinearGradientBase.startYPropertyKey:
+ case LinearGradientBase.endXPropertyKey:
+ case LinearGradientBase.endYPropertyKey:
+ case LinearGradientBase.opacityPropertyKey:
+ case StrokeBase.thicknessPropertyKey:
+ case GradientStopBase.positionPropertyKey:
+ case NodeBase.xPropertyKey:
+ case NodeBase.yPropertyKey:
+ case NodeBase.rotationPropertyKey:
+ case NodeBase.scaleXPropertyKey:
+ case NodeBase.scaleYPropertyKey:
+ case NodeBase.opacityPropertyKey:
+ case PathVertexBase.xPropertyKey:
+ case PathVertexBase.yPropertyKey:
+ case StraightVertexBase.radiusPropertyKey:
+ case CubicAsymmetricVertexBase.rotationPropertyKey:
+ case CubicAsymmetricVertexBase.inDistancePropertyKey:
+ case CubicAsymmetricVertexBase.outDistancePropertyKey:
+ case ParametricPathBase.widthPropertyKey:
+ case ParametricPathBase.heightPropertyKey:
+ case RectangleBase.cornerRadiusPropertyKey:
+ case CubicMirroredVertexBase.rotationPropertyKey:
+ case CubicMirroredVertexBase.distancePropertyKey:
+ case CubicDetachedVertexBase.inRotationPropertyKey:
+ case CubicDetachedVertexBase.inDistancePropertyKey:
+ case CubicDetachedVertexBase.outRotationPropertyKey:
+ case CubicDetachedVertexBase.outDistancePropertyKey:
+ case ArtboardBase.widthPropertyKey:
+ case ArtboardBase.heightPropertyKey:
+ case ArtboardBase.xPropertyKey:
+ case ArtboardBase.yPropertyKey:
+ case ArtboardBase.originXPropertyKey:
+ case ArtboardBase.originYPropertyKey:
+ return doubleType;
+ case KeyFrameColorBase.valuePropertyKey:
+ case SolidColorBase.colorValuePropertyKey:
+ case GradientStopBase.colorValuePropertyKey:
+ return colorType;
+ case LinearAnimationBase.enableWorkAreaPropertyKey:
+ case ShapePaintBase.isVisiblePropertyKey:
+ case StrokeBase.transformAffectsStrokePropertyKey:
+ case PointsPathBase.isClosedPropertyKey:
+ return boolType;
+ default:
+ return null;
+ }
+ }
+
+ static int getInt(Core object, int propertyKey) {
+ switch (propertyKey) {
+ case KeyedObjectBase.objectIdPropertyKey:
+ return (object as KeyedObjectBase).objectId;
+ case KeyedPropertyBase.propertyKeyPropertyKey:
+ return (object as KeyedPropertyBase).propertyKey;
+ case KeyFrameBase.framePropertyKey:
+ return (object as KeyFrameBase).frame;
+ case KeyFrameBase.interpolationTypePropertyKey:
+ return (object as KeyFrameBase).interpolationType;
+ case KeyFrameBase.interpolatorIdPropertyKey:
+ return (object as KeyFrameBase).interpolatorId;
+ case LinearAnimationBase.fpsPropertyKey:
+ return (object as LinearAnimationBase).fps;
+ case LinearAnimationBase.durationPropertyKey:
+ return (object as LinearAnimationBase).duration;
+ case LinearAnimationBase.loopValuePropertyKey:
+ return (object as LinearAnimationBase).loopValue;
+ case LinearAnimationBase.workStartPropertyKey:
+ return (object as LinearAnimationBase).workStart;
+ case LinearAnimationBase.workEndPropertyKey:
+ return (object as LinearAnimationBase).workEnd;
+ case KeyFrameDrawOrderValueBase.drawableIdPropertyKey:
+ return (object as KeyFrameDrawOrderValueBase).drawableId;
+ case KeyFrameDrawOrderValueBase.valuePropertyKey:
+ return (object as KeyFrameDrawOrderValueBase).value;
+ case ComponentBase.parentIdPropertyKey:
+ return (object as ComponentBase).parentId;
+ case StrokeBase.capPropertyKey:
+ return (object as StrokeBase).cap;
+ case StrokeBase.joinPropertyKey:
+ return (object as StrokeBase).join;
+ case FillBase.fillRulePropertyKey:
+ return (object as FillBase).fillRule;
+ case DrawableBase.drawOrderPropertyKey:
+ return (object as DrawableBase).drawOrder;
+ case DrawableBase.blendModeValuePropertyKey:
+ return (object as DrawableBase).blendModeValue;
+ }
+ return 0;
+ }
+
+ static String getString(Core object, int propertyKey) {
+ switch (propertyKey) {
+ case AnimationBase.namePropertyKey:
+ return (object as AnimationBase).name;
+ case ComponentBase.namePropertyKey:
+ return (object as ComponentBase).name;
+ }
+ return null;
+ }
+
+ static double getDouble(Core object, int propertyKey) {
+ switch (propertyKey) {
+ case CubicInterpolatorBase.x1PropertyKey:
+ return (object as CubicInterpolatorBase).x1;
+ case CubicInterpolatorBase.y1PropertyKey:
+ return (object as CubicInterpolatorBase).y1;
+ case CubicInterpolatorBase.x2PropertyKey:
+ return (object as CubicInterpolatorBase).x2;
+ case CubicInterpolatorBase.y2PropertyKey:
+ return (object as CubicInterpolatorBase).y2;
+ case KeyFrameDoubleBase.valuePropertyKey:
+ return (object as KeyFrameDoubleBase).value;
+ case LinearAnimationBase.speedPropertyKey:
+ return (object as LinearAnimationBase).speed;
+ case LinearGradientBase.startXPropertyKey:
+ return (object as LinearGradientBase).startX;
+ case LinearGradientBase.startYPropertyKey:
+ return (object as LinearGradientBase).startY;
+ case LinearGradientBase.endXPropertyKey:
+ return (object as LinearGradientBase).endX;
+ case LinearGradientBase.endYPropertyKey:
+ return (object as LinearGradientBase).endY;
+ case LinearGradientBase.opacityPropertyKey:
+ return (object as LinearGradientBase).opacity;
+ case StrokeBase.thicknessPropertyKey:
+ return (object as StrokeBase).thickness;
+ case GradientStopBase.positionPropertyKey:
+ return (object as GradientStopBase).position;
+ case NodeBase.xPropertyKey:
+ return (object as NodeBase).x;
+ case NodeBase.yPropertyKey:
+ return (object as NodeBase).y;
+ case NodeBase.rotationPropertyKey:
+ return (object as NodeBase).rotation;
+ case NodeBase.scaleXPropertyKey:
+ return (object as NodeBase).scaleX;
+ case NodeBase.scaleYPropertyKey:
+ return (object as NodeBase).scaleY;
+ case NodeBase.opacityPropertyKey:
+ return (object as NodeBase).opacity;
+ case PathVertexBase.xPropertyKey:
+ return (object as PathVertexBase).x;
+ case PathVertexBase.yPropertyKey:
+ return (object as PathVertexBase).y;
+ case StraightVertexBase.radiusPropertyKey:
+ return (object as StraightVertexBase).radius;
+ case CubicAsymmetricVertexBase.rotationPropertyKey:
+ return (object as CubicAsymmetricVertexBase).rotation;
+ case CubicAsymmetricVertexBase.inDistancePropertyKey:
+ return (object as CubicAsymmetricVertexBase).inDistance;
+ case CubicAsymmetricVertexBase.outDistancePropertyKey:
+ return (object as CubicAsymmetricVertexBase).outDistance;
+ case ParametricPathBase.widthPropertyKey:
+ return (object as ParametricPathBase).width;
+ case ParametricPathBase.heightPropertyKey:
+ return (object as ParametricPathBase).height;
+ case RectangleBase.cornerRadiusPropertyKey:
+ return (object as RectangleBase).cornerRadius;
+ case CubicMirroredVertexBase.rotationPropertyKey:
+ return (object as CubicMirroredVertexBase).rotation;
+ case CubicMirroredVertexBase.distancePropertyKey:
+ return (object as CubicMirroredVertexBase).distance;
+ case CubicDetachedVertexBase.inRotationPropertyKey:
+ return (object as CubicDetachedVertexBase).inRotation;
+ case CubicDetachedVertexBase.inDistancePropertyKey:
+ return (object as CubicDetachedVertexBase).inDistance;
+ case CubicDetachedVertexBase.outRotationPropertyKey:
+ return (object as CubicDetachedVertexBase).outRotation;
+ case CubicDetachedVertexBase.outDistancePropertyKey:
+ return (object as CubicDetachedVertexBase).outDistance;
+ case ArtboardBase.widthPropertyKey:
+ return (object as ArtboardBase).width;
+ case ArtboardBase.heightPropertyKey:
+ return (object as ArtboardBase).height;
+ case ArtboardBase.xPropertyKey:
+ return (object as ArtboardBase).x;
+ case ArtboardBase.yPropertyKey:
+ return (object as ArtboardBase).y;
+ case ArtboardBase.originXPropertyKey:
+ return (object as ArtboardBase).originX;
+ case ArtboardBase.originYPropertyKey:
+ return (object as ArtboardBase).originY;
+ }
+ return 0.0;
+ }
+
+ static int getColor(Core object, int propertyKey) {
+ switch (propertyKey) {
+ case KeyFrameColorBase.valuePropertyKey:
+ return (object as KeyFrameColorBase).value;
+ case SolidColorBase.colorValuePropertyKey:
+ return (object as SolidColorBase).colorValue;
+ case GradientStopBase.colorValuePropertyKey:
+ return (object as GradientStopBase).colorValue;
+ }
+ return 0;
+ }
+
+ static bool getBool(Core object, int propertyKey) {
+ switch (propertyKey) {
+ case LinearAnimationBase.enableWorkAreaPropertyKey:
+ return (object as LinearAnimationBase).enableWorkArea;
+ case ShapePaintBase.isVisiblePropertyKey:
+ return (object as ShapePaintBase).isVisible;
+ case StrokeBase.transformAffectsStrokePropertyKey:
+ return (object as StrokeBase).transformAffectsStroke;
+ case PointsPathBase.isClosedPropertyKey:
+ return (object as PointsPathBase).isClosed;
+ }
+ return false;
+ }
+
+ static void setInt(Core object, int propertyKey, int value) {
+ switch (propertyKey) {
+ case KeyedObjectBase.objectIdPropertyKey:
+ (object as KeyedObjectBase).objectId = value;
+ break;
+ case KeyedPropertyBase.propertyKeyPropertyKey:
+ (object as KeyedPropertyBase).propertyKey = value;
+ break;
+ case KeyFrameBase.framePropertyKey:
+ (object as KeyFrameBase).frame = value;
+ break;
+ case KeyFrameBase.interpolationTypePropertyKey:
+ (object as KeyFrameBase).interpolationType = value;
+ break;
+ case KeyFrameBase.interpolatorIdPropertyKey:
+ (object as KeyFrameBase).interpolatorId = value;
+ break;
+ case LinearAnimationBase.fpsPropertyKey:
+ (object as LinearAnimationBase).fps = value;
+ break;
+ case LinearAnimationBase.durationPropertyKey:
+ (object as LinearAnimationBase).duration = value;
+ break;
+ case LinearAnimationBase.loopValuePropertyKey:
+ (object as LinearAnimationBase).loopValue = value;
+ break;
+ case LinearAnimationBase.workStartPropertyKey:
+ (object as LinearAnimationBase).workStart = value;
+ break;
+ case LinearAnimationBase.workEndPropertyKey:
+ (object as LinearAnimationBase).workEnd = value;
+ break;
+ case KeyFrameDrawOrderValueBase.drawableIdPropertyKey:
+ (object as KeyFrameDrawOrderValueBase).drawableId = value;
+ break;
+ case KeyFrameDrawOrderValueBase.valuePropertyKey:
+ (object as KeyFrameDrawOrderValueBase).value = value;
+ break;
+ case ComponentBase.parentIdPropertyKey:
+ (object as ComponentBase).parentId = value;
+ break;
+ case StrokeBase.capPropertyKey:
+ (object as StrokeBase).cap = value;
+ break;
+ case StrokeBase.joinPropertyKey:
+ (object as StrokeBase).join = value;
+ break;
+ case FillBase.fillRulePropertyKey:
+ (object as FillBase).fillRule = value;
+ break;
+ case DrawableBase.drawOrderPropertyKey:
+ (object as DrawableBase).drawOrder = value;
+ break;
+ case DrawableBase.blendModeValuePropertyKey:
+ (object as DrawableBase).blendModeValue = value;
+ break;
+ }
+ }
+
+ static void setString(Core object, int propertyKey, String value) {
+ switch (propertyKey) {
+ case AnimationBase.namePropertyKey:
+ (object as AnimationBase).name = value;
+ break;
+ case ComponentBase.namePropertyKey:
+ (object as ComponentBase).name = value;
+ break;
+ }
+ }
+
+ static void setDouble(Core object, int propertyKey, double value) {
+ switch (propertyKey) {
+ case CubicInterpolatorBase.x1PropertyKey:
+ (object as CubicInterpolatorBase).x1 = value;
+ break;
+ case CubicInterpolatorBase.y1PropertyKey:
+ (object as CubicInterpolatorBase).y1 = value;
+ break;
+ case CubicInterpolatorBase.x2PropertyKey:
+ (object as CubicInterpolatorBase).x2 = value;
+ break;
+ case CubicInterpolatorBase.y2PropertyKey:
+ (object as CubicInterpolatorBase).y2 = value;
+ break;
+ case KeyFrameDoubleBase.valuePropertyKey:
+ (object as KeyFrameDoubleBase).value = value;
+ break;
+ case LinearAnimationBase.speedPropertyKey:
+ (object as LinearAnimationBase).speed = value;
+ break;
+ case LinearGradientBase.startXPropertyKey:
+ (object as LinearGradientBase).startX = value;
+ break;
+ case LinearGradientBase.startYPropertyKey:
+ (object as LinearGradientBase).startY = value;
+ break;
+ case LinearGradientBase.endXPropertyKey:
+ (object as LinearGradientBase).endX = value;
+ break;
+ case LinearGradientBase.endYPropertyKey:
+ (object as LinearGradientBase).endY = value;
+ break;
+ case LinearGradientBase.opacityPropertyKey:
+ (object as LinearGradientBase).opacity = value;
+ break;
+ case StrokeBase.thicknessPropertyKey:
+ (object as StrokeBase).thickness = value;
+ break;
+ case GradientStopBase.positionPropertyKey:
+ (object as GradientStopBase).position = value;
+ break;
+ case NodeBase.xPropertyKey:
+ (object as NodeBase).x = value;
+ break;
+ case NodeBase.yPropertyKey:
+ (object as NodeBase).y = value;
+ break;
+ case NodeBase.rotationPropertyKey:
+ (object as NodeBase).rotation = value;
+ break;
+ case NodeBase.scaleXPropertyKey:
+ (object as NodeBase).scaleX = value;
+ break;
+ case NodeBase.scaleYPropertyKey:
+ (object as NodeBase).scaleY = value;
+ break;
+ case NodeBase.opacityPropertyKey:
+ (object as NodeBase).opacity = value;
+ break;
+ case PathVertexBase.xPropertyKey:
+ (object as PathVertexBase).x = value;
+ break;
+ case PathVertexBase.yPropertyKey:
+ (object as PathVertexBase).y = value;
+ break;
+ case StraightVertexBase.radiusPropertyKey:
+ (object as StraightVertexBase).radius = value;
+ break;
+ case CubicAsymmetricVertexBase.rotationPropertyKey:
+ (object as CubicAsymmetricVertexBase).rotation = value;
+ break;
+ case CubicAsymmetricVertexBase.inDistancePropertyKey:
+ (object as CubicAsymmetricVertexBase).inDistance = value;
+ break;
+ case CubicAsymmetricVertexBase.outDistancePropertyKey:
+ (object as CubicAsymmetricVertexBase).outDistance = value;
+ break;
+ case ParametricPathBase.widthPropertyKey:
+ (object as ParametricPathBase).width = value;
+ break;
+ case ParametricPathBase.heightPropertyKey:
+ (object as ParametricPathBase).height = value;
+ break;
+ case RectangleBase.cornerRadiusPropertyKey:
+ (object as RectangleBase).cornerRadius = value;
+ break;
+ case CubicMirroredVertexBase.rotationPropertyKey:
+ (object as CubicMirroredVertexBase).rotation = value;
+ break;
+ case CubicMirroredVertexBase.distancePropertyKey:
+ (object as CubicMirroredVertexBase).distance = value;
+ break;
+ case CubicDetachedVertexBase.inRotationPropertyKey:
+ (object as CubicDetachedVertexBase).inRotation = value;
+ break;
+ case CubicDetachedVertexBase.inDistancePropertyKey:
+ (object as CubicDetachedVertexBase).inDistance = value;
+ break;
+ case CubicDetachedVertexBase.outRotationPropertyKey:
+ (object as CubicDetachedVertexBase).outRotation = value;
+ break;
+ case CubicDetachedVertexBase.outDistancePropertyKey:
+ (object as CubicDetachedVertexBase).outDistance = value;
+ break;
+ case ArtboardBase.widthPropertyKey:
+ (object as ArtboardBase).width = value;
+ break;
+ case ArtboardBase.heightPropertyKey:
+ (object as ArtboardBase).height = value;
+ break;
+ case ArtboardBase.xPropertyKey:
+ (object as ArtboardBase).x = value;
+ break;
+ case ArtboardBase.yPropertyKey:
+ (object as ArtboardBase).y = value;
+ break;
+ case ArtboardBase.originXPropertyKey:
+ (object as ArtboardBase).originX = value;
+ break;
+ case ArtboardBase.originYPropertyKey:
+ (object as ArtboardBase).originY = value;
+ break;
+ }
+ }
+
+ static void setColor(Core object, int propertyKey, int value) {
+ switch (propertyKey) {
+ case KeyFrameColorBase.valuePropertyKey:
+ (object as KeyFrameColorBase).value = value;
+ break;
+ case SolidColorBase.colorValuePropertyKey:
+ (object as SolidColorBase).colorValue = value;
+ break;
+ case GradientStopBase.colorValuePropertyKey:
+ (object as GradientStopBase).colorValue = value;
+ break;
+ }
+ }
+
+ static void setBool(Core object, int propertyKey, bool value) {
+ switch (propertyKey) {
+ case LinearAnimationBase.enableWorkAreaPropertyKey:
+ (object as LinearAnimationBase).enableWorkArea = value;
+ break;
+ case ShapePaintBase.isVisiblePropertyKey:
+ (object as ShapePaintBase).isVisible = value;
+ break;
+ case StrokeBase.transformAffectsStrokePropertyKey:
+ (object as StrokeBase).transformAffectsStroke = value;
+ break;
+ case PointsPathBase.isClosedPropertyKey:
+ (object as PointsPathBase).isClosed = value;
+ break;
+ }
+ }
+}
diff --git a/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart b/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart
new file mode 100644
index 0000000..56f21d8
--- /dev/null
+++ b/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart
@@ -0,0 +1,85 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/shapes/cubic_vertex_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
+
+abstract class CubicAsymmetricVertexBase extends CubicVertex {
+ static const int typeKey = 34;
+ @override
+ int get coreType => CubicAsymmetricVertexBase.typeKey;
+ @override
+ Set get coreTypes => {
+ CubicAsymmetricVertexBase.typeKey,
+ CubicVertexBase.typeKey,
+ PathVertexBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Rotation field with key 79.
+ double _rotation = 0;
+ static const int rotationPropertyKey = 79;
+
+ /// The control points' angle.
+ double get rotation => _rotation;
+
+ /// Change the [_rotation] field value.
+ /// [rotationChanged] will be invoked only if the field's value has changed.
+ set rotation(double value) {
+ if (_rotation == value) {
+ return;
+ }
+ double from = _rotation;
+ _rotation = value;
+ rotationChanged(from, value);
+ }
+
+ void rotationChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// InDistance field with key 80.
+ double _inDistance = 0;
+ static const int inDistancePropertyKey = 80;
+
+ /// The in point's distance from the translation of the point.
+ double get inDistance => _inDistance;
+
+ /// Change the [_inDistance] field value.
+ /// [inDistanceChanged] will be invoked only if the field's value has changed.
+ set inDistance(double value) {
+ if (_inDistance == value) {
+ return;
+ }
+ double from = _inDistance;
+ _inDistance = value;
+ inDistanceChanged(from, value);
+ }
+
+ void inDistanceChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// OutDistance field with key 81.
+ double _outDistance = 0;
+ static const int outDistancePropertyKey = 81;
+
+ /// The out point's distance from the translation of the point.
+ double get outDistance => _outDistance;
+
+ /// Change the [_outDistance] field value.
+ /// [outDistanceChanged] will be invoked only if the field's value has
+ /// changed.
+ set outDistance(double value) {
+ if (_outDistance == value) {
+ return;
+ }
+ double from = _outDistance;
+ _outDistance = value;
+ outDistanceChanged(from, value);
+ }
+
+ void outDistanceChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/cubic_detached_vertex_base.dart b/lib/src/generated/shapes/cubic_detached_vertex_base.dart
new file mode 100644
index 0000000..c12849b
--- /dev/null
+++ b/lib/src/generated/shapes/cubic_detached_vertex_base.dart
@@ -0,0 +1,107 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/cubic_detached_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/shapes/cubic_vertex_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
+
+abstract class CubicDetachedVertexBase extends CubicVertex {
+ static const int typeKey = 6;
+ @override
+ int get coreType => CubicDetachedVertexBase.typeKey;
+ @override
+ Set get coreTypes => {
+ CubicDetachedVertexBase.typeKey,
+ CubicVertexBase.typeKey,
+ PathVertexBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// InRotation field with key 84.
+ double _inRotation = 0;
+ static const int inRotationPropertyKey = 84;
+
+ /// The in point's angle.
+ double get inRotation => _inRotation;
+
+ /// Change the [_inRotation] field value.
+ /// [inRotationChanged] will be invoked only if the field's value has changed.
+ set inRotation(double value) {
+ if (_inRotation == value) {
+ return;
+ }
+ double from = _inRotation;
+ _inRotation = value;
+ inRotationChanged(from, value);
+ }
+
+ void inRotationChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// InDistance field with key 85.
+ double _inDistance = 0;
+ static const int inDistancePropertyKey = 85;
+
+ /// The in point's distance from the translation of the point.
+ double get inDistance => _inDistance;
+
+ /// Change the [_inDistance] field value.
+ /// [inDistanceChanged] will be invoked only if the field's value has changed.
+ set inDistance(double value) {
+ if (_inDistance == value) {
+ return;
+ }
+ double from = _inDistance;
+ _inDistance = value;
+ inDistanceChanged(from, value);
+ }
+
+ void inDistanceChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// OutRotation field with key 86.
+ double _outRotation = 0;
+ static const int outRotationPropertyKey = 86;
+
+ /// The out point's angle.
+ double get outRotation => _outRotation;
+
+ /// Change the [_outRotation] field value.
+ /// [outRotationChanged] will be invoked only if the field's value has
+ /// changed.
+ set outRotation(double value) {
+ if (_outRotation == value) {
+ return;
+ }
+ double from = _outRotation;
+ _outRotation = value;
+ outRotationChanged(from, value);
+ }
+
+ void outRotationChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// OutDistance field with key 87.
+ double _outDistance = 0;
+ static const int outDistancePropertyKey = 87;
+
+ /// The out point's distance from the translation of the point.
+ double get outDistance => _outDistance;
+
+ /// Change the [_outDistance] field value.
+ /// [outDistanceChanged] will be invoked only if the field's value has
+ /// changed.
+ set outDistance(double value) {
+ if (_outDistance == value) {
+ return;
+ }
+ double from = _outDistance;
+ _outDistance = value;
+ outDistanceChanged(from, value);
+ }
+
+ void outDistanceChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart b/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart
new file mode 100644
index 0000000..2dc4cda
--- /dev/null
+++ b/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart
@@ -0,0 +1,63 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/cubic_mirrored_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/shapes/cubic_vertex_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
+
+abstract class CubicMirroredVertexBase extends CubicVertex {
+ static const int typeKey = 35;
+ @override
+ int get coreType => CubicMirroredVertexBase.typeKey;
+ @override
+ Set get coreTypes => {
+ CubicMirroredVertexBase.typeKey,
+ CubicVertexBase.typeKey,
+ PathVertexBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Rotation field with key 82.
+ double _rotation = 0;
+ static const int rotationPropertyKey = 82;
+
+ /// The control points' angle.
+ double get rotation => _rotation;
+
+ /// Change the [_rotation] field value.
+ /// [rotationChanged] will be invoked only if the field's value has changed.
+ set rotation(double value) {
+ if (_rotation == value) {
+ return;
+ }
+ double from = _rotation;
+ _rotation = value;
+ rotationChanged(from, value);
+ }
+
+ void rotationChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Distance field with key 83.
+ double _distance = 0;
+ static const int distancePropertyKey = 83;
+
+ /// The control points' distance from the translation of the point.
+ double get distance => _distance;
+
+ /// Change the [_distance] field value.
+ /// [distanceChanged] will be invoked only if the field's value has changed.
+ set distance(double value) {
+ if (_distance == value) {
+ return;
+ }
+ double from = _distance;
+ _distance = value;
+ distanceChanged(from, value);
+ }
+
+ void distanceChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/cubic_vertex_base.dart b/lib/src/generated/shapes/cubic_vertex_base.dart
new file mode 100644
index 0000000..a972f7f
--- /dev/null
+++ b/lib/src/generated/shapes/cubic_vertex_base.dart
@@ -0,0 +1,16 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/cubic_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+
+abstract class CubicVertexBase extends PathVertex {
+ static const int typeKey = 36;
+ @override
+ int get coreType => CubicVertexBase.typeKey;
+ @override
+ Set get coreTypes =>
+ {CubicVertexBase.typeKey, PathVertexBase.typeKey, ComponentBase.typeKey};
+}
diff --git a/lib/src/generated/shapes/ellipse_base.dart b/lib/src/generated/shapes/ellipse_base.dart
new file mode 100644
index 0000000..b3c46ba
--- /dev/null
+++ b/lib/src/generated/shapes/ellipse_base.dart
@@ -0,0 +1,24 @@
+/// Core automatically generated lib/src/generated/shapes/ellipse_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/parametric_path_base.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+import 'package:rive/src/rive_core/shapes/parametric_path.dart';
+
+abstract class EllipseBase extends ParametricPath {
+ static const int typeKey = 4;
+ @override
+ int get coreType => EllipseBase.typeKey;
+ @override
+ Set get coreTypes => {
+ EllipseBase.typeKey,
+ ParametricPathBase.typeKey,
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+}
diff --git a/lib/src/generated/shapes/paint/fill_base.dart b/lib/src/generated/shapes/paint/fill_base.dart
new file mode 100644
index 0000000..7a87593
--- /dev/null
+++ b/lib/src/generated/shapes/paint/fill_base.dart
@@ -0,0 +1,39 @@
+/// Core automatically generated lib/src/generated/shapes/paint/fill_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint.dart';
+
+abstract class FillBase extends ShapePaint {
+ static const int typeKey = 20;
+ @override
+ int get coreType => FillBase.typeKey;
+ @override
+ Set get coreTypes => {
+ FillBase.typeKey,
+ ShapePaintBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// FillRule field with key 40.
+ int _fillRule = 0;
+ static const int fillRulePropertyKey = 40;
+ int get fillRule => _fillRule;
+
+ /// Change the [_fillRule] field value.
+ /// [fillRuleChanged] will be invoked only if the field's value has changed.
+ set fillRule(int value) {
+ if (_fillRule == value) {
+ return;
+ }
+ int from = _fillRule;
+ _fillRule = value;
+ fillRuleChanged(from, value);
+ }
+
+ void fillRuleChanged(int from, int to);
+}
diff --git a/lib/src/generated/shapes/paint/gradient_stop_base.dart b/lib/src/generated/shapes/paint/gradient_stop_base.dart
new file mode 100644
index 0000000..8284ef8
--- /dev/null
+++ b/lib/src/generated/shapes/paint/gradient_stop_base.dart
@@ -0,0 +1,52 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/gradient_stop_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/rive_core/component.dart';
+
+abstract class GradientStopBase extends Component {
+ static const int typeKey = 19;
+ @override
+ int get coreType => GradientStopBase.typeKey;
+ @override
+ Set get coreTypes => {GradientStopBase.typeKey, ComponentBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// ColorValue field with key 38.
+ int _colorValue = 0xFFFFFFFF;
+ static const int colorValuePropertyKey = 38;
+ int get colorValue => _colorValue;
+
+ /// Change the [_colorValue] field value.
+ /// [colorValueChanged] will be invoked only if the field's value has changed.
+ set colorValue(int value) {
+ if (_colorValue == value) {
+ return;
+ }
+ int from = _colorValue;
+ _colorValue = value;
+ colorValueChanged(from, value);
+ }
+
+ void colorValueChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// Position field with key 39.
+ double _position = 0;
+ static const int positionPropertyKey = 39;
+ double get position => _position;
+
+ /// Change the [_position] field value.
+ /// [positionChanged] will be invoked only if the field's value has changed.
+ set position(double value) {
+ if (_position == value) {
+ return;
+ }
+ double from = _position;
+ _position = value;
+ positionChanged(from, value);
+ }
+
+ void positionChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/paint/linear_gradient_base.dart b/lib/src/generated/shapes/paint/linear_gradient_base.dart
new file mode 100644
index 0000000..b7e339b
--- /dev/null
+++ b/lib/src/generated/shapes/paint/linear_gradient_base.dart
@@ -0,0 +1,114 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/linear_gradient_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+
+abstract class LinearGradientBase extends ContainerComponent {
+ static const int typeKey = 22;
+ @override
+ int get coreType => LinearGradientBase.typeKey;
+ @override
+ Set get coreTypes => {
+ LinearGradientBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// StartX field with key 42.
+ double _startX = 0;
+ static const int startXPropertyKey = 42;
+ double get startX => _startX;
+
+ /// Change the [_startX] field value.
+ /// [startXChanged] will be invoked only if the field's value has changed.
+ set startX(double value) {
+ if (_startX == value) {
+ return;
+ }
+ double from = _startX;
+ _startX = value;
+ startXChanged(from, value);
+ }
+
+ void startXChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// StartY field with key 33.
+ double _startY = 0;
+ static const int startYPropertyKey = 33;
+ double get startY => _startY;
+
+ /// Change the [_startY] field value.
+ /// [startYChanged] will be invoked only if the field's value has changed.
+ set startY(double value) {
+ if (_startY == value) {
+ return;
+ }
+ double from = _startY;
+ _startY = value;
+ startYChanged(from, value);
+ }
+
+ void startYChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// EndX field with key 34.
+ double _endX = 0;
+ static const int endXPropertyKey = 34;
+ double get endX => _endX;
+
+ /// Change the [_endX] field value.
+ /// [endXChanged] will be invoked only if the field's value has changed.
+ set endX(double value) {
+ if (_endX == value) {
+ return;
+ }
+ double from = _endX;
+ _endX = value;
+ endXChanged(from, value);
+ }
+
+ void endXChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// EndY field with key 35.
+ double _endY = 0;
+ static const int endYPropertyKey = 35;
+ double get endY => _endY;
+
+ /// Change the [_endY] field value.
+ /// [endYChanged] will be invoked only if the field's value has changed.
+ set endY(double value) {
+ if (_endY == value) {
+ return;
+ }
+ double from = _endY;
+ _endY = value;
+ endYChanged(from, value);
+ }
+
+ void endYChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Opacity field with key 46.
+ double _opacity = 1;
+ static const int opacityPropertyKey = 46;
+ double get opacity => _opacity;
+
+ /// Change the [_opacity] field value.
+ /// [opacityChanged] will be invoked only if the field's value has changed.
+ set opacity(double value) {
+ if (_opacity == value) {
+ return;
+ }
+ double from = _opacity;
+ _opacity = value;
+ opacityChanged(from, value);
+ }
+
+ void opacityChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/paint/radial_gradient_base.dart b/lib/src/generated/shapes/paint/radial_gradient_base.dart
new file mode 100644
index 0000000..18a26a6
--- /dev/null
+++ b/lib/src/generated/shapes/paint/radial_gradient_base.dart
@@ -0,0 +1,21 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/radial_gradient_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';
+import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart';
+
+abstract class RadialGradientBase extends LinearGradient {
+ static const int typeKey = 17;
+ @override
+ int get coreType => RadialGradientBase.typeKey;
+ @override
+ Set get coreTypes => {
+ RadialGradientBase.typeKey,
+ LinearGradientBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+}
diff --git a/lib/src/generated/shapes/paint/shape_paint_base.dart b/lib/src/generated/shapes/paint/shape_paint_base.dart
new file mode 100644
index 0000000..f4c680c
--- /dev/null
+++ b/lib/src/generated/shapes/paint/shape_paint_base.dart
@@ -0,0 +1,38 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/shape_paint_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+
+abstract class ShapePaintBase extends ContainerComponent {
+ static const int typeKey = 21;
+ @override
+ int get coreType => ShapePaintBase.typeKey;
+ @override
+ Set get coreTypes => {
+ ShapePaintBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// IsVisible field with key 41.
+ bool _isVisible = true;
+ static const int isVisiblePropertyKey = 41;
+ bool get isVisible => _isVisible;
+
+ /// Change the [_isVisible] field value.
+ /// [isVisibleChanged] will be invoked only if the field's value has changed.
+ set isVisible(bool value) {
+ if (_isVisible == value) {
+ return;
+ }
+ bool from = _isVisible;
+ _isVisible = value;
+ isVisibleChanged(from, value);
+ }
+
+ void isVisibleChanged(bool from, bool to);
+}
diff --git a/lib/src/generated/shapes/paint/solid_color_base.dart b/lib/src/generated/shapes/paint/solid_color_base.dart
new file mode 100644
index 0000000..4d38d44
--- /dev/null
+++ b/lib/src/generated/shapes/paint/solid_color_base.dart
@@ -0,0 +1,33 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/solid_color_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/rive_core/component.dart';
+
+abstract class SolidColorBase extends Component {
+ static const int typeKey = 18;
+ @override
+ int get coreType => SolidColorBase.typeKey;
+ @override
+ Set get coreTypes => {SolidColorBase.typeKey, ComponentBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// ColorValue field with key 37.
+ int _colorValue = 0xFF747474;
+ static const int colorValuePropertyKey = 37;
+ int get colorValue => _colorValue;
+
+ /// Change the [_colorValue] field value.
+ /// [colorValueChanged] will be invoked only if the field's value has changed.
+ set colorValue(int value) {
+ if (_colorValue == value) {
+ return;
+ }
+ int from = _colorValue;
+ _colorValue = value;
+ colorValueChanged(from, value);
+ }
+
+ void colorValueChanged(int from, int to);
+}
diff --git a/lib/src/generated/shapes/paint/stroke_base.dart b/lib/src/generated/shapes/paint/stroke_base.dart
new file mode 100644
index 0000000..ba93e18
--- /dev/null
+++ b/lib/src/generated/shapes/paint/stroke_base.dart
@@ -0,0 +1,98 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/paint/stroke_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint.dart';
+
+abstract class StrokeBase extends ShapePaint {
+ static const int typeKey = 24;
+ @override
+ int get coreType => StrokeBase.typeKey;
+ @override
+ Set get coreTypes => {
+ StrokeBase.typeKey,
+ ShapePaintBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Thickness field with key 47.
+ double _thickness = 1;
+ static const int thicknessPropertyKey = 47;
+ double get thickness => _thickness;
+
+ /// Change the [_thickness] field value.
+ /// [thicknessChanged] will be invoked only if the field's value has changed.
+ set thickness(double value) {
+ if (_thickness == value) {
+ return;
+ }
+ double from = _thickness;
+ _thickness = value;
+ thicknessChanged(from, value);
+ }
+
+ void thicknessChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Cap field with key 48.
+ int _cap = 0;
+ static const int capPropertyKey = 48;
+ int get cap => _cap;
+
+ /// Change the [_cap] field value.
+ /// [capChanged] will be invoked only if the field's value has changed.
+ set cap(int value) {
+ if (_cap == value) {
+ return;
+ }
+ int from = _cap;
+ _cap = value;
+ capChanged(from, value);
+ }
+
+ void capChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// Join field with key 49.
+ int _join = 0;
+ static const int joinPropertyKey = 49;
+ int get join => _join;
+
+ /// Change the [_join] field value.
+ /// [joinChanged] will be invoked only if the field's value has changed.
+ set join(int value) {
+ if (_join == value) {
+ return;
+ }
+ int from = _join;
+ _join = value;
+ joinChanged(from, value);
+ }
+
+ void joinChanged(int from, int to);
+
+ /// --------------------------------------------------------------------------
+ /// TransformAffectsStroke field with key 50.
+ bool _transformAffectsStroke = true;
+ static const int transformAffectsStrokePropertyKey = 50;
+ bool get transformAffectsStroke => _transformAffectsStroke;
+
+ /// Change the [_transformAffectsStroke] field value.
+ /// [transformAffectsStrokeChanged] will be invoked only if the field's value
+ /// has changed.
+ set transformAffectsStroke(bool value) {
+ if (_transformAffectsStroke == value) {
+ return;
+ }
+ bool from = _transformAffectsStroke;
+ _transformAffectsStroke = value;
+ transformAffectsStrokeChanged(from, value);
+ }
+
+ void transformAffectsStrokeChanged(bool from, bool to);
+}
diff --git a/lib/src/generated/shapes/parametric_path_base.dart b/lib/src/generated/shapes/parametric_path_base.dart
new file mode 100644
index 0000000..e51dc46
--- /dev/null
+++ b/lib/src/generated/shapes/parametric_path_base.dart
@@ -0,0 +1,65 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/parametric_path_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+import 'package:rive/src/rive_core/shapes/path.dart';
+
+abstract class ParametricPathBase extends Path {
+ static const int typeKey = 15;
+ @override
+ int get coreType => ParametricPathBase.typeKey;
+ @override
+ Set get coreTypes => {
+ ParametricPathBase.typeKey,
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Width field with key 20.
+ double _width = 0;
+ static const int widthPropertyKey = 20;
+
+ /// Width of the parametric path.
+ double get width => _width;
+
+ /// Change the [_width] field value.
+ /// [widthChanged] will be invoked only if the field's value has changed.
+ set width(double value) {
+ if (_width == value) {
+ return;
+ }
+ double from = _width;
+ _width = value;
+ widthChanged(from, value);
+ }
+
+ void widthChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Height field with key 21.
+ double _height = 0;
+ static const int heightPropertyKey = 21;
+
+ /// Height of the parametric path.
+ double get height => _height;
+
+ /// Change the [_height] field value.
+ /// [heightChanged] will be invoked only if the field's value has changed.
+ set height(double value) {
+ if (_height == value) {
+ return;
+ }
+ double from = _height;
+ _height = value;
+ heightChanged(from, value);
+ }
+
+ void heightChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/path_base.dart b/lib/src/generated/shapes/path_base.dart
new file mode 100644
index 0000000..5f00988
--- /dev/null
+++ b/lib/src/generated/shapes/path_base.dart
@@ -0,0 +1,20 @@
+/// Core automatically generated lib/src/generated/shapes/path_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/rive_core/node.dart';
+
+abstract class PathBase extends Node {
+ static const int typeKey = 12;
+ @override
+ int get coreType => PathBase.typeKey;
+ @override
+ Set get coreTypes => {
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+}
diff --git a/lib/src/generated/shapes/path_composer_base.dart b/lib/src/generated/shapes/path_composer_base.dart
new file mode 100644
index 0000000..ddbd0fc
--- /dev/null
+++ b/lib/src/generated/shapes/path_composer_base.dart
@@ -0,0 +1,14 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/path_composer_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/rive_core/component.dart';
+
+abstract class PathComposerBase extends Component {
+ static const int typeKey = 9;
+ @override
+ int get coreType => PathComposerBase.typeKey;
+ @override
+ Set get coreTypes => {PathComposerBase.typeKey, ComponentBase.typeKey};
+}
diff --git a/lib/src/generated/shapes/path_vertex_base.dart b/lib/src/generated/shapes/path_vertex_base.dart
new file mode 100644
index 0000000..8eb5027
--- /dev/null
+++ b/lib/src/generated/shapes/path_vertex_base.dart
@@ -0,0 +1,55 @@
+/// Core automatically generated lib/src/generated/shapes/path_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/rive_core/component.dart';
+
+abstract class PathVertexBase extends Component {
+ static const int typeKey = 14;
+ @override
+ int get coreType => PathVertexBase.typeKey;
+ @override
+ Set get coreTypes => {PathVertexBase.typeKey, ComponentBase.typeKey};
+
+ /// --------------------------------------------------------------------------
+ /// X field with key 24.
+ double _x;
+ static const int xPropertyKey = 24;
+
+ /// X value for the translation of the vertex.
+ double get x => _x;
+
+ /// Change the [_x] field value.
+ /// [xChanged] will be invoked only if the field's value has changed.
+ set x(double value) {
+ if (_x == value) {
+ return;
+ }
+ double from = _x;
+ _x = value;
+ xChanged(from, value);
+ }
+
+ void xChanged(double from, double to);
+
+ /// --------------------------------------------------------------------------
+ /// Y field with key 25.
+ double _y;
+ static const int yPropertyKey = 25;
+
+ /// Y value for the translation of the vertex.
+ double get y => _y;
+
+ /// Change the [_y] field value.
+ /// [yChanged] will be invoked only if the field's value has changed.
+ set y(double value) {
+ if (_y == value) {
+ return;
+ }
+ double from = _y;
+ _y = value;
+ yChanged(from, value);
+ }
+
+ void yChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/points_path_base.dart b/lib/src/generated/shapes/points_path_base.dart
new file mode 100644
index 0000000..8683b9f
--- /dev/null
+++ b/lib/src/generated/shapes/points_path_base.dart
@@ -0,0 +1,44 @@
+/// Core automatically generated lib/src/generated/shapes/points_path_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+import 'package:rive/src/rive_core/shapes/path.dart';
+
+abstract class PointsPathBase extends Path {
+ static const int typeKey = 16;
+ @override
+ int get coreType => PointsPathBase.typeKey;
+ @override
+ Set get coreTypes => {
+ PointsPathBase.typeKey,
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// IsClosed field with key 32.
+ bool _isClosed;
+ static const int isClosedPropertyKey = 32;
+
+ /// If the path should close back on its first vertex.
+ @override
+ bool get isClosed => _isClosed;
+
+ /// Change the [_isClosed] field value.
+ /// [isClosedChanged] will be invoked only if the field's value has changed.
+ set isClosed(bool value) {
+ if (_isClosed == value) {
+ return;
+ }
+ bool from = _isClosed;
+ _isClosed = value;
+ isClosedChanged(from, value);
+ }
+
+ void isClosedChanged(bool from, bool to);
+}
diff --git a/lib/src/generated/shapes/rectangle_base.dart b/lib/src/generated/shapes/rectangle_base.dart
new file mode 100644
index 0000000..ddda4fc
--- /dev/null
+++ b/lib/src/generated/shapes/rectangle_base.dart
@@ -0,0 +1,46 @@
+/// Core automatically generated lib/src/generated/shapes/rectangle_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/parametric_path_base.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+import 'package:rive/src/rive_core/shapes/parametric_path.dart';
+
+abstract class RectangleBase extends ParametricPath {
+ static const int typeKey = 7;
+ @override
+ int get coreType => RectangleBase.typeKey;
+ @override
+ Set get coreTypes => {
+ RectangleBase.typeKey,
+ ParametricPathBase.typeKey,
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// CornerRadius field with key 31.
+ double _cornerRadius;
+ static const int cornerRadiusPropertyKey = 31;
+
+ /// Radius of the corners of this rectangle
+ double get cornerRadius => _cornerRadius;
+
+ /// Change the [_cornerRadius] field value.
+ /// [cornerRadiusChanged] will be invoked only if the field's value has
+ /// changed.
+ set cornerRadius(double value) {
+ if (_cornerRadius == value) {
+ return;
+ }
+ double from = _cornerRadius;
+ _cornerRadius = value;
+ cornerRadiusChanged(from, value);
+ }
+
+ void cornerRadiusChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/shape_base.dart b/lib/src/generated/shapes/shape_base.dart
new file mode 100644
index 0000000..9f4d59b
--- /dev/null
+++ b/lib/src/generated/shapes/shape_base.dart
@@ -0,0 +1,22 @@
+/// Core automatically generated lib/src/generated/shapes/shape_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/drawable_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/rive_core/drawable.dart';
+
+abstract class ShapeBase extends Drawable {
+ static const int typeKey = 3;
+ @override
+ int get coreType => ShapeBase.typeKey;
+ @override
+ Set get coreTypes => {
+ ShapeBase.typeKey,
+ DrawableBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+}
diff --git a/lib/src/generated/shapes/straight_vertex_base.dart b/lib/src/generated/shapes/straight_vertex_base.dart
new file mode 100644
index 0000000..630a73e
--- /dev/null
+++ b/lib/src/generated/shapes/straight_vertex_base.dart
@@ -0,0 +1,40 @@
+/// Core automatically generated
+/// lib/src/generated/shapes/straight_vertex_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+
+abstract class StraightVertexBase extends PathVertex {
+ static const int typeKey = 5;
+ @override
+ int get coreType => StraightVertexBase.typeKey;
+ @override
+ Set get coreTypes => {
+ StraightVertexBase.typeKey,
+ PathVertexBase.typeKey,
+ ComponentBase.typeKey
+ };
+
+ /// --------------------------------------------------------------------------
+ /// Radius field with key 26.
+ double _radius = 0;
+ static const int radiusPropertyKey = 26;
+
+ /// Radius of the vertex
+ double get radius => _radius;
+
+ /// Change the [_radius] field value.
+ /// [radiusChanged] will be invoked only if the field's value has changed.
+ set radius(double value) {
+ if (_radius == value) {
+ return;
+ }
+ double from = _radius;
+ _radius = value;
+ radiusChanged(from, value);
+ }
+
+ void radiusChanged(double from, double to);
+}
diff --git a/lib/src/generated/shapes/triangle_base.dart b/lib/src/generated/shapes/triangle_base.dart
new file mode 100644
index 0000000..33d6de9
--- /dev/null
+++ b/lib/src/generated/shapes/triangle_base.dart
@@ -0,0 +1,24 @@
+/// Core automatically generated lib/src/generated/shapes/triangle_base.dart.
+/// Do not modify manually.
+
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:rive/src/generated/shapes/parametric_path_base.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+import 'package:rive/src/rive_core/shapes/parametric_path.dart';
+
+abstract class TriangleBase extends ParametricPath {
+ static const int typeKey = 8;
+ @override
+ int get coreType => TriangleBase.typeKey;
+ @override
+ Set get coreTypes => {
+ TriangleBase.typeKey,
+ ParametricPathBase.typeKey,
+ PathBase.typeKey,
+ NodeBase.typeKey,
+ ContainerComponentBase.typeKey,
+ ComponentBase.typeKey
+ };
+}
diff --git a/lib/src/rive.dart b/lib/src/rive.dart
new file mode 100644
index 0000000..4e58cb2
--- /dev/null
+++ b/lib/src/rive.dart
@@ -0,0 +1,84 @@
+import 'package:flutter/widgets.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_render_box.dart';
+import 'package:rive/src/runtime_artboard.dart';
+
+class Rive extends LeafRenderObjectWidget {
+ final Artboard artboard;
+ final bool useIntrinsicSize;
+ final BoxFit fit;
+ final Alignment alignment;
+
+ const Rive({
+ @required this.artboard,
+ this.useIntrinsicSize = false,
+ this.fit = BoxFit.contain,
+ this.alignment = Alignment.center,
+ });
+
+ @override
+ RenderObject createRenderObject(BuildContext context) {
+ return RiveRenderObject()
+ ..artboard = artboard
+ ..fit = fit
+ ..alignment = alignment
+ ..useIntrinsicSize = useIntrinsicSize;
+ }
+
+ @override
+ void updateRenderObject(
+ BuildContext context, covariant RiveRenderObject renderObject) {
+ renderObject
+ ..artboard = artboard
+ ..fit = fit
+ ..alignment = alignment
+ ..useIntrinsicSize = useIntrinsicSize;
+ }
+
+ @override
+ void didUnmountRenderObject(covariant RiveRenderObject renderObject) {
+ renderObject.dispose();
+ }
+}
+
+class RiveRenderObject extends RiveRenderBox {
+ RuntimeArtboard _artboard;
+ RuntimeArtboard get artboard => _artboard;
+ set artboard(Artboard value) {
+ if (_artboard == value) {
+ return;
+ }
+ _artboard?.redraw?.removeListener(scheduleRepaint);
+ _artboard = value as RuntimeArtboard;
+ _artboard?.redraw?.addListener(scheduleRepaint);
+ markNeedsLayout();
+ }
+
+ void dispose() {
+ _artboard?.redraw?.removeListener(scheduleRepaint);
+ }
+
+ @override
+ AABB get aabb {
+ var width = _artboard.width;
+ var height = _artboard.height;
+ double minX = -1 * _artboard.originX * width;
+ double minY = -1 * _artboard.originY * height;
+ return AABB.fromValues(minX, minY, minX + width, minY + height);
+ }
+
+ @override
+ bool advance(double elapsedSeconds) => _artboard.advance(elapsedSeconds);
+
+ @override
+ void beforeDraw(Canvas canvas, Offset offset) {
+ canvas.clipRect(offset & size);
+ }
+
+ @override
+ void draw(Canvas canvas, Mat2D viewTransform) {
+ artboard.draw(canvas);
+ }
+}
diff --git a/lib/src/rive_core/animation/animation.dart b/lib/src/rive_core/animation/animation.dart
new file mode 100644
index 0000000..0a8f63f
--- /dev/null
+++ b/lib/src/rive_core/animation/animation.dart
@@ -0,0 +1,36 @@
+import 'package:rive/src/core/core.dart';
+import 'package:meta/meta.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+import 'package:rive/src/generated/animation/animation_base.dart';
+export 'package:rive/src/generated/animation/animation_base.dart';
+
+class Animation extends AnimationBase {
+ Artboard _artboard;
+ Artboard get artboard => _artboard;
+ set artboard(Artboard value) {
+ if (_artboard == value) {
+ return;
+ }
+ var old = _artboard;
+ _artboard = value;
+ artboardChanged(old, value);
+ }
+
+ @protected
+ void artboardChanged(Artboard from, Artboard to) {
+ from?.internalRemoveAnimation(this);
+ to?.internalAddAnimation(this);
+ }
+
+ @override
+ void onAdded() {}
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {
+ artboard = null;
+ }
+
+ @override
+ void nameChanged(String from, String to) {}
+}
diff --git a/lib/src/rive_core/animation/cubic_interpolator.dart b/lib/src/rive_core/animation/cubic_interpolator.dart
new file mode 100644
index 0000000..430fb6b
--- /dev/null
+++ b/lib/src/rive_core/animation/cubic_interpolator.dart
@@ -0,0 +1,135 @@
+import 'dart:typed_data';
+import 'package:rive/src/rive_core/animation/interpolator.dart';
+import 'package:rive/src/generated/animation/cubic_interpolator_base.dart';
+
+const int newtonIterations = 4;
+const double newtonMinSlope = 0.001;
+const double sampleStepSize = 1.0 / (splineTableSize - 1.0);
+const int splineTableSize = 11;
+const int subdivisionMaxIterations = 10;
+const double subdivisionPrecision = 0.0000001;
+double _calcBezier(double aT, double aA1, double aA2) {
+ return (((1.0 - 3.0 * aA2 + 3.0 * aA1) * aT + (3.0 * aA2 - 6.0 * aA1)) * aT +
+ (3.0 * aA1)) *
+ aT;
+}
+
+double _getSlope(double aT, double aA1, double aA2) {
+ return 3.0 * (1.0 - 3.0 * aA2 + 3.0 * aA1) * aT * aT +
+ 2.0 * (3.0 * aA2 - 6.0 * aA1) * aT +
+ (3.0 * aA1);
+}
+
+class CubicInterpolator extends CubicInterpolatorBase implements Interpolator {
+ _CubicEase _ease;
+ @override
+ bool equalParameters(Interpolator other) {
+ if (other is CubicInterpolator) {
+ return x1 == other.x1 &&
+ x2 == other.x2 &&
+ y1 == other.y1 &&
+ y2 == other.y2;
+ }
+ return false;
+ }
+
+ @override
+ void onAdded() {
+ _updateStoredCubic();
+ }
+
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {}
+ @override
+ double transform(double value) => _ease.transform(value);
+ @override
+ void x1Changed(double from, double to) => _updateStoredCubic();
+ @override
+ void x2Changed(double from, double to) => _updateStoredCubic();
+ @override
+ void y1Changed(double from, double to) => _updateStoredCubic();
+ @override
+ void y2Changed(double from, double to) => _updateStoredCubic();
+ void _updateStoredCubic() {
+ _ease = _CubicEase.make(x1, y1, x2, y2);
+ }
+}
+
+class _Cubic extends _CubicEase {
+ Float64List _values;
+ final double x1, y1, x2, y2;
+ _Cubic(this.x1, this.y1, this.x2, this.y2) {
+ _values = Float64List(splineTableSize);
+ for (int i = 0; i < splineTableSize; ++i) {
+ _values[i] = _calcBezier(i * sampleStepSize, x1, x2);
+ }
+ }
+ double getT(double x) {
+ double intervalStart = 0.0;
+ int currentSample = 1;
+ int lastSample = splineTableSize - 1;
+ for (;
+ currentSample != lastSample && _values[currentSample] <= x;
+ ++currentSample) {
+ intervalStart += sampleStepSize;
+ }
+ --currentSample;
+ var dist = (x - _values[currentSample]) /
+ (_values[currentSample + 1] - _values[currentSample]);
+ var guessForT = intervalStart + dist * sampleStepSize;
+ var initialSlope = _getSlope(guessForT, x1, x2);
+ if (initialSlope >= newtonMinSlope) {
+ for (int i = 0; i < newtonIterations; ++i) {
+ double currentSlope = _getSlope(guessForT, x1, x2);
+ if (currentSlope == 0.0) {
+ return guessForT;
+ }
+ double currentX = _calcBezier(guessForT, x1, x2) - x;
+ guessForT -= currentX / currentSlope;
+ }
+ return guessForT;
+ } else if (initialSlope == 0.0) {
+ return guessForT;
+ } else {
+ double aB = intervalStart + sampleStepSize;
+ double currentX, currentT;
+ int i = 0;
+ do {
+ currentT = intervalStart + (aB - intervalStart) / 2.0;
+ currentX = _calcBezier(currentT, x1, x2) - x;
+ if (currentX > 0.0) {
+ aB = currentT;
+ } else {
+ intervalStart = currentT;
+ }
+ } while (currentX.abs() > subdivisionPrecision &&
+ ++i < subdivisionMaxIterations);
+ return currentT;
+ }
+ }
+
+ @override
+ double transform(double mix) {
+ return _calcBezier(getT(mix), y1, y2);
+ }
+}
+
+abstract class _CubicEase {
+ double transform(double t);
+ static _CubicEase make(double x1, double y1, double x2, double y2) {
+ if (x1 == y1 && x2 == y2) {
+ return _LinearCubicEase();
+ } else {
+ return _Cubic(x1, y1, x2, y2);
+ }
+ }
+}
+
+class _LinearCubicEase extends _CubicEase {
+ @override
+ double transform(double t) {
+ return t;
+ }
+}
diff --git a/lib/src/rive_core/animation/interpolator.dart b/lib/src/rive_core/animation/interpolator.dart
new file mode 100644
index 0000000..7ec2734
--- /dev/null
+++ b/lib/src/rive_core/animation/interpolator.dart
@@ -0,0 +1,6 @@
+
+abstract class Interpolator {
+ int get id;
+ double transform(double value);
+ bool equalParameters(Interpolator other);
+}
diff --git a/lib/src/rive_core/animation/keyed_object.dart b/lib/src/rive_core/animation/keyed_object.dart
new file mode 100644
index 0000000..c4bf8ab
--- /dev/null
+++ b/lib/src/rive_core/animation/keyed_object.dart
@@ -0,0 +1,46 @@
+import 'dart:collection';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyed_property.dart';
+import 'package:rive/src/generated/animation/keyed_object_base.dart';
+export 'package:rive/src/generated/animation/keyed_object_base.dart';
+
+class KeyedObject extends KeyedObjectBase {
+ final HashMap _keyedProperties =
+ HashMap();
+ Iterable get keyedProperties => _keyedProperties.values;
+ @override
+ void onAdded() {}
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {}
+ bool internalAddKeyedProperty(KeyedProperty property) {
+ var value = _keyedProperties[property.propertyKey];
+ if (value != null && value != property) {
+ return false;
+ }
+ _keyedProperties[property.propertyKey] = property;
+ return true;
+ }
+
+ bool internalRemoveKeyedProperty(KeyedProperty property) {
+ var removed = _keyedProperties.remove(property.propertyKey);
+ if (_keyedProperties.isEmpty) {
+ context.removeObject(this);
+ }
+ return removed != null;
+ }
+
+ void apply(double time, double mix, CoreContext coreContext) {
+ Core object = coreContext.resolve(objectId);
+ if (object == null) {
+ return;
+ }
+ for (final keyedProperty in _keyedProperties.values) {
+ keyedProperty.apply(time, mix, object);
+ }
+ }
+
+ @override
+ void objectIdChanged(int from, int to) {}
+}
diff --git a/lib/src/rive_core/animation/keyed_property.dart b/lib/src/rive_core/animation/keyed_property.dart
new file mode 100644
index 0000000..164bbac
--- /dev/null
+++ b/lib/src/rive_core/animation/keyed_property.dart
@@ -0,0 +1,138 @@
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+import 'package:rive/src/generated/animation/keyed_property_base.dart';
+export 'package:rive/src/generated/animation/keyed_property_base.dart';
+
+abstract class KeyFrameInterface {
+ int get frame;
+}
+
+class KeyFrameList {
+ List _keyframes = [];
+ Iterable get keyframes => _keyframes;
+ set keyframes(Iterable frames) => _keyframes = frames.toList();
+ T after(T keyframe) {
+ var index = _keyframes.indexOf(keyframe);
+ if (index != -1 && index + 1 < _keyframes.length) {
+ return _keyframes[index + 1];
+ }
+ return null;
+ }
+
+ int indexOfFrame(int frame) {
+ int idx = 0;
+ int mid = 0;
+ int closestFrame = 0;
+ int start = 0;
+ int end = _keyframes.length - 1;
+ while (start <= end) {
+ mid = (start + end) >> 1;
+ closestFrame = _keyframes[mid].frame;
+ if (closestFrame < frame) {
+ start = mid + 1;
+ } else if (closestFrame > frame) {
+ end = mid - 1;
+ } else {
+ idx = start = mid;
+ break;
+ }
+ idx = start;
+ }
+ return idx;
+ }
+
+ void sort() => _keyframes.sort((a, b) => a.frame.compareTo(b.frame));
+}
+
+class KeyedProperty extends KeyedPropertyBase
+ with KeyFrameList {
+ @override
+ void onAdded() {}
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {}
+ bool internalAddKeyFrame(KeyFrame frame) {
+ if (_keyframes.contains(frame)) {
+ return false;
+ }
+ _keyframes.add(frame);
+ markKeyFrameOrderDirty();
+ return true;
+ }
+
+ bool internalRemoveKeyFrame(KeyFrame frame) {
+ var removed = _keyframes.remove(frame);
+ if (_keyframes.isEmpty) {
+ context.removeObject(this);
+ }
+ return removed;
+ }
+
+ void markKeyFrameOrderDirty() {
+ context?.dirty(_sortAndValidateKeyFrames);
+ }
+
+ void _sortAndValidateKeyFrames() {
+ sort();
+ for (int i = 0; i < _keyframes.length - 1; i++) {
+ var a = _keyframes[i];
+ var b = _keyframes[i + 1];
+ if (a.frame == b.frame) {
+ context.removeObject(a);
+ i--;
+ }
+ }
+ }
+
+ int get numFrames => _keyframes.length;
+ KeyFrame getFrameAt(int index) => _keyframes[index];
+ void apply(double seconds, double mix, Core object) {
+ if (_keyframes.isEmpty) {
+ return;
+ }
+ int idx = 0;
+ int mid = 0;
+ double closestSeconds = 0;
+ int start = 0;
+ int end = _keyframes.length - 1;
+ while (start <= end) {
+ mid = (start + end) >> 1;
+ closestSeconds = _keyframes[mid].seconds;
+ if (closestSeconds < seconds) {
+ start = mid + 1;
+ } else if (closestSeconds > seconds) {
+ end = mid - 1;
+ } else {
+ idx = start = mid;
+ break;
+ }
+ idx = start;
+ }
+ int pk = propertyKey;
+ if (idx == 0) {
+ var first = _keyframes[0];
+ first.apply(object, pk, mix);
+ } else {
+ if (idx < _keyframes.length) {
+ KeyFrame fromFrame = _keyframes[idx - 1];
+ KeyFrame toFrame = _keyframes[idx];
+ if (seconds == toFrame.seconds) {
+ toFrame.apply(object, pk, mix);
+ } else {
+ if (fromFrame.interpolationType == 0) {
+ fromFrame.apply(object, pk, mix);
+ } else {
+ fromFrame.applyInterpolation(object, pk, seconds, toFrame, mix);
+ }
+ }
+ } else {
+ var last = _keyframes[idx - 1];
+ last.apply(object, pk, mix);
+ }
+ }
+ }
+
+ @override
+ void propertyKeyChanged(int from, int to) {}
+}
diff --git a/lib/src/rive_core/animation/keyframe.dart b/lib/src/rive_core/animation/keyframe.dart
new file mode 100644
index 0000000..7fd4bc8
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe.dart
@@ -0,0 +1,56 @@
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/interpolator.dart';
+import 'package:rive/src/rive_core/animation/keyed_property.dart';
+import 'package:rive/src/rive_core/animation/keyframe_interpolation.dart';
+import 'package:rive/src/rive_core/animation/linear_animation.dart';
+import 'package:rive/src/generated/animation/keyframe_base.dart';
+export 'package:rive/src/generated/animation/keyframe_base.dart';
+
+abstract class KeyFrame extends KeyFrameBase
+ implements KeyFrameInterface {
+ double _timeInSeconds;
+ double get seconds => _timeInSeconds;
+ KeyFrameInterpolation get interpolation => interpolationType == null
+ ? null
+ : KeyFrameInterpolation.values[interpolationType];
+ set interpolation(KeyFrameInterpolation value) {
+ interpolationType = value.index;
+ }
+
+ @override
+ void interpolationTypeChanged(int from, int to) {}
+ @override
+ void interpolatorIdChanged(int from, int to) {
+ interpolator = context?.resolve(to);
+ }
+
+ @override
+ void onAdded() {}
+ void computeSeconds(LinearAnimation animation) {
+ _timeInSeconds = frame / animation.fps;
+ }
+
+ @override
+ void onAddedDirty() {
+ if (interpolatorId != null) {
+ interpolator = context?.resolve(interpolatorId);
+ }
+ }
+
+ @override
+ void onRemoved() {}
+ @override
+ void frameChanged(int from, int to) {}
+ void apply(Core object, int propertyKey, double mix);
+ void applyInterpolation(Core object, int propertyKey, double seconds,
+ covariant KeyFrame nextFrame, double mix);
+ Interpolator _interpolator;
+ Interpolator get interpolator => _interpolator;
+ set interpolator(Interpolator value) {
+ if (_interpolator == value) {
+ return;
+ }
+ _interpolator = value;
+ interpolatorId = value?.id;
+ }
+}
diff --git a/lib/src/rive_core/animation/keyframe_color.dart b/lib/src/rive_core/animation/keyframe_color.dart
new file mode 100644
index 0000000..8345368
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe_color.dart
@@ -0,0 +1,49 @@
+import 'dart:ui';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyframe_interpolation.dart';
+import 'package:rive/src/generated/animation/keyframe_color_base.dart';
+import 'package:rive/src/generated/rive_core_context.dart';
+export 'package:rive/src/generated/animation/keyframe_color_base.dart';
+
+class KeyFrameColor extends KeyFrameColorBase {
+ @override
+ void apply(Core object, int propertyKey, double mix) {
+ if (mix == 1) {
+ RiveCoreContext.setColor(object, propertyKey, value);
+ } else {
+ var mixedColor = Color.lerp(
+ Color(RiveCoreContext.getColor(object, propertyKey)),
+ Color(value),
+ mix);
+ RiveCoreContext.setColor(object, propertyKey, mixedColor.value);
+ }
+ }
+
+ @override
+ void onAdded() {
+ super.onAdded();
+ interpolation ??= KeyFrameInterpolation.linear;
+ }
+
+ @override
+ void applyInterpolation(Core object, int propertyKey,
+ double currentTime, KeyFrameColor nextFrame, double mix) {
+ var f = (currentTime - seconds) / (nextFrame.seconds - seconds);
+ if (interpolator != null) {
+ f = interpolator.transform(f);
+ }
+ var interpolatedValue = Color.lerp(Color(value), Color(nextFrame.value), f);
+ if (mix == 1) {
+ RiveCoreContext.setColor(object, propertyKey, interpolatedValue.value);
+ } else {
+ var mixedColor = Color.lerp(
+ Color(RiveCoreContext.getColor(object, propertyKey)),
+ interpolatedValue,
+ mix);
+ RiveCoreContext.setColor(object, propertyKey, mixedColor.value);
+ }
+ }
+
+ @override
+ void valueChanged(int from, int to) {}
+}
diff --git a/lib/src/rive_core/animation/keyframe_double.dart b/lib/src/rive_core/animation/keyframe_double.dart
new file mode 100644
index 0000000..5ec7611
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe_double.dart
@@ -0,0 +1,41 @@
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyframe_interpolation.dart';
+import 'package:rive/src/generated/animation/keyframe_double_base.dart';
+import 'package:rive/src/generated/rive_core_context.dart';
+export 'package:rive/src/generated/animation/keyframe_double_base.dart';
+
+class KeyFrameDouble extends KeyFrameDoubleBase {
+ @override
+ void apply(Core object, int propertyKey, double mix) {
+ RiveCoreContext.setDouble(object, propertyKey, value * mix);
+ }
+
+ @override
+ void onAdded() {
+ super.onAdded();
+ interpolation ??= KeyFrameInterpolation.linear;
+ }
+
+ @override
+ void applyInterpolation(Core object, int propertyKey,
+ double currentTime, KeyFrameDouble nextFrame, double mix) {
+ var f = (currentTime - seconds) / (nextFrame.seconds - seconds);
+ if (interpolator != null) {
+ f = interpolator.transform(f);
+ }
+ var interpolatedValue = value + (nextFrame.value - value) * f;
+ if (mix == 1) {
+ RiveCoreContext.setDouble(object, propertyKey, interpolatedValue);
+ } else {
+ var mixi = 1.0 - mix;
+ RiveCoreContext.setDouble(
+ object,
+ propertyKey,
+ RiveCoreContext.getDouble(object, propertyKey) * mixi +
+ interpolatedValue * mix);
+ }
+ }
+
+ @override
+ void valueChanged(double from, double to) {}
+}
diff --git a/lib/src/rive_core/animation/keyframe_draw_order.dart b/lib/src/rive_core/animation/keyframe_draw_order.dart
new file mode 100644
index 0000000..5985a02
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe_draw_order.dart
@@ -0,0 +1,37 @@
+import 'dart:collection';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyframe_draw_order_value.dart';
+import 'package:rive/src/generated/animation/keyframe_draw_order_base.dart';
+
+class KeyFrameDrawOrder extends KeyFrameDrawOrderBase {
+ final HashSet _values =
+ HashSet();
+ bool internalAddValue(KeyFrameDrawOrderValue value) {
+ if (_values.contains(value)) {
+ return false;
+ }
+ _values.add(value);
+ return true;
+ }
+
+ bool internalRemoveValue(KeyFrameDrawOrderValue value) {
+ if (_values.remove(value)) {
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ void apply(Core object, int propertyKey, double mix) {
+ for (final value in _values) {
+ value.apply(object.context);
+ }
+ }
+
+ @override
+ void applyInterpolation(Core object, int propertyKey,
+ double seconds, KeyFrame nextFrame, double mix) {
+ apply(object, propertyKey, mix);
+ }
+}
diff --git a/lib/src/rive_core/animation/keyframe_draw_order_value.dart b/lib/src/rive_core/animation/keyframe_draw_order_value.dart
new file mode 100644
index 0000000..ae5f7a7
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe_draw_order_value.dart
@@ -0,0 +1,28 @@
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/drawable.dart';
+import 'package:rive/src/generated/animation/keyframe_draw_order_value_base.dart';
+
+class KeyFrameDrawOrderValue extends KeyFrameDrawOrderValueBase {
+ @override
+ void onAdded() {}
+ @override
+ void drawableIdChanged(int from, int to) {}
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {}
+ @override
+ void valueChanged(int from, int to) {}
+ void apply(CoreContext context) {
+ var drawable = context.resolve(drawableId);
+ if (drawable != null) {
+ drawable.drawOrder = value;
+ }
+ }
+
+ @override
+ int runtimeValueValue(int editorValue) {
+ assert(false, 'this should never get called');
+ return 0;
+ }
+}
diff --git a/lib/src/rive_core/animation/keyframe_interpolation.dart b/lib/src/rive_core/animation/keyframe_interpolation.dart
new file mode 100644
index 0000000..015c144
--- /dev/null
+++ b/lib/src/rive_core/animation/keyframe_interpolation.dart
@@ -0,0 +1 @@
+enum KeyFrameInterpolation { hold, linear, cubic }
diff --git a/lib/src/rive_core/animation/linear_animation.dart b/lib/src/rive_core/animation/linear_animation.dart
new file mode 100644
index 0000000..92c1162
--- /dev/null
+++ b/lib/src/rive_core/animation/linear_animation.dart
@@ -0,0 +1,47 @@
+import 'dart:collection';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/keyed_object.dart';
+import 'package:rive/src/rive_core/animation/loop.dart';
+import 'package:rive/src/generated/animation/linear_animation_base.dart';
+export 'package:rive/src/generated/animation/linear_animation_base.dart';
+
+class LinearAnimation extends LinearAnimationBase {
+ final _keyedObjects = HashMap();
+ Iterable get keyedObjects => _keyedObjects.values;
+ bool internalAddKeyedObject(KeyedObject object) {
+ assert(
+ object.objectId != null,
+ 'KeyedObject must be referencing a Core object '
+ 'before being added to an animation.');
+ var value = _keyedObjects[object.objectId];
+ if (value != null && value != object) {
+ return false;
+ }
+ _keyedObjects[object.objectId] = object;
+ return true;
+ }
+
+ void apply(double time, {double mix = 1, CoreContext coreContext}) {
+ coreContext ??= context;
+ for (final keyedObject in _keyedObjects.values) {
+ keyedObject.apply(time, mix, coreContext);
+ }
+ }
+
+ Loop get loop => Loop.values[loopValue];
+ set loop(Loop value) => loopValue = value.index;
+ @override
+ void durationChanged(int from, int to) {}
+ @override
+ void enableWorkAreaChanged(bool from, bool to) {}
+ @override
+ void fpsChanged(int from, int to) {}
+ @override
+ void loopValueChanged(int from, int to) {}
+ @override
+ void speedChanged(double from, double to) {}
+ @override
+ void workEndChanged(int from, int to) {}
+ @override
+ void workStartChanged(int from, int to) {}
+}
diff --git a/lib/src/rive_core/animation/loop.dart b/lib/src/rive_core/animation/loop.dart
new file mode 100644
index 0000000..c0f3046
--- /dev/null
+++ b/lib/src/rive_core/animation/loop.dart
@@ -0,0 +1 @@
+enum Loop { oneShot, loop, pingPong }
diff --git a/lib/src/rive_core/artboard.dart b/lib/src/rive_core/artboard.dart
new file mode 100644
index 0000000..fda90d6
--- /dev/null
+++ b/lib/src/rive_core/artboard.dart
@@ -0,0 +1,255 @@
+import 'dart:ui';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/animation/animation.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/drawable.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/rive_animation_controller.dart';
+import 'package:rive/src/rive_core/shapes/paint/fill.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
+import 'package:rive/src/utilities/dependency_sorter.dart';
+import 'package:rive/src/generated/artboard_base.dart';
+export 'package:rive/src/generated/artboard_base.dart';
+
+class Artboard extends ArtboardBase with ShapePaintContainer {
+ @override
+ bool get canBeOrphaned => true;
+ final Path path = Path();
+ List _dependencyOrder = [];
+ final DrawableList _drawables = DrawableList();
+ final Set _components = {};
+ DrawableList get drawables => _drawables;
+ final AnimationList _animations = AnimationList();
+ AnimationList get animations => _animations;
+ bool get hasAnimations => _animations.isNotEmpty;
+ int _dirtDepth = 0;
+ int _dirt = 255;
+ void forEachComponent(void Function(Component) callback) =>
+ _components.forEach(callback);
+ @override
+ Artboard get artboard => this;
+ Vec2D get originWorld {
+ return Vec2D.fromValues(
+ x + width * (originX ?? 0), y + height * (originY ?? 0));
+ }
+
+ bool updateComponents() {
+ bool didUpdate = false;
+ if ((_dirt & ComponentDirt.drawOrder) != 0) {
+ _drawables.sortDrawables();
+ _dirt &= ~ComponentDirt.drawOrder;
+ didUpdate = true;
+ }
+ if ((_dirt & ComponentDirt.components) != 0) {
+ const int maxSteps = 100;
+ int step = 0;
+ int count = _dependencyOrder.length;
+ while ((_dirt & ComponentDirt.components) != 0 && step < maxSteps) {
+ _dirt &= ~ComponentDirt.components;
+ for (int i = 0; i < count; i++) {
+ Component component = _dependencyOrder[i];
+ _dirtDepth = i;
+ int d = component.dirt;
+ if (d == 0) {
+ continue;
+ }
+ component.dirt = 0;
+ component.update(d);
+ if (_dirtDepth < i) {
+ break;
+ }
+ }
+ step++;
+ }
+ return true;
+ }
+ return didUpdate;
+ }
+
+ bool advance(double elapsedSeconds) {
+ bool didUpdate = false;
+ for (final controller in _animationControllers) {
+ if (controller.isActive) {
+ controller.apply(context, elapsedSeconds);
+ didUpdate = true;
+ }
+ }
+ return updateComponents() || didUpdate;
+ }
+
+ @override
+ void childAdded(Component child) {
+ super.childAdded(child);
+ if (child is Fill) {
+ addFill(child);
+ }
+ }
+
+ @override
+ void childRemoved(Component child) {
+ super.childRemoved(child);
+ if (child is Fill) {
+ removeFill(child);
+ }
+ }
+
+ @override
+ void heightChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ }
+
+ void onComponentDirty(Component component) {
+ if ((dirt & ComponentDirt.components) == 0) {
+ context?.markNeedsAdvance();
+ _dirt |= ComponentDirt.components;
+ }
+ if (component.graphOrder < _dirtDepth) {
+ _dirtDepth = component.graphOrder;
+ }
+ }
+
+ @override
+ bool resolveArtboard() => true;
+ void sortDependencies() {
+ var optimistic = DependencySorter();
+ var order = optimistic.sort(this);
+ if (order == null) {
+ var robust = TarjansDependencySorter();
+ order = robust.sort(this);
+ }
+ _dependencyOrder = order;
+ for (final component in _dependencyOrder) {
+ component.graphOrder = graphOrder++;
+ }
+ _dirt |= ComponentDirt.components;
+ }
+
+ @override
+ void update(int dirt) {
+ if (dirt & ComponentDirt.worldTransform != 0) {
+ var bounds = worldBounds;
+ var rect = Rect.fromLTWH(bounds[0], bounds[1], bounds[2], bounds[3]);
+ path.reset();
+ path.addRect(rect);
+ }
+ }
+
+ @override
+ void widthChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ }
+
+ Vec2D renderTranslation(Vec2D worldTranslation) {
+ final wt = originWorld;
+ return Vec2D.add(Vec2D(), worldTranslation, wt);
+ }
+
+ void addComponent(Component component) {
+ if (!_components.add(component)) {
+ return;
+ }
+ if (component is Drawable) {
+ assert(!_drawables.contains(component));
+ _drawables.add(component);
+ markDrawOrderDirty();
+ }
+ }
+
+ void removeComponent(Component component) {
+ _components.remove(component);
+ if (component is Drawable) {
+ _drawables.remove(component);
+ }
+ }
+
+ void markDrawOrderDirty() {
+ if ((dirt & ComponentDirt.drawOrder) == 0) {
+ context?.markNeedsAdvance();
+ _dirt |= ComponentDirt.drawOrder;
+ }
+ }
+
+ void draw(Canvas canvas) {
+ for (final fill in fills) {
+ fill.draw(canvas, path);
+ }
+ canvas.save();
+ canvas.clipRect(Rect.fromLTWH(0, 0, width, height));
+ for (final drawable in _drawables) {
+ drawable.draw(canvas);
+ }
+ canvas.restore();
+ }
+
+ @override
+ AABB get localBounds => AABB.fromValues(0, 0, width, height);
+ @override
+ AABB get worldBounds => localBounds;
+ @override
+ Mat2D get worldTransform => Mat2D();
+ @override
+ void originXChanged(double from, double to) {}
+ @override
+ void originYChanged(double from, double to) {}
+ bool internalAddAnimation(Animation animation) {
+ if (_animations.contains(animation)) {
+ return false;
+ }
+ _animations.add(animation);
+ return true;
+ }
+
+ bool internalRemoveAnimation(Animation animation) {
+ bool removed = _animations.remove(animation);
+ return removed;
+ }
+
+ final Set _animationControllers = {};
+ bool addController(RiveAnimationController controller) {
+ assert(controller != null);
+ if (_animationControllers.contains(controller) ||
+ !controller.init(context)) {
+ return false;
+ }
+ controller.isActiveChanged.addListener(_onControllerPlayingChanged);
+ _animationControllers.add(controller);
+ if (controller.isActive) {
+ context?.markNeedsAdvance();
+ }
+ return true;
+ }
+
+ bool removeController(RiveAnimationController controller) {
+ assert(controller != null);
+ if (_animationControllers.remove(controller)) {
+ controller.isActiveChanged.removeListener(_onControllerPlayingChanged);
+ controller.dispose();
+ return true;
+ }
+ return false;
+ }
+
+ void _onControllerPlayingChanged() => context?.markNeedsAdvance();
+ @override
+ void onFillsChanged() {}
+ @override
+ void onPaintMutatorChanged(ShapePaintMutator mutator) {}
+ @override
+ void onStrokesChanged() {}
+ @override
+ Vec2D get worldTranslation => Vec2D();
+}
diff --git a/lib/src/rive_core/backboard.dart b/lib/src/rive_core/backboard.dart
new file mode 100644
index 0000000..eb0fc9a
--- /dev/null
+++ b/lib/src/rive_core/backboard.dart
@@ -0,0 +1,11 @@
+import 'package:rive/src/generated/backboard_base.dart';
+export 'package:rive/src/generated/backboard_base.dart';
+
+class Backboard extends BackboardBase {
+ @override
+ void onAdded() {}
+ @override
+ void onAddedDirty() {}
+ @override
+ void onRemoved() {}
+}
diff --git a/lib/src/rive_core/bounds_delegate.dart b/lib/src/rive_core/bounds_delegate.dart
new file mode 100644
index 0000000..48de16b
--- /dev/null
+++ b/lib/src/rive_core/bounds_delegate.dart
@@ -0,0 +1,3 @@
+abstract class BoundsDelegate {
+ void boundsChanged();
+}
diff --git a/lib/src/rive_core/component.dart b/lib/src/rive_core/component.dart
new file mode 100644
index 0000000..30fa108
--- /dev/null
+++ b/lib/src/rive_core/component.dart
@@ -0,0 +1,182 @@
+import 'package:rive/src/core/core.dart';
+import 'package:flutter/foundation.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+import 'package:rive/src/generated/component_base.dart';
+import 'package:rive/src/utilities/dependency_sorter.dart';
+import 'package:rive/src/utilities/tops.dart';
+export 'package:rive/src/generated/component_base.dart';
+
+abstract class Component extends ComponentBase
+ implements DependencyGraphNode, Parentable {
+ Artboard _artboard;
+ dynamic _userData;
+ bool get canBeOrphaned => false;
+ int graphOrder = 0;
+ int dirt = 255;
+ static const int maxTreeDepth = 5000;
+ bool addDirt(int value, {bool recurse = false}) {
+ if ((dirt & value) == value) {
+ return false;
+ }
+ dirt |= value;
+ onDirty(dirt);
+ artboard?.onComponentDirty(this);
+ if (!recurse) {
+ return true;
+ }
+ for (final d in dependents) {
+ d.addDirt(value, recurse: recurse);
+ }
+ return true;
+ }
+
+ void onDirty(int mask) {}
+ void update(int dirt);
+ Artboard get artboard => _artboard;
+ void _changeArtboard(Artboard value) {
+ if (_artboard == value) {
+ return;
+ }
+ _artboard?.removeComponent(this);
+ _artboard = value;
+ _artboard?.addComponent(this);
+ }
+
+ void visitAncestor(Component ancestor) {}
+ bool resolveArtboard() {
+ int sanity = maxTreeDepth;
+ for (Component curr = this;
+ curr != null && sanity > 0;
+ curr = curr.parent, sanity--) {
+ visitAncestor(curr);
+ if (curr is Artboard) {
+ _changeArtboard(curr);
+ return true;
+ }
+ }
+ _changeArtboard(null);
+ return false;
+ }
+
+ dynamic get userData => _userData;
+ set userData(dynamic value) {
+ if (value == _userData) {
+ return;
+ }
+ dynamic last = _userData;
+ _userData = value;
+ userDataChanged(last, value);
+ }
+
+ void userDataChanged(dynamic from, dynamic to) {}
+ @override
+ void parentIdChanged(int from, int to) {
+ parent = context?.resolve(to);
+ }
+
+ ContainerComponent _parent;
+ @override
+ ContainerComponent get parent => _parent;
+ set parent(ContainerComponent value) {
+ if (_parent == value) {
+ return;
+ }
+ var old = _parent;
+ _parent = value;
+ parentId = value?.id;
+ parentChanged(old, value);
+ }
+
+ @protected
+ void parentChanged(ContainerComponent from, ContainerComponent to) {
+ if (from != null) {
+ from.children.remove(this);
+ from.childRemoved(this);
+ }
+ if (to != null) {
+ to.children.add(this);
+ to.childAdded(this);
+ }
+ markRebuildDependencies();
+ }
+
+ final Set _dependents = {};
+ final Set _dependsOn = {};
+ @override
+ Set get dependents => _dependents;
+ bool addDependent(Component dependent) {
+ assert(dependent != null, "Dependent cannot be null.");
+ assert(artboard == dependent.artboard,
+ "Components must be in the same artboard.");
+ if (!_dependents.add(dependent)) {
+ return false;
+ }
+ dependent._dependsOn.add(this);
+ return true;
+ }
+
+ bool isValidParent(Component parent) => parent is ContainerComponent;
+ void markRebuildDependencies() {
+ if (context == null || !context.markDependenciesDirty(this)) {
+ return;
+ }
+ for (final dependent in _dependents) {
+ dependent.markRebuildDependencies();
+ }
+ }
+
+ @mustCallSuper
+ void buildDependencies() {
+ for (final parentDep in _dependsOn) {
+ parentDep._dependents.remove(this);
+ }
+ _dependsOn.clear();
+ }
+
+ void onDependencyRemoved(Component dependent) {}
+ @override
+ @mustCallSuper
+ void onAdded() {
+ if (!canBeOrphaned && parent == null) {
+ remove();
+ }
+ }
+
+ @override
+ void onAddedDirty() {
+ if (parentId != null) {
+ parent = context?.resolve(parentId);
+ }
+ }
+
+ @override
+ @mustCallSuper
+ void onRemoved() {
+ for (final parentDep in _dependsOn) {
+ parentDep._dependents.remove(this);
+ }
+ _dependsOn.clear();
+ for (final dependent in _dependents) {
+ dependent.onDependencyRemoved(this);
+ }
+ _dependents.clear();
+ if (parent != null) {
+ parent.children.remove(this);
+ parent.childRemoved(this);
+ }
+ if (artboard != null) {
+ context?.markDependencyOrderDirty();
+ _changeArtboard(null);
+ }
+ }
+
+ @override
+ String toString() {
+ return '${super.toString()} ($id)';
+ }
+
+ void remove() => context?.removeObject(this);
+ @override
+ void nameChanged(String from, String to) {}
+}
diff --git a/lib/src/rive_core/component_dirt.dart b/lib/src/rive_core/component_dirt.dart
new file mode 100644
index 0000000..8b35c68
--- /dev/null
+++ b/lib/src/rive_core/component_dirt.dart
@@ -0,0 +1,11 @@
+class ComponentDirt {
+ static const int dependents = 1 << 0;
+ static const int components = 1 << 1;
+ static const int drawOrder = 1 << 2;
+ static const int path = 1 << 3;
+ static const int vertices = 1 << 4;
+ static const int transform = 1 << 5;
+ static const int worldTransform = 1 << 6;
+ static const int paint = 1 << 7;
+ static const int stops = 1 << 8;
+}
diff --git a/lib/src/rive_core/container_component.dart b/lib/src/rive_core/container_component.dart
new file mode 100644
index 0000000..e777fbe
--- /dev/null
+++ b/lib/src/rive_core/container_component.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/generated/container_component_base.dart';
+
+typedef bool DescentCallback(Component component);
+
+abstract class ContainerComponent extends ContainerComponentBase {
+ final ContainerChildren children = ContainerChildren();
+ void appendChild(Component child) {
+ child.parent = this;
+ }
+
+ @mustCallSuper
+ void childAdded(Component child) {}
+ void childRemoved(Component child) {}
+ bool forAll(DescentCallback cb) {
+ if (cb(this) == false) {
+ return false;
+ }
+ forEachChild(cb);
+ return true;
+ }
+
+ void forEachChild(DescentCallback cb) {
+ for (final child in children) {
+ if (cb(child) == false) {
+ continue;
+ }
+ if (child is ContainerComponent) {
+ child.forEachChild(cb);
+ }
+ }
+ }
+
+ void removeRecursive() {
+ assert(context != null);
+ Set deathRow = {this};
+ forEachChild((child) => deathRow.add(child));
+ deathRow.forEach(context.removeObject);
+ }
+}
diff --git a/lib/src/rive_core/drawable.dart b/lib/src/rive_core/drawable.dart
new file mode 100644
index 0000000..83bb3fa
--- /dev/null
+++ b/lib/src/rive_core/drawable.dart
@@ -0,0 +1,15 @@
+import 'dart:ui';
+import 'package:rive/src/generated/drawable_base.dart';
+export 'package:rive/src/generated/drawable_base.dart';
+
+abstract class Drawable extends DrawableBase {
+ void draw(Canvas canvas);
+ BlendMode get blendMode => BlendMode.values[blendModeValue];
+ set blendMode(BlendMode value) => blendModeValue = value.index;
+ @override
+ void blendModeValueChanged(int from, int to) {}
+ @override
+ void drawOrderChanged(int from, int to) {
+ artboard?.markDrawOrderDirty();
+ }
+}
diff --git a/lib/src/rive_core/event.dart b/lib/src/rive_core/event.dart
new file mode 100644
index 0000000..a8f87db
--- /dev/null
+++ b/lib/src/rive_core/event.dart
@@ -0,0 +1,6 @@
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+
+class Event extends ChangeNotifier {
+ void notify() => notifyListeners();
+}
diff --git a/lib/src/rive_core/math/aabb.dart b/lib/src/rive_core/math/aabb.dart
new file mode 100644
index 0000000..7d1f2a4
--- /dev/null
+++ b/lib/src/rive_core/math/aabb.dart
@@ -0,0 +1,213 @@
+import 'dart:math';
+import "dart:typed_data";
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import "vec2d.dart";
+
+class AABB {
+ Float32List _buffer;
+ Float32List get values {
+ return _buffer;
+ }
+
+ Vec2D get topLeft => minimum;
+ Vec2D get topRight {
+ return Vec2D.fromValues(_buffer[2], _buffer[1]);
+ }
+
+ Vec2D get bottomRight => maximum;
+ Vec2D get bottomLeft {
+ return Vec2D.fromValues(_buffer[0], _buffer[3]);
+ }
+
+ Vec2D get minimum {
+ return Vec2D.fromValues(_buffer[0], _buffer[1]);
+ }
+
+ Vec2D get maximum {
+ return Vec2D.fromValues(_buffer[2], _buffer[3]);
+ }
+
+ AABB() {
+ _buffer = Float32List.fromList([0.0, 0.0, 0.0, 0.0]);
+ }
+ AABB.clone(AABB a) {
+ _buffer = Float32List.fromList(a.values);
+ }
+ AABB.fromValues(double a, double b, double c, double d) {
+ _buffer = Float32List.fromList([a, b, c, d]);
+ }
+ AABB.empty() {
+ _buffer = Float32List.fromList([
+ double.maxFinite,
+ double.maxFinite,
+ -double.maxFinite,
+ -double.maxFinite
+ ]);
+ }
+ Vec2D includePoint(Vec2D point, Mat2D transform) {
+ var transformedPoint = transform == null
+ ? point
+ : Vec2D.transformMat2D(Vec2D(), point, transform);
+ var x = transformedPoint[0];
+ var y = transformedPoint[1];
+ if (x < _buffer[0]) {
+ _buffer[0] = x;
+ }
+ if (x > _buffer[2]) {
+ _buffer[2] = x;
+ }
+ if (y < _buffer[1]) {
+ _buffer[1] = y;
+ }
+ if (y > _buffer[3]) {
+ _buffer[3] = y;
+ }
+ return transformedPoint;
+ }
+
+ AABB.fromMinMax(Vec2D min, Vec2D max) {
+ _buffer = Float32List.fromList([min[0], min[1], max[0], max[1]]);
+ }
+ static bool areEqual(AABB a, AABB b) {
+ return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3];
+ }
+
+ double get width => _buffer[2] - _buffer[0];
+ double get height => _buffer[3] - _buffer[1];
+ double operator [](int idx) {
+ return _buffer[idx];
+ }
+
+ void operator []=(int idx, double v) {
+ _buffer[idx] = v;
+ }
+
+ static AABB copy(AABB out, AABB a) {
+ out[0] = a[0];
+ out[1] = a[1];
+ out[2] = a[2];
+ out[3] = a[3];
+ return out;
+ }
+
+ static Vec2D center(Vec2D out, AABB a) {
+ out[0] = (a[0] + a[2]) * 0.5;
+ out[1] = (a[1] + a[3]) * 0.5;
+ return out;
+ }
+
+ static Vec2D size(Vec2D out, AABB a) {
+ out[0] = a[2] - a[0];
+ out[1] = a[3] - a[1];
+ return out;
+ }
+
+ static Vec2D extents(Vec2D out, AABB a) {
+ out[0] = (a[2] - a[0]) * 0.5;
+ out[1] = (a[3] - a[1]) * 0.5;
+ return out;
+ }
+
+ static double perimeter(AABB a) {
+ double wx = a[2] - a[0];
+ double wy = a[3] - a[1];
+ return 2.0 * (wx + wy);
+ }
+
+ static AABB combine(AABB out, AABB a, AABB b) {
+ out[0] = min(a[0], b[0]);
+ out[1] = min(a[1], b[1]);
+ out[2] = max(a[2], b[2]);
+ out[3] = max(a[3], b[3]);
+ return out;
+ }
+
+ static bool contains(AABB a, AABB b) {
+ return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3];
+ }
+
+ static bool isValid(AABB a) {
+ double dx = a[2] - a[0];
+ double dy = a[3] - a[1];
+ return dx >= 0 &&
+ dy >= 0 &&
+ a[0] <= double.maxFinite &&
+ a[1] <= double.maxFinite &&
+ a[2] <= double.maxFinite &&
+ a[3] <= double.maxFinite;
+ }
+
+ static bool testOverlap(AABB a, AABB b) {
+ double d1x = b[0] - a[2];
+ double d1y = b[1] - a[3];
+ double d2x = a[0] - b[2];
+ double d2y = a[1] - b[3];
+ if (d1x > 0.0 || d1y > 0.0) {
+ return false;
+ }
+ if (d2x > 0.0 || d2y > 0.0) {
+ return false;
+ }
+ return true;
+ }
+
+ AABB translate(Vec2D vec) => AABB.fromValues(_buffer[0] + vec[0],
+ _buffer[1] + vec[1], _buffer[2] + vec[0], _buffer[3] + vec[1]);
+ @override
+ String toString() {
+ return _buffer.toString();
+ }
+
+ AABB transform(Mat2D matrix) {
+ return AABB.fromPoints([
+ minimum,
+ Vec2D.fromValues(maximum[0], minimum[1]),
+ maximum,
+ Vec2D.fromValues(minimum[0], maximum[1])
+ ], transform: matrix);
+ }
+
+ AABB.fromPoints(Iterable points,
+ {Mat2D transform, double expand = 0}) {
+ double minX = double.maxFinite;
+ double minY = double.maxFinite;
+ double maxX = -double.maxFinite;
+ double maxY = -double.maxFinite;
+ for (final point in points) {
+ var p = transform == null
+ ? point
+ : Vec2D.transformMat2D(Vec2D(), point, transform);
+ double x = p[0];
+ double y = p[1];
+ if (x < minX) {
+ minX = x;
+ }
+ if (y < minY) {
+ minY = y;
+ }
+ if (x > maxX) {
+ maxX = x;
+ }
+ if (y > maxY) {
+ maxY = y;
+ }
+ }
+ if (expand != 0) {
+ double width = maxX - minX;
+ double diff = expand - width;
+ if (diff > 0) {
+ diff /= 2;
+ minX -= diff;
+ maxX += diff;
+ }
+ double height = maxY - minY;
+ diff = expand - height;
+ if (diff > 0) {
+ diff /= 2;
+ minY -= diff;
+ maxY += diff;
+ }
+ }
+ _buffer = Float32List.fromList([minX, minY, maxX, maxY]);
+ }
+}
diff --git a/lib/src/rive_core/math/circle_constant.dart b/lib/src/rive_core/math/circle_constant.dart
new file mode 100644
index 0000000..08aee37
--- /dev/null
+++ b/lib/src/rive_core/math/circle_constant.dart
@@ -0,0 +1 @@
+double circleConstant = 0.552284749831;
diff --git a/lib/src/rive_core/math/mat2d.dart b/lib/src/rive_core/math/mat2d.dart
new file mode 100644
index 0000000..cab0418
--- /dev/null
+++ b/lib/src/rive_core/math/mat2d.dart
@@ -0,0 +1,234 @@
+import "dart:math";
+import "dart:typed_data";
+import "transform_components.dart";
+import "vec2d.dart";
+
+class Mat2D {
+ Float32List _buffer;
+ Float32List get values {
+ return _buffer;
+ }
+
+ Float64List get mat4 {
+ return Float64List.fromList([
+ _buffer[0],
+ _buffer[1],
+ 0.0,
+ 0.0,
+ _buffer[2],
+ _buffer[3],
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0,
+ 0.0,
+ _buffer[4],
+ _buffer[5],
+ 0.0,
+ 1.0
+ ]);
+ }
+
+ double operator [](int index) {
+ return _buffer[index];
+ }
+
+ void operator []=(int index, double value) {
+ _buffer[index] = value;
+ }
+
+ Mat2D() {
+ _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
+ }
+ Mat2D.fromTranslation(Vec2D translation) {
+ _buffer = Float32List.fromList(
+ [1.0, 0.0, 0.0, 1.0, translation[0], translation[1]]);
+ }
+ Mat2D.fromScaling(Vec2D scaling) {
+ _buffer = Float32List.fromList([scaling[0], 0, 0, scaling[1], 0, 0]);
+ }
+ Mat2D.clone(Mat2D copy) {
+ _buffer = Float32List.fromList(copy.values);
+ }
+ static Mat2D fromRotation(Mat2D o, double rad) {
+ double s = sin(rad);
+ double c = cos(rad);
+ o[0] = c;
+ o[1] = s;
+ o[2] = -s;
+ o[3] = c;
+ o[4] = 0.0;
+ o[5] = 0.0;
+ return o;
+ }
+
+ static void copy(Mat2D o, Mat2D f) {
+ o[0] = f[0];
+ o[1] = f[1];
+ o[2] = f[2];
+ o[3] = f[3];
+ o[4] = f[4];
+ o[5] = f[5];
+ }
+
+ static void copyFromList(Mat2D o, Float32List f) {
+ o[0] = f[0];
+ o[1] = f[1];
+ o[2] = f[2];
+ o[3] = f[3];
+ o[4] = f[4];
+ o[5] = f[5];
+ }
+
+ static void scale(Mat2D o, Mat2D a, Vec2D v) {
+ double a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ v0 = v[0],
+ v1 = v[1];
+ o[0] = a0 * v0;
+ o[1] = a1 * v0;
+ o[2] = a2 * v1;
+ o[3] = a3 * v1;
+ o[4] = a4;
+ o[5] = a5;
+ }
+
+ static void scaleByValues(Mat2D o, double x, double y) {
+ o[0] *= x;
+ o[1] *= x;
+ o[2] *= y;
+ o[3] *= y;
+ }
+
+ static Mat2D multiply(Mat2D o, Mat2D a, Mat2D b) {
+ double a0 = a[0],
+ a1 = a[1],
+ a2 = a[2],
+ a3 = a[3],
+ a4 = a[4],
+ a5 = a[5],
+ b0 = b[0],
+ b1 = b[1],
+ b2 = b[2],
+ b3 = b[3],
+ b4 = b[4],
+ b5 = b[5];
+ o[0] = a0 * b0 + a2 * b1;
+ o[1] = a1 * b0 + a3 * b1;
+ o[2] = a0 * b2 + a2 * b3;
+ o[3] = a1 * b2 + a3 * b3;
+ o[4] = a0 * b4 + a2 * b5 + a4;
+ o[5] = a1 * b4 + a3 * b5 + a5;
+ return o;
+ }
+
+ static void cCopy(Mat2D o, Mat2D a) {
+ o[0] = a[0];
+ o[1] = a[1];
+ o[2] = a[2];
+ o[3] = a[3];
+ o[4] = a[4];
+ o[5] = a[5];
+ }
+
+ static Mat2D translate(Mat2D o, Mat2D a, Vec2D b) {
+ o[0] = a[0];
+ o[1] = a[1];
+ o[2] = a[2];
+ o[3] = a[3];
+ o[4] = a[4] + b[0];
+ o[5] = a[5] + b[1];
+ return o;
+ }
+
+ static bool invert(Mat2D o, Mat2D a) {
+ double aa = a[0], ab = a[1], ac = a[2], ad = a[3], atx = a[4], aty = a[5];
+ double det = aa * ad - ab * ac;
+ if (det == 0.0) {
+ return false;
+ }
+ det = 1.0 / det;
+ o[0] = ad * det;
+ o[1] = -ab * det;
+ o[2] = -ac * det;
+ o[3] = aa * det;
+ o[4] = (ac * aty - ad * atx) * det;
+ o[5] = (ab * atx - aa * aty) * det;
+ return true;
+ }
+
+ static void getScale(Mat2D m, Vec2D s) {
+ double x = m[0];
+ double y = m[1];
+ s[0] = x.sign * sqrt(x * x + y * y);
+ x = m[2];
+ y = m[3];
+ s[1] = y.sign * sqrt(x * x + y * y);
+ }
+
+ static Vec2D getTranslation(Mat2D m, Vec2D t) {
+ t[0] = m[4];
+ t[1] = m[5];
+ return t;
+ }
+
+ static void identity(Mat2D mat) {
+ mat[0] = 1.0;
+ mat[1] = 0.0;
+ mat[2] = 0.0;
+ mat[3] = 1.0;
+ mat[4] = 0.0;
+ mat[5] = 0.0;
+ }
+
+ static void decompose(Mat2D m, TransformComponents result) {
+ double m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3];
+ double rotation = atan2(m1, m0);
+ double denom = m0 * m0 + m1 * m1;
+ double scaleX = sqrt(denom);
+ double scaleY = (scaleX == 0) ? 0 : ((m0 * m3 - m2 * m1) / scaleX);
+ double skewX = atan2(m0 * m2 + m1 * m3, denom);
+ result[0] = m[4];
+ result[1] = m[5];
+ result[2] = scaleX;
+ result[3] = scaleY;
+ result[4] = rotation;
+ result[5] = skewX;
+ }
+
+ static void compose(Mat2D m, TransformComponents result) {
+ double r = result[4];
+ if (r != 0.0) {
+ Mat2D.fromRotation(m, r);
+ } else {
+ Mat2D.identity(m);
+ }
+ m[4] = result[0];
+ m[5] = result[1];
+ Mat2D.scale(m, m, result.scale);
+ double sk = result[5];
+ if (sk != 0.0) {
+ m[2] = m[0] * sk + m[2];
+ m[3] = m[1] * sk + m[3];
+ }
+ }
+
+ static bool areEqual(Mat2D a, Mat2D b) {
+ return a[0] == b[0] &&
+ a[1] == b[1] &&
+ a[2] == b[2] &&
+ a[3] == b[3] &&
+ a[4] == b[4] &&
+ a[5] == b[5];
+ }
+
+ @override
+ String toString() {
+ return _buffer.toString();
+ }
+}
diff --git a/lib/src/rive_core/math/segment2d.dart b/lib/src/rive_core/math/segment2d.dart
new file mode 100644
index 0000000..14eb98c
--- /dev/null
+++ b/lib/src/rive_core/math/segment2d.dart
@@ -0,0 +1,37 @@
+import 'package:rive/src/rive_core/math/vec2d.dart';
+
+class ProjectionResult {
+ final double t;
+ final Vec2D point;
+ ProjectionResult(this.t, this.point);
+}
+
+class Segment2D {
+ final Vec2D start;
+ final Vec2D end;
+ Vec2D diff;
+ double lengthSquared;
+ Segment2D(this.start, this.end);
+ ProjectionResult projectPoint(Vec2D point) {
+ if (diff == null) {
+ diff = Vec2D.subtract(Vec2D(), start, end);
+ lengthSquared = Vec2D.squaredLength(diff);
+ }
+ if (lengthSquared == 0) {
+ return ProjectionResult(0, start);
+ }
+ double t = ((point[0] - start[0]) * (end[0] - start[0]) +
+ (point[1] - start[1]) * (end[1] - start[1])) /
+ lengthSquared;
+ if (t < 0.0) {
+ return ProjectionResult(0, start);
+ }
+ if (t > 1.0) {
+ return ProjectionResult(1, end);
+ }
+ return ProjectionResult(
+ t,
+ Vec2D.fromValues(start[0] + t * (end[0] - start[0]),
+ start[1] + t * (end[1] - start[1])));
+ }
+}
diff --git a/lib/src/rive_core/math/transform_components.dart b/lib/src/rive_core/math/transform_components.dart
new file mode 100644
index 0000000..96aca8f
--- /dev/null
+++ b/lib/src/rive_core/math/transform_components.dart
@@ -0,0 +1,86 @@
+import 'dart:math';
+import "dart:typed_data";
+import "vec2d.dart";
+
+class TransformComponents {
+ Float32List _buffer;
+ Float32List get values {
+ return _buffer;
+ }
+
+ double operator [](int index) {
+ return _buffer[index];
+ }
+
+ void operator []=(int index, double value) {
+ _buffer[index] = value;
+ }
+
+ TransformComponents() {
+ _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
+ }
+ TransformComponents.clone(TransformComponents copy) {
+ _buffer = Float32List.fromList(copy.values);
+ }
+ double get x {
+ return _buffer[0];
+ }
+
+ set x(double value) {
+ _buffer[0] = value;
+ }
+
+ double get y {
+ return _buffer[1];
+ }
+
+ set y(double value) {
+ _buffer[1] = value;
+ }
+
+ double get scaleX {
+ return _buffer[2];
+ }
+
+ set scaleX(double value) {
+ _buffer[2] = value;
+ }
+
+ double get scaleY {
+ return _buffer[3];
+ }
+
+ set scaleY(double value) {
+ _buffer[3] = value;
+ }
+
+ double get rotation {
+ return _buffer[4];
+ }
+
+ set rotation(double value) {
+ _buffer[4] = value;
+ }
+
+ double get skew {
+ return _buffer[5];
+ }
+
+ set skew(double value) {
+ _buffer[5] = value;
+ }
+
+ Vec2D get translation {
+ return Vec2D.fromValues(_buffer[0], _buffer[1]);
+ }
+
+ Vec2D get scale {
+ return Vec2D.fromValues(_buffer[2], _buffer[3]);
+ }
+
+ @override
+ String toString() {
+ return 'TransformComponents(x: $x y: $y sx: $scaleX '
+ 'sy: $scaleY r: ${rotation / pi * 180} s: $skew)';
+ }
+}
diff --git a/lib/src/rive_core/math/vec2d.dart b/lib/src/rive_core/math/vec2d.dart
new file mode 100644
index 0000000..ec26993
--- /dev/null
+++ b/lib/src/rive_core/math/vec2d.dart
@@ -0,0 +1,169 @@
+import 'dart:math';
+import 'dart:typed_data';
+import 'mat2d.dart';
+
+class Vec2D {
+ Float32List _buffer;
+ Float32List get values {
+ return _buffer;
+ }
+
+ double operator [](int index) {
+ return _buffer[index];
+ }
+
+ void operator []=(int index, double value) {
+ _buffer[index] = value;
+ }
+
+ Vec2D() {
+ _buffer = Float32List.fromList([0.0, 0.0]);
+ }
+ Vec2D.clone(Vec2D copy) {
+ _buffer = Float32List.fromList(copy._buffer);
+ }
+ Vec2D.fromValues(double x, double y) {
+ _buffer = Float32List.fromList([x, y]);
+ }
+ static void copy(Vec2D o, Vec2D a) {
+ o[0] = a[0];
+ o[1] = a[1];
+ }
+
+ static void copyFromList(Vec2D o, Float32List a) {
+ o[0] = a[0];
+ o[1] = a[1];
+ }
+
+ static Vec2D transformMat2D(Vec2D o, Vec2D a, Mat2D m) {
+ double x = a[0];
+ double y = a[1];
+ o[0] = m[0] * x + m[2] * y + m[4];
+ o[1] = m[1] * x + m[3] * y + m[5];
+ return o;
+ }
+
+ static Vec2D transformMat2(Vec2D o, Vec2D a, Mat2D m) {
+ double x = a[0];
+ double y = a[1];
+ o[0] = m[0] * x + m[2] * y;
+ o[1] = m[1] * x + m[3] * y;
+ return o;
+ }
+
+ static Vec2D subtract(Vec2D o, Vec2D a, Vec2D b) {
+ o[0] = a[0] - b[0];
+ o[1] = a[1] - b[1];
+ return o;
+ }
+
+ static Vec2D add(Vec2D o, Vec2D a, Vec2D b) {
+ o[0] = a[0] + b[0];
+ o[1] = a[1] + b[1];
+ return o;
+ }
+
+ static Vec2D scale(Vec2D o, Vec2D a, double scale) {
+ o[0] = a[0] * scale;
+ o[1] = a[1] * scale;
+ return o;
+ }
+
+ static Vec2D lerp(Vec2D o, Vec2D a, Vec2D b, double f) {
+ double ax = a[0];
+ double ay = a[1];
+ o[0] = ax + f * (b[0] - ax);
+ o[1] = ay + f * (b[1] - ay);
+ return o;
+ }
+
+ static double length(Vec2D a) {
+ double x = a[0];
+ double y = a[1];
+ return sqrt(x * x + y * y);
+ }
+
+ static double squaredLength(Vec2D a) {
+ double x = a[0];
+ double y = a[1];
+ return x * x + y * y;
+ }
+
+ static double distance(Vec2D a, Vec2D b) {
+ double x = b[0] - a[0];
+ double y = b[1] - a[1];
+ return sqrt(x * x + y * y);
+ }
+
+ static double squaredDistance(Vec2D a, Vec2D b) {
+ double x = b[0] - a[0];
+ double y = b[1] - a[1];
+ return x * x + y * y;
+ }
+
+ static Vec2D negate(Vec2D result, Vec2D a) {
+ result[0] = -1 * a[0];
+ result[1] = -1 * a[1];
+ return result;
+ }
+
+ static void normalize(Vec2D result, Vec2D a) {
+ double x = a[0];
+ double y = a[1];
+ double len = x * x + y * y;
+ if (len > 0.0) {
+ len = 1.0 / sqrt(len);
+ result[0] = a[0] * len;
+ result[1] = a[1] * len;
+ }
+ }
+
+ static double dot(Vec2D a, Vec2D b) {
+ return a[0] * b[0] + a[1] * b[1];
+ }
+
+ static Vec2D scaleAndAdd(Vec2D result, Vec2D a, Vec2D b, double scale) {
+ result[0] = a[0] + b[0] * scale;
+ result[1] = a[1] + b[1] * scale;
+ return result;
+ }
+
+ static double onSegment(Vec2D segmentPoint1, Vec2D segmentPoint2, Vec2D pt) {
+ double l2 = squaredDistance(segmentPoint1, segmentPoint2);
+ if (l2 == 0) {
+ return 0;
+ }
+ return ((pt[0] - segmentPoint1[0]) * (segmentPoint2[0] - segmentPoint1[0]) +
+ (pt[1] - segmentPoint1[1]) *
+ (segmentPoint2[1] - segmentPoint1[1])) /
+ l2;
+ }
+
+ static double segmentSquaredDistance(
+ Vec2D segmentPoint1, Vec2D segmentPoint2, Vec2D pt) {
+ double t = onSegment(segmentPoint1, segmentPoint2, pt);
+ if (t <= 0) {
+ return Vec2D.squaredDistance(segmentPoint1, pt);
+ }
+ if (t >= 1) {
+ return Vec2D.squaredDistance(segmentPoint2, pt);
+ }
+ Vec2D ptOnSeg = Vec2D.fromValues(
+ segmentPoint1[0] + t * (segmentPoint2[0] - segmentPoint1[0]),
+ segmentPoint1[1] + t * (segmentPoint2[1] - segmentPoint1[1]));
+ return Vec2D.squaredDistance(ptOnSeg, pt);
+ }
+
+ static bool approximatelyEqual(Vec2D a, Vec2D b, {double threshold = 0.001}) {
+ var a0 = a[0], a1 = a[1];
+ var b0 = b[0], b1 = b[1];
+ return (a0 - b0).abs() <= threshold * max(1.0, max(a0.abs(), b0.abs())) &&
+ (a1 - b1).abs() <= threshold * max(1.0, max(a1.abs(), b1.abs()));
+ }
+
+ @override
+ String toString() {
+ String v = _buffer[0].toString() + ", ";
+ return v + _buffer[1].toString();
+ }
+}
diff --git a/lib/src/rive_core/node.dart b/lib/src/rive_core/node.dart
new file mode 100644
index 0000000..afd195e
--- /dev/null
+++ b/lib/src/rive_core/node.dart
@@ -0,0 +1,142 @@
+import 'package:flutter/foundation.dart';
+import 'package:rive/src/rive_core/bounds_delegate.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/generated/node_base.dart';
+import 'package:meta/meta.dart';
+export 'package:rive/src/generated/node_base.dart';
+
+class Node extends NodeBase {
+ final Mat2D transform = Mat2D();
+ final Mat2D worldTransform = Mat2D();
+ BoundsDelegate _delegate;
+ double _renderOpacity = 0;
+ double get renderOpacity => _renderOpacity;
+ @override
+ void update(int dirt) {
+ if (dirt & ComponentDirt.transform != 0) {
+ updateTransform();
+ }
+ if (dirt & ComponentDirt.worldTransform != 0) {
+ updateWorldTransform();
+ }
+ }
+
+ Vec2D get translation => Vec2D.fromValues(x, y);
+ Vec2D get worldTranslation =>
+ Vec2D.fromValues(worldTransform[4], worldTransform[5]);
+ set translation(Vec2D pos) {
+ x = pos[0];
+ y = pos[1];
+ }
+
+ Vec2D get scale => Vec2D.fromValues(scaleX, scaleY);
+ set scale(Vec2D value) {
+ scaleX = value[0];
+ scaleY = value[1];
+ }
+
+ void updateTransform() {
+ if (rotation != 0) {
+ Mat2D.fromRotation(transform, rotation);
+ } else {
+ Mat2D.identity(transform);
+ }
+ transform[4] = x;
+ transform[5] = y;
+ Mat2D.scaleByValues(transform, scaleX, scaleY);
+ }
+
+ double get childOpacity => _renderOpacity;
+ @mustCallSuper
+ void updateWorldTransform() {
+ _renderOpacity = opacity;
+ if (parent is Node) {
+ var parentNode = parent as Node;
+ _renderOpacity *= parentNode.childOpacity;
+ Mat2D.multiply(worldTransform, parentNode.worldTransform, transform);
+ } else {
+ Mat2D.copy(worldTransform, transform);
+ }
+ _delegate?.boundsChanged();
+ }
+
+ @override
+ void userDataChanged(dynamic from, dynamic to) {
+ if (to is BoundsDelegate) {
+ _delegate = to;
+ } else {
+ _delegate = null;
+ }
+ }
+
+ void calculateWorldTransform() {
+ var parent = this.parent;
+ final chain = [this];
+ while (parent != null) {
+ if (parent is Node) {
+ chain.insert(0, parent);
+ }
+ parent = parent.parent;
+ }
+ for (final item in chain) {
+ item.updateTransform();
+ item.updateWorldTransform();
+ }
+ }
+
+ @override
+ void buildDependencies() {
+ super.buildDependencies();
+ parent?.addDependent(this);
+ }
+
+ void markTransformDirty() {
+ if (!addDirt(ComponentDirt.transform)) {
+ return;
+ }
+ markWorldTransformDirty();
+ }
+
+ void markWorldTransformDirty() {
+ addDirt(ComponentDirt.worldTransform, recurse: true);
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void rotationChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void scaleXChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void scaleYChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void opacityChanged(double from, double to) {
+ markTransformDirty();
+ }
+
+ @override
+ void parentChanged(ContainerComponent from, ContainerComponent to) {
+ super.parentChanged(from, to);
+ markWorldTransformDirty();
+ }
+}
diff --git a/lib/src/rive_core/rive_animation_controller.dart b/lib/src/rive_core/rive_animation_controller.dart
new file mode 100644
index 0000000..991a8fc
--- /dev/null
+++ b/lib/src/rive_core/rive_animation_controller.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+
+abstract class RiveAnimationController {
+ final _isActive = ValueNotifier(false);
+ ValueListenable get isActiveChanged => _isActive;
+ bool get isActive => _isActive.value;
+ set isActive(bool value) {
+ if (_isActive.value != value) {
+ _isActive.value = value;
+ if (value) {
+ onActivate();
+ } else {
+ onDeactivate();
+ }
+ }
+ }
+
+ @protected
+ void onActivate();
+ @protected
+ void onDeactivate();
+ void apply(T core, double elapsedSeconds);
+ bool init(T core) => true;
+ void dispose();
+}
diff --git a/lib/src/rive_core/runtime/exceptions/rive_format_error_exception.dart b/lib/src/rive_core/runtime/exceptions/rive_format_error_exception.dart
new file mode 100644
index 0000000..efda20a
--- /dev/null
+++ b/lib/src/rive_core/runtime/exceptions/rive_format_error_exception.dart
@@ -0,0 +1,7 @@
+import 'package:meta/meta.dart';
+
+@immutable
+class RiveFormatErrorException implements Exception {
+ final String cause;
+ const RiveFormatErrorException(this.cause);
+}
diff --git a/lib/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart b/lib/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart
new file mode 100644
index 0000000..9ebde2b
--- /dev/null
+++ b/lib/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart
@@ -0,0 +1,16 @@
+import 'package:meta/meta.dart';
+
+@immutable
+class RiveUnsupportedVersionException implements Exception {
+ final int majorVersion;
+ final int minorVersion;
+ final int fileMajorVersion;
+ final int fileMinorVersion;
+ const RiveUnsupportedVersionException(this.majorVersion, this.minorVersion,
+ this.fileMajorVersion, this.fileMinorVersion);
+ @override
+ String toString() {
+ return 'File contains version $fileMajorVersion.$fileMinorVersion. '
+ 'This runtime can only support $fileMajorVersion.$fileMinorVersion';
+ }
+}
diff --git a/lib/src/rive_core/runtime/runtime_header.dart b/lib/src/rive_core/runtime/runtime_header.dart
new file mode 100644
index 0000000..231920f
--- /dev/null
+++ b/lib/src/rive_core/runtime/runtime_header.dart
@@ -0,0 +1,30 @@
+import 'package:meta/meta.dart';
+import 'package:rive/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+import 'exceptions/rive_format_error_exception.dart';
+
+class RuntimeHeader {
+ static const int majorVersion = 1;
+ static const int minorVersion = 0;
+ static const String fingerprint = 'RIVE';
+ final int ownerId;
+ final int fileId;
+ RuntimeHeader({@required this.ownerId, @required this.fileId});
+ factory RuntimeHeader.read(BinaryReader reader) {
+ var fingerprint = RuntimeHeader.fingerprint.codeUnits;
+ for (int i = 0; i < fingerprint.length; i++) {
+ if (reader.readUint8() != fingerprint[i]) {
+ throw const RiveFormatErrorException('Fingerprint doesn\'t match.');
+ }
+ }
+ int readMajorVersion = reader.readVarUint();
+ int readMinorVersion = reader.readVarUint();
+ if (readMajorVersion > majorVersion) {
+ throw RiveUnsupportedVersionException(
+ majorVersion, minorVersion, readMajorVersion, readMinorVersion);
+ }
+ int ownerId = reader.readVarUint();
+ int fileId = reader.readVarUint();
+ return RuntimeHeader(ownerId: ownerId, fileId: fileId);
+ }
+}
diff --git a/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart
new file mode 100644
index 0000000..e377105
--- /dev/null
+++ b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart
@@ -0,0 +1,66 @@
+import 'dart:math';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart';
+export 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart';
+
+class CubicAsymmetricVertex extends CubicAsymmetricVertexBase {
+ Vec2D _inPoint;
+ Vec2D _outPoint;
+ @override
+ Vec2D get outPoint {
+ return _outPoint ??= Vec2D.add(
+ Vec2D(),
+ translation,
+ Vec2D.fromValues(
+ cos(rotation) * outDistance, sin(rotation) * outDistance));
+ }
+
+ @override
+ Vec2D get inPoint {
+ return _inPoint ??= Vec2D.add(
+ Vec2D(),
+ translation,
+ Vec2D.fromValues(
+ cos(rotation) * -inDistance, sin(rotation) * -inDistance));
+ }
+
+ @override
+ String toString() {
+ return 'in ${inPoint[0]}, ${inPoint[1]} | ${translation.toString()} '
+ '| out ${outPoint[0]}, ${outPoint[1]}';
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void inDistanceChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = _outPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void outDistanceChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = _outPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void rotationChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = _outPoint = null;
+ path?.markPathDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/cubic_detached_vertex.dart b/lib/src/rive_core/shapes/cubic_detached_vertex.dart
new file mode 100644
index 0000000..63e4189
--- /dev/null
+++ b/lib/src/rive_core/shapes/cubic_detached_vertex.dart
@@ -0,0 +1,92 @@
+import 'dart:math';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart';
+export 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart';
+
+class CubicDetachedVertex extends CubicDetachedVertexBase {
+ Vec2D _inPoint;
+ Vec2D _outPoint;
+ CubicDetachedVertex();
+ CubicDetachedVertex.fromValues(
+ {double x,
+ double y,
+ double inX,
+ double inY,
+ double outX,
+ double outY,
+ Vec2D inPoint,
+ Vec2D outPoint}) {
+ this.x = x;
+ this.y = y;
+ this.inPoint = Vec2D.fromValues(inX ?? inPoint[0], inY ?? inPoint[1]);
+ this.outPoint = Vec2D.fromValues(outX ?? outPoint[0], outY ?? outPoint[1]);
+ }
+ @override
+ Vec2D get outPoint => _outPoint ??= Vec2D.add(
+ Vec2D(),
+ translation,
+ Vec2D.fromValues(
+ cos(outRotation) * outDistance, sin(outRotation) * outDistance));
+ @override
+ set outPoint(Vec2D value) {
+ _outPoint = Vec2D.clone(value);
+ }
+
+ @override
+ Vec2D get inPoint => _inPoint ??= Vec2D.add(
+ Vec2D(),
+ translation,
+ Vec2D.fromValues(
+ cos(inRotation) * inDistance, sin(inRotation) * inDistance));
+ @override
+ set inPoint(Vec2D value) {
+ _inPoint = Vec2D.clone(value);
+ }
+
+ @override
+ String toString() {
+ return 'in ${inPoint[0]}, ${inPoint[1]} | ${translation.toString()} '
+ '| out ${outPoint[0]}, ${outPoint[1]}';
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void inDistanceChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void inRotationChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void outDistanceChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _outPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void outRotationChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _outPoint = null;
+ path?.markPathDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart
new file mode 100644
index 0000000..1899835
--- /dev/null
+++ b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart
@@ -0,0 +1,53 @@
+import 'dart:math';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart';
+export 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart';
+
+class CubicMirroredVertex extends CubicMirroredVertexBase {
+ Vec2D _inPoint;
+ Vec2D _outPoint;
+ @override
+ Vec2D get outPoint {
+ return _outPoint ??= Vec2D.add(Vec2D(), translation,
+ Vec2D.fromValues(cos(rotation) * distance, sin(rotation) * distance));
+ }
+
+ @override
+ Vec2D get inPoint {
+ return _inPoint ??= Vec2D.add(Vec2D(), translation,
+ Vec2D.fromValues(cos(rotation) * -distance, sin(rotation) * -distance));
+ }
+
+ @override
+ String toString() {
+ return 'in ${inPoint[0]}, ${inPoint[1]} | ${translation.toString()} '
+ '| out ${outPoint[0]}, ${outPoint[1]}';
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ super.xChanged(from, to);
+ _outPoint = _inPoint = null;
+ }
+
+ @override
+ void distanceChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = _outPoint = null;
+ path?.markPathDirty();
+ }
+
+ @override
+ void rotationChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ _inPoint = _outPoint = null;
+ path?.markPathDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/cubic_vertex.dart b/lib/src/rive_core/shapes/cubic_vertex.dart
new file mode 100644
index 0000000..2ea5b38
--- /dev/null
+++ b/lib/src/rive_core/shapes/cubic_vertex.dart
@@ -0,0 +1,7 @@
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/generated/shapes/cubic_vertex_base.dart';
+
+abstract class CubicVertex extends CubicVertexBase {
+ Vec2D get outPoint;
+ Vec2D get inPoint;
+}
diff --git a/lib/src/rive_core/shapes/ellipse.dart b/lib/src/rive_core/shapes/ellipse.dart
new file mode 100644
index 0000000..9b4f935
--- /dev/null
+++ b/lib/src/rive_core/shapes/ellipse.dart
@@ -0,0 +1,42 @@
+import 'package:rive/src/rive_core/shapes/cubic_detached_vertex.dart';
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+import 'package:rive/src/generated/shapes/ellipse_base.dart';
+export 'package:rive/src/generated/shapes/ellipse_base.dart';
+
+const double circleConstant = 0.55;
+
+class Ellipse extends EllipseBase {
+ @override
+ List get vertices => [
+ CubicDetachedVertex.fromValues(
+ x: 0,
+ y: -radiusY,
+ inX: -radiusX * circleConstant,
+ inY: -radiusY,
+ outX: radiusX * circleConstant,
+ outY: -radiusY),
+ CubicDetachedVertex.fromValues(
+ x: radiusX,
+ y: 0,
+ inX: radiusX,
+ inY: circleConstant * -radiusY,
+ outX: radiusX,
+ outY: circleConstant * radiusY),
+ CubicDetachedVertex.fromValues(
+ x: 0,
+ y: radiusY,
+ inX: radiusX * circleConstant,
+ inY: radiusY,
+ outX: -radiusX * circleConstant,
+ outY: radiusY),
+ CubicDetachedVertex.fromValues(
+ x: -radiusX,
+ y: 0,
+ inX: -radiusX,
+ inY: radiusY * circleConstant,
+ outX: -radiusX,
+ outY: -radiusY * circleConstant)
+ ];
+ double get radiusX => width / 2;
+ double get radiusY => height / 2;
+}
diff --git a/lib/src/rive_core/shapes/paint/fill.dart b/lib/src/rive_core/shapes/paint/fill.dart
new file mode 100644
index 0000000..347210d
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/fill.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/generated/shapes/paint/fill_base.dart';
+export 'package:rive/src/generated/shapes/paint/fill_base.dart';
+
+class Fill extends FillBase {
+ @override
+ Paint makePaint() => Paint()..style = PaintingStyle.fill;
+ PathFillType get fillType => PathFillType.values[fillRule];
+ set fillType(PathFillType type) => fillRule = type.index;
+ @override
+ void fillRuleChanged(int from, int to) {
+ parent?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void update(int dirt) {}
+ @override
+ void draw(Canvas canvas, Path path) {
+ if (!isVisible) {
+ return;
+ }
+ path.fillType = fillType;
+ canvas.drawPath(path, paint);
+ }
+}
diff --git a/lib/src/rive_core/shapes/paint/gradient_stop.dart b/lib/src/rive_core/shapes/paint/gradient_stop.dart
new file mode 100644
index 0000000..324d203
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/gradient_stop.dart
@@ -0,0 +1,43 @@
+import 'dart:ui' as ui;
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+import 'package:rive/src/generated/shapes/paint/gradient_stop_base.dart';
+import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart';
+export 'package:rive/src/generated/shapes/paint/gradient_stop_base.dart';
+
+class GradientStop extends GradientStopBase {
+ @override
+ Component get timelineParent =>
+ _gradient is LinearGradient ? _gradient.parent : null;
+ @override
+ String get timelineName =>
+ 'Stop ${_gradient.gradientStops.indexOf(this) + 1}';
+ LinearGradient _gradient;
+ LinearGradient get gradient => _gradient;
+ ui.Color get color => ui.Color(colorValue);
+ set color(ui.Color c) {
+ colorValue = c.value;
+ }
+
+ @override
+ void positionChanged(double from, double to) {
+ _gradient?.markStopsDirty();
+ }
+
+ @override
+ void colorValueChanged(int from, int to) {
+ _gradient?.markGradientDirty();
+ }
+
+ @override
+ void update(int dirt) {}
+ @override
+ void parentChanged(ContainerComponent from, ContainerComponent to) {
+ super.parentChanged(from, to);
+ if (parent is LinearGradient) {
+ _gradient = parent as LinearGradient;
+ } else {
+ _gradient = null;
+ }
+ }
+}
diff --git a/lib/src/rive_core/shapes/paint/linear_gradient.dart b/lib/src/rive_core/shapes/paint/linear_gradient.dart
new file mode 100644
index 0000000..c78ea02
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/linear_gradient.dart
@@ -0,0 +1,121 @@
+import 'dart:ui' as ui;
+import 'package:meta/meta.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/shapes/paint/gradient_stop.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';
+export 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart';
+
+class LinearGradient extends LinearGradientBase with ShapePaintMutator {
+ final List gradientStops = [];
+ @override
+ Component get timelineProxy => parent;
+ bool _paintsInWorldSpace = true;
+ bool get paintsInWorldSpace => _paintsInWorldSpace;
+ set paintsInWorldSpace(bool value) {
+ if (_paintsInWorldSpace == value) {
+ return;
+ }
+ _paintsInWorldSpace = value;
+ addDirt(ComponentDirt.paint);
+ }
+
+ Vec2D get start => Vec2D.fromValues(startX, startY);
+ Vec2D get end => Vec2D.fromValues(endX, endY);
+ ui.Offset get startOffset => ui.Offset(startX, startY);
+ ui.Offset get endOffset => ui.Offset(endX, endY);
+ @override
+ void buildDependencies() {
+ super.buildDependencies();
+ shapePaintContainer?.addDependent(this);
+ }
+
+ @override
+ void childAdded(Component child) {
+ super.childAdded(child);
+ if (child is GradientStop && !gradientStops.contains(child)) {
+ gradientStops.add(child);
+ markStopsDirty();
+ }
+ }
+
+ @override
+ void childRemoved(Component child) {
+ super.childRemoved(child);
+ if (child is GradientStop && gradientStops.contains(child)) {
+ gradientStops.remove(child);
+ markStopsDirty();
+ }
+ }
+
+ void markStopsDirty() => addDirt(ComponentDirt.stops | ComponentDirt.paint);
+ void markGradientDirty() => addDirt(ComponentDirt.paint);
+ @override
+ void update(int dirt) {
+ bool stopsChanged = dirt & ComponentDirt.stops != 0;
+ if (stopsChanged) {
+ gradientStops.sort((a, b) => a.position.compareTo(b.position));
+ }
+ bool worldTransformed = dirt & ComponentDirt.worldTransform != 0;
+ bool localTransformed = dirt & ComponentDirt.transform != 0;
+ var rebuildGradient = dirt & ComponentDirt.paint != 0 ||
+ localTransformed ||
+ (paintsInWorldSpace && worldTransformed);
+ if (rebuildGradient) {
+ var colors = [];
+ var colorPositions = [];
+ for (final stop in gradientStops) {
+ colors.add(stop.color);
+ colorPositions.add(stop.position);
+ }
+ if (paintsInWorldSpace) {
+ var world = shapePaintContainer.worldTransform;
+ var worldStart = Vec2D.transformMat2D(Vec2D(), start, world);
+ var worldEnd = Vec2D.transformMat2D(Vec2D(), end, world);
+ paint.shader = makeGradient(ui.Offset(worldStart[0], worldStart[1]),
+ ui.Offset(worldEnd[0], worldEnd[1]), colors, colorPositions);
+ } else {
+ paint.shader =
+ makeGradient(startOffset, endOffset, colors, colorPositions);
+ }
+ }
+ }
+
+ @protected
+ ui.Gradient makeGradient(ui.Offset start, ui.Offset end,
+ List colors, List colorPositions) =>
+ ui.Gradient.linear(start, end, colors, colorPositions);
+ @override
+ void startXChanged(double from, double to) {
+ addDirt(ComponentDirt.transform);
+ }
+
+ @override
+ void startYChanged(double from, double to) {
+ addDirt(ComponentDirt.transform);
+ }
+
+ @override
+ void endXChanged(double from, double to) {
+ addDirt(ComponentDirt.transform);
+ }
+
+ @override
+ void endYChanged(double from, double to) {
+ addDirt(ComponentDirt.transform);
+ }
+
+ @override
+ void opacityChanged(double from, double to) {
+ syncColor();
+ shapePaintContainer?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void syncColor() {
+ paint?.color = const ui.Color(0xFFFFFFFF)
+ .withOpacity((opacity * renderOpacity).clamp(0, 1).toDouble());
+ }
+}
diff --git a/lib/src/rive_core/shapes/paint/radial_gradient.dart b/lib/src/rive_core/shapes/paint/radial_gradient.dart
new file mode 100644
index 0000000..d405a3a
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/radial_gradient.dart
@@ -0,0 +1,10 @@
+import 'dart:ui' as ui;
+import 'package:rive/src/generated/shapes/paint/radial_gradient_base.dart';
+export 'package:rive/src/generated/shapes/paint/radial_gradient_base.dart';
+
+class RadialGradient extends RadialGradientBase {
+ @override
+ ui.Gradient makeGradient(ui.Offset start, ui.Offset end,
+ List colors, List colorPositions) =>
+ ui.Gradient.radial(start, (end - start).distance, colors, colorPositions);
+}
diff --git a/lib/src/rive_core/shapes/paint/shape_paint.dart b/lib/src/rive_core/shapes/paint/shape_paint.dart
new file mode 100644
index 0000000..402914d
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/shape_paint.dart
@@ -0,0 +1,75 @@
+import 'dart:ui';
+import 'package:meta/meta.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/container_component.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
+import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
+export 'package:rive/src/generated/shapes/paint/shape_paint_base.dart';
+
+abstract class ShapePaint extends ShapePaintBase {
+ Paint _paint;
+ Paint get paint => _paint;
+ ShapePaintMutator _paintMutator;
+ ShapePaintContainer _shapePaintContainer;
+ ShapePaintContainer get shapePaintContainer => _shapePaintContainer;
+ ShapePaint() {
+ _paint = makePaint();
+ }
+ BlendMode get blendMode => _paint.blendMode;
+ set blendMode(BlendMode value) => _paint.blendMode = value;
+ double get renderOpacity => _paintMutator.renderOpacity;
+ set renderOpacity(double value) => _paintMutator.renderOpacity = value;
+ @override
+ Component get timelineParent => _shapePaintContainer as Component;
+ ShapePaintMutator get paintMutator => _paintMutator;
+ void _changeMutator(ShapePaintMutator mutator) {
+ _paint = makePaint();
+ _paintMutator = mutator;
+ }
+
+ @protected
+ Paint makePaint();
+ @override
+ void childAdded(Component child) {
+ super.childAdded(child);
+ if (child is ShapePaintMutator) {
+ _changeMutator(child as ShapePaintMutator);
+ _initMutator();
+ }
+ }
+
+ @override
+ void isVisibleChanged(bool from, bool to) {
+ _shapePaintContainer?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void childRemoved(Component child) {
+ super.childRemoved(child);
+ if (child is ShapePaintMutator &&
+ _paintMutator == child as ShapePaintMutator) {
+ _changeMutator(null);
+ }
+ }
+
+ @override
+ void parentChanged(ContainerComponent from, ContainerComponent to) {
+ super.parentChanged(from, to);
+ if (parent is ShapePaintContainer) {
+ _shapePaintContainer = parent as ShapePaintContainer;
+ _initMutator();
+ } else {
+ _shapePaintContainer = null;
+ }
+ }
+
+ void _initMutator() {
+ if (_shapePaintContainer != null && _paintMutator != null) {
+ _paintMutator.initializePaintMutator(_shapePaintContainer, paint);
+ }
+ }
+
+ void draw(Canvas canvas, Path path);
+}
diff --git a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart
new file mode 100644
index 0000000..409e7fa
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart
@@ -0,0 +1,28 @@
+import 'dart:ui';
+import 'package:flutter/material.dart';
+import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
+
+abstract class ShapePaintMutator {
+ ShapePaintContainer _shapePaintContainer;
+ Paint _paint;
+ ShapePaintContainer get shapePaintContainer => _shapePaintContainer;
+ Paint get paint => _paint;
+ double _renderOpacity = 1;
+ double get renderOpacity => _renderOpacity;
+ set renderOpacity(double value) {
+ if (_renderOpacity != value) {
+ _renderOpacity = value;
+ syncColor();
+ }
+ }
+
+ @protected
+ void syncColor();
+ @mustCallSuper
+ void initializePaintMutator(ShapePaintContainer container, Paint paint) {
+ _shapePaintContainer = container;
+ _paint = paint;
+ _shapePaintContainer?.onPaintMutatorChanged(this);
+ syncColor();
+ }
+}
diff --git a/lib/src/rive_core/shapes/paint/solid_color.dart b/lib/src/rive_core/shapes/paint/solid_color.dart
new file mode 100644
index 0000000..0cde995
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/solid_color.dart
@@ -0,0 +1,36 @@
+import 'dart:ui';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
+import 'package:rive/src/generated/shapes/paint/solid_color_base.dart';
+export 'package:rive/src/generated/shapes/paint/solid_color_base.dart';
+
+class SolidColor extends SolidColorBase with ShapePaintMutator {
+ @override
+ Component get timelineProxy => parent;
+ Color get color => Color(colorValue);
+ set color(Color c) {
+ colorValue = c.value;
+ }
+
+ @override
+ void colorValueChanged(int from, int to) {
+ syncColor();
+ shapePaintContainer?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void update(int dirt) {}
+ @override
+ void initializePaintMutator(ShapePaintContainer paintContainer, Paint paint) {
+ super.initializePaintMutator(paintContainer, paint);
+ syncColor();
+ }
+
+ @override
+ void syncColor() {
+ paint?.color = color
+ .withOpacity((color.opacity * renderOpacity).clamp(0, 1).toDouble());
+ }
+}
diff --git a/lib/src/rive_core/shapes/paint/stroke.dart b/lib/src/rive_core/shapes/paint/stroke.dart
new file mode 100644
index 0000000..4f97189
--- /dev/null
+++ b/lib/src/rive_core/shapes/paint/stroke.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/shapes/shape.dart';
+import 'package:rive/src/generated/shapes/paint/stroke_base.dart';
+export 'package:rive/src/generated/shapes/paint/stroke_base.dart';
+
+class Stroke extends StrokeBase {
+ @override
+ Paint makePaint() => Paint()
+ ..style = PaintingStyle.stroke
+ ..strokeCap = strokeCap
+ ..strokeJoin = strokeJoin
+ ..strokeWidth = thickness;
+ @override
+ String get timelineParentGroup => 'strokes';
+ StrokeCap get strokeCap => StrokeCap.values[cap];
+ set strokeCap(StrokeCap value) => cap = value.index;
+ StrokeJoin get strokeJoin => StrokeJoin.values[join];
+ set strokeJoin(StrokeJoin value) => join = value.index;
+ @override
+ void capChanged(int from, int to) {
+ paint.strokeCap = StrokeCap.values[to];
+ parent?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void joinChanged(int from, int to) {
+ paint.strokeJoin = StrokeJoin.values[to];
+ parent?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void thicknessChanged(double from, double to) {
+ paint.strokeWidth = to;
+ parent?.addDirt(ComponentDirt.paint);
+ }
+
+ @override
+ void transformAffectsStrokeChanged(bool from, bool to) {
+ var parentShape = parent;
+ if (parentShape is Shape) {
+ parentShape.transformAffectsStrokeChanged();
+ }
+ }
+
+ @override
+ void update(int dirt) {}
+ @override
+ void draw(Canvas canvas, Path path) {
+ if (!isVisible) {
+ return;
+ }
+ canvas.drawPath(path, paint);
+ }
+}
diff --git a/lib/src/rive_core/shapes/parametric_path.dart b/lib/src/rive_core/shapes/parametric_path.dart
new file mode 100644
index 0000000..b0d8355
--- /dev/null
+++ b/lib/src/rive_core/shapes/parametric_path.dart
@@ -0,0 +1,45 @@
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/generated/shapes/parametric_path_base.dart';
+export 'package:rive/src/generated/shapes/parametric_path_base.dart';
+
+abstract class ParametricPath extends ParametricPathBase {
+ @override
+ bool get isClosed => true;
+ @override
+ Mat2D get pathTransform => worldTransform;
+ @override
+ Mat2D get inversePathTransform => inverseWorldTransform;
+ @override
+ void widthChanged(double from, double to) => markPathDirty();
+ @override
+ void heightChanged(double from, double to) => markPathDirty();
+ @override
+ void xChanged(double from, double to) {
+ super.xChanged(from, to);
+ shape?.pathChanged(this);
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ super.yChanged(from, to);
+ shape?.pathChanged(this);
+ }
+
+ @override
+ void rotationChanged(double from, double to) {
+ super.rotationChanged(from, to);
+ shape?.pathChanged(this);
+ }
+
+ @override
+ void scaleXChanged(double from, double to) {
+ super.scaleXChanged(from, to);
+ shape?.pathChanged(this);
+ }
+
+ @override
+ void scaleYChanged(double from, double to) {
+ super.scaleYChanged(from, to);
+ shape?.pathChanged(this);
+ }
+}
diff --git a/lib/src/rive_core/shapes/path.dart b/lib/src/rive_core/shapes/path.dart
new file mode 100644
index 0000000..1ba1d3f
--- /dev/null
+++ b/lib/src/rive_core/shapes/path.dart
@@ -0,0 +1,377 @@
+import 'dart:math';
+import 'dart:ui' as ui;
+import 'package:rive/src/rive_core/bounds_delegate.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+import 'package:rive/src/rive_core/shapes/render_cubic_vertex.dart';
+import 'package:rive/src/rive_core/shapes/shape.dart';
+import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
+import 'package:rive/src/generated/shapes/path_base.dart';
+export 'package:rive/src/generated/shapes/path_base.dart';
+
+abstract class Path extends PathBase {
+ final Mat2D _inverseWorldTransform = Mat2D();
+ final ui.Path _uiPath = ui.Path();
+ ui.Path get uiPath {
+ if (!_isValid) {
+ _buildPath();
+ }
+ return _uiPath;
+ }
+
+ bool _isValid = false;
+ bool get isClosed;
+ Shape _shape;
+ Shape get shape => _shape;
+ Mat2D get pathTransform;
+ Mat2D get inversePathTransform;
+ Mat2D get inverseWorldTransform => _inverseWorldTransform;
+ @override
+ Component get timelineParent => _shape;
+ @override
+ bool resolveArtboard() {
+ _changeShape(null);
+ return super.resolveArtboard();
+ }
+
+ BoundsDelegate _delegate;
+ void markBoundsDirty() {
+ _delegate?.boundsChanged();
+ }
+
+ @override
+ void userDataChanged(dynamic from, dynamic to) {
+ if (to is BoundsDelegate) {
+ _delegate = to;
+ } else {
+ _delegate = null;
+ }
+ }
+
+ @override
+ void visitAncestor(Component ancestor) {
+ if (_shape == null && ancestor is Shape) {
+ _changeShape(ancestor);
+ }
+ }
+
+ void _changeShape(Shape value) {
+ if (_shape == value) {
+ return;
+ }
+ _shape?.removePath(this);
+ value?.addPath(this);
+ _shape = value;
+ }
+
+ @override
+ void onRemoved() {
+ _changeShape(null);
+ super.onRemoved();
+ }
+
+ @override
+ void updateWorldTransform() {
+ super.updateWorldTransform();
+ _shape?.pathChanged(this);
+ if (!Mat2D.invert(_inverseWorldTransform, worldTransform)) {
+ Mat2D.identity(_inverseWorldTransform);
+ }
+ }
+
+ @override
+ void update(int dirt) {
+ super.update(dirt);
+ if (dirt & ComponentDirt.path != 0) {
+ _buildPath();
+ }
+ }
+
+ void markPathDirty() {
+ addDirt(ComponentDirt.path);
+ _shape?.pathChanged(this);
+ }
+
+ void _invalidatePath() {
+ _isValid = false;
+ _cachedRenderVertices = null;
+ }
+
+ @override
+ bool addDirt(int value, {bool recurse = false}) {
+ _invalidatePath();
+ return super.addDirt(value, recurse: recurse);
+ }
+
+ List get vertices;
+ List _cachedRenderVertices;
+ List get renderVertices {
+ if (_cachedRenderVertices != null) {
+ return _cachedRenderVertices;
+ }
+ return _cachedRenderVertices = makeRenderVertices(vertices, isClosed);
+ }
+
+ static List makeRenderVertices(
+ List pts, bool isClosed) {
+ if (pts == null || pts.isEmpty) {
+ return [];
+ }
+ List renderPoints = [];
+ int pl = pts.length;
+ const double arcConstant = 0.55;
+ const double iarcConstant = 1.0 - arcConstant;
+ PathVertex previous = isClosed ? pts[pl - 1] : null;
+ for (int i = 0; i < pl; i++) {
+ PathVertex point = pts[i];
+ switch (point.coreType) {
+ case StraightVertexBase.typeKey:
+ {
+ StraightVertex straightPoint = point as StraightVertex;
+ double radius = straightPoint.radius;
+ if (radius != null && radius > 0) {
+ if (!isClosed && (i == 0 || i == pl - 1)) {
+ renderPoints.add(point);
+ previous = point;
+ } else {
+ PathVertex next = pts[(i + 1) % pl];
+ Vec2D prevPoint = previous is CubicVertex
+ ? previous.outPoint
+ : previous.translation;
+ Vec2D nextPoint =
+ next is CubicVertex ? next.inPoint : next.translation;
+ Vec2D pos = point.translation;
+ Vec2D toPrev = Vec2D.subtract(Vec2D(), prevPoint, pos);
+ double toPrevLength = Vec2D.length(toPrev);
+ toPrev[0] /= toPrevLength;
+ toPrev[1] /= toPrevLength;
+ Vec2D toNext = Vec2D.subtract(Vec2D(), nextPoint, pos);
+ double toNextLength = Vec2D.length(toNext);
+ toNext[0] /= toNextLength;
+ toNext[1] /= toNextLength;
+ double renderRadius =
+ min(toPrevLength, min(toNextLength, radius));
+ Vec2D translation =
+ Vec2D.scaleAndAdd(Vec2D(), pos, toPrev, renderRadius);
+ renderPoints.add(RenderCubicVertex()
+ ..translation = translation
+ ..inPoint = translation
+ ..outPoint = Vec2D.scaleAndAdd(
+ Vec2D(), pos, toPrev, iarcConstant * renderRadius));
+ translation =
+ Vec2D.scaleAndAdd(Vec2D(), pos, toNext, renderRadius);
+ previous = RenderCubicVertex()
+ ..translation = translation
+ ..inPoint = Vec2D.scaleAndAdd(
+ Vec2D(), pos, toNext, iarcConstant * renderRadius)
+ ..outPoint = translation;
+ renderPoints.add(previous);
+ }
+ } else {
+ renderPoints.add(point);
+ previous = point;
+ }
+ break;
+ }
+ default:
+ renderPoints.add(point);
+ previous = point;
+ break;
+ }
+ }
+ return renderPoints;
+ }
+
+ bool _buildPath() {
+ _isValid = true;
+ _uiPath.reset();
+ List pts = vertices;
+ if (pts == null || pts.isEmpty) {
+ return false;
+ }
+ var renderPoints = makeRenderVertices(pts, isClosed);
+ PathVertex firstPoint = renderPoints[0];
+ _uiPath.moveTo(firstPoint.translation[0], firstPoint.translation[1]);
+ for (int i = 0,
+ l = isClosed ? renderPoints.length : renderPoints.length - 1,
+ pl = renderPoints.length;
+ i < l;
+ i++) {
+ PathVertex point = renderPoints[i];
+ PathVertex nextPoint = renderPoints[(i + 1) % pl];
+ Vec2D cin = nextPoint is CubicVertex ? nextPoint.inPoint : null;
+ Vec2D cout = point is CubicVertex ? point.outPoint : null;
+ if (cin == null && cout == null) {
+ _uiPath.lineTo(nextPoint.translation[0], nextPoint.translation[1]);
+ } else {
+ cout ??= point.translation;
+ cin ??= nextPoint.translation;
+ _uiPath.cubicTo(cout[0], cout[1], cin[0], cin[1],
+ nextPoint.translation[0], nextPoint.translation[1]);
+ }
+ }
+ if (isClosed) {
+ _uiPath.close();
+ }
+ return true;
+ }
+
+ AABB preciseComputeBounds(List renderPoints, Mat2D transform) {
+ if (renderPoints.isEmpty) {
+ return AABB();
+ }
+ AABB bounds = AABB.empty();
+ PathVertex firstPoint = renderPoints[0];
+ Vec2D lastPoint = bounds.includePoint(firstPoint.translation, transform);
+ for (int i = 0,
+ l = isClosed ? renderPoints.length : renderPoints.length - 1,
+ pl = renderPoints.length;
+ i < l;
+ i++) {
+ PathVertex point = renderPoints[i];
+ PathVertex nextPoint = renderPoints[(i + 1) % pl];
+ Vec2D cin = nextPoint is CubicVertex ? nextPoint.inPoint : null;
+ Vec2D cout = point is CubicVertex ? point.outPoint : null;
+ if (cin == null && cout == null) {
+ lastPoint = bounds.includePoint(nextPoint.translation, transform);
+ } else {
+ cout ??= point.translation;
+ cin ??= nextPoint.translation;
+ var next = bounds.includePoint(nextPoint.translation, transform);
+ if (transform != null) {
+ cin = Vec2D.transformMat2D(Vec2D(), cin, transform);
+ cout = Vec2D.transformMat2D(Vec2D(), cout, transform);
+ }
+ const double epsilon = 0.000000001;
+ final double startX = lastPoint[0];
+ final double startY = lastPoint[1];
+ final double cpX1 = cout[0];
+ final double cpY1 = cout[1];
+ final double cpX2 = cin[0];
+ final double cpY2 = cin[1];
+ final double endX = next[0];
+ final double endY = next[1];
+ lastPoint = next;
+ double extremaX;
+ double extremaY;
+ double a, b, c;
+ if (!(((startX < cpX1) && (cpX1 < cpX2) && (cpX2 < endX)) ||
+ ((startX > cpX1) && (cpX1 > cpX2) && (cpX2 > endX)))) {
+ a = -startX + (3 * (cpX1 - cpX2)) + endX;
+ b = 2 * (startX - (2 * cpX1) + cpX2);
+ c = -startX + cpX1;
+ double s = (b * b) - (4 * a * c);
+ if ((s >= 0.0) && (a.abs() > epsilon)) {
+ if (s == 0.0) {
+ final double t = -b / (2 * a);
+ final double tprime = 1.0 - t;
+ if ((t >= 0.0) && (t <= 1.0)) {
+ extremaX = ((tprime * tprime * tprime) * startX) +
+ ((3 * tprime * tprime * t) * cpX1) +
+ ((3 * tprime * t * t) * cpX2) +
+ (t * t * t * endX);
+ if (extremaX < bounds[0]) {
+ bounds[0] = extremaX;
+ }
+ if (extremaX > bounds[2]) {
+ bounds[2] = extremaX;
+ }
+ }
+ } else {
+ s = sqrt(s);
+ double t = (-b - s) / (2 * a);
+ double tprime = 1.0 - t;
+ if ((t >= 0.0) && (t <= 1.0)) {
+ extremaX = ((tprime * tprime * tprime) * startX) +
+ ((3 * tprime * tprime * t) * cpX1) +
+ ((3 * tprime * t * t) * cpX2) +
+ (t * t * t * endX);
+ if (extremaX < bounds[0]) {
+ bounds[0] = extremaX;
+ }
+ if (extremaX > bounds[2]) {
+ bounds[2] = extremaX;
+ }
+ }
+ t = (-b + s) / (2 * a);
+ tprime = 1.0 - t;
+ if ((t >= 0.0) && (t <= 1.0)) {
+ extremaX = ((tprime * tprime * tprime) * startX) +
+ ((3 * tprime * tprime * t) * cpX1) +
+ ((3 * tprime * t * t) * cpX2) +
+ (t * t * t * endX);
+ if (extremaX < bounds[0]) {
+ bounds[0] = extremaX;
+ }
+ if (extremaX > bounds[2]) {
+ bounds[2] = extremaX;
+ }
+ }
+ }
+ }
+ }
+ if (!(((startY < cpY1) && (cpY1 < cpY2) && (cpY2 < endY)) ||
+ ((startY > cpY1) && (cpY1 > cpY2) && (cpY2 > endY)))) {
+ a = -startY + (3 * (cpY1 - cpY2)) + endY;
+ b = 2 * (startY - (2 * cpY1) + cpY2);
+ c = -startY + cpY1;
+ double s = (b * b) - (4 * a * c);
+ if ((s >= 0.0) && (a.abs() > epsilon)) {
+ if (s == 0.0) {
+ final double t = -b / (2 * a);
+ final double tprime = 1.0 - t;
+ if ((t >= 0.0) && (t <= 1.0)) {
+ extremaY = ((tprime * tprime * tprime) * startY) +
+ ((3 * tprime * tprime * t) * cpY1) +
+ ((3 * tprime * t * t) * cpY2) +
+ (t * t * t * endY);
+ if (extremaY < bounds[1]) {
+ bounds[1] = extremaY;
+ }
+ if (extremaY > bounds[3]) {
+ bounds[3] = extremaY;
+ }
+ }
+ } else {
+ s = sqrt(s);
+ final double t = (-b - s) / (2 * a);
+ final double tprime = 1.0 - t;
+ if ((t >= 0.0) && (t <= 1.0)) {
+ extremaY = ((tprime * tprime * tprime) * startY) +
+ ((3 * tprime * tprime * t) * cpY1) +
+ ((3 * tprime * t * t) * cpY2) +
+ (t * t * t * endY);
+ if (extremaY < bounds[1]) {
+ bounds[1] = extremaY;
+ }
+ if (extremaY > bounds[3]) {
+ bounds[3] = extremaY;
+ }
+ }
+ final double t2 = (-b + s) / (2 * a);
+ final double tprime2 = 1.0 - t2;
+ if ((t2 >= 0.0) && (t2 <= 1.0)) {
+ extremaY = ((tprime2 * tprime2 * tprime2) * startY) +
+ ((3 * tprime2 * tprime2 * t2) * cpY1) +
+ ((3 * tprime2 * t2 * t2) * cpY2) +
+ (t2 * t2 * t2 * endY);
+ if (extremaY < bounds[1]) {
+ bounds[1] = extremaY;
+ }
+ if (extremaY > bounds[3]) {
+ bounds[3] = extremaY;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return bounds;
+ }
+}
diff --git a/lib/src/rive_core/shapes/path_composer.dart b/lib/src/rive_core/shapes/path_composer.dart
new file mode 100644
index 0000000..568ab7e
--- /dev/null
+++ b/lib/src/rive_core/shapes/path_composer.dart
@@ -0,0 +1,91 @@
+import 'dart:ui' as ui;
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/shapes/shape.dart';
+import 'package:rive/src/generated/shapes/path_composer_base.dart';
+
+class PathComposer extends PathComposerBase {
+ Shape _shape;
+ Shape get shape => _shape;
+ final ui.Path worldPath = ui.Path();
+ final ui.Path localPath = ui.Path();
+ ui.Path _fillPath;
+ ui.Path get fillPath => _fillPath;
+ void _changeShape(Shape value) {
+ if (value == _shape) {
+ return;
+ }
+ if (_shape != null && _shape.pathComposer == this) {
+ _shape.pathComposer = null;
+ }
+ value?.pathComposer = this;
+ _shape = value;
+ }
+
+ void _recomputePath() {
+ var buildLocalPath = _shape.wantLocalPath;
+ var buildWorldPath = _shape.wantWorldPath || !buildLocalPath;
+ if (buildLocalPath) {
+ localPath.reset();
+ var world = _shape.worldTransform;
+ Mat2D inverseWorld = Mat2D();
+ if (!Mat2D.invert(inverseWorld, world)) {
+ Mat2D.identity(inverseWorld);
+ }
+ for (final path in _shape.paths) {
+ Mat2D localTransform;
+ var transform = path.pathTransform;
+ if (transform != null) {
+ localTransform = Mat2D();
+ Mat2D.multiply(localTransform, inverseWorld, transform);
+ }
+ localPath.addPath(path.uiPath, ui.Offset.zero,
+ matrix4: localTransform?.mat4);
+ }
+ if (!buildWorldPath) {
+ _shape.markBoundsDirty();
+ }
+ }
+ if (buildWorldPath) {
+ worldPath.reset();
+ for (final path in _shape.paths) {
+ worldPath.addPath(path.uiPath, ui.Offset.zero,
+ matrix4: path.pathTransform?.mat4);
+ }
+ _shape.markBoundsDirty();
+ }
+ _fillPath = _shape.fillInWorld ? worldPath : localPath;
+ }
+
+ @override
+ void buildDependencies() {
+ super.buildDependencies();
+ if (_shape != null) {
+ _shape.addDependent(this);
+ for (final path in _shape?.paths) {
+ path.addDependent(this);
+ }
+ }
+ }
+
+ @override
+ void update(int dirt) {
+ if (dirt & ComponentDirt.path != 0) {
+ _recomputePath();
+ }
+ }
+
+ @override
+ bool resolveArtboard() {
+ _changeShape(null);
+ return super.resolveArtboard();
+ }
+
+ @override
+ void visitAncestor(Component ancestor) {
+ if (_shape == null && ancestor is Shape) {
+ _changeShape(ancestor);
+ }
+ }
+}
diff --git a/lib/src/rive_core/shapes/path_vertex.dart b/lib/src/rive_core/shapes/path_vertex.dart
new file mode 100644
index 0000000..7a100dc
--- /dev/null
+++ b/lib/src/rive_core/shapes/path_vertex.dart
@@ -0,0 +1,36 @@
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/shapes/path.dart';
+import 'package:rive/src/generated/shapes/path_vertex_base.dart';
+export 'package:rive/src/generated/shapes/path_vertex_base.dart';
+
+abstract class PathVertex extends PathVertexBase {
+ Path get path => parent as Path;
+ @override
+ void update(int dirt) {}
+ Vec2D get translation {
+ return Vec2D.fromValues(x, y);
+ }
+
+ set translation(Vec2D value) {
+ x = value[0];
+ y = value[1];
+ }
+
+ @override
+ void xChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ path?.markPathDirty();
+ }
+
+ @override
+ void yChanged(double from, double to) {
+ addDirt(ComponentDirt.worldTransform);
+ path?.markPathDirty();
+ }
+
+ @override
+ String toString() {
+ return translation.toString();
+ }
+}
diff --git a/lib/src/rive_core/shapes/points_path.dart b/lib/src/rive_core/shapes/points_path.dart
new file mode 100644
index 0000000..a31746d
--- /dev/null
+++ b/lib/src/rive_core/shapes/points_path.dart
@@ -0,0 +1,43 @@
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+import 'package:rive/src/generated/shapes/points_path_base.dart';
+export 'package:rive/src/generated/shapes/points_path_base.dart';
+
+enum PointsPathEditMode { off, creating, editing }
+
+class PointsPath extends PointsPathBase {
+ final List _vertices = [];
+ PointsPath() {
+ isClosed = false;
+ }
+ @override
+ Mat2D get pathTransform => worldTransform;
+ @override
+ Mat2D get inversePathTransform => inverseWorldTransform;
+ @override
+ List get vertices => _vertices;
+ @override
+ void childAdded(Component child) {
+ super.childAdded(child);
+ if (child is PathVertex && !_vertices.contains(child)) {
+ _vertices.add(child);
+ markPathDirty();
+ addDirt(ComponentDirt.vertices);
+ }
+ }
+
+ @override
+ void childRemoved(Component child) {
+ super.childRemoved(child);
+ if (child is PathVertex && _vertices.remove(child)) {
+ markPathDirty();
+ }
+ }
+
+ @override
+ void isClosedChanged(bool from, bool to) {
+ markPathDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/rectangle.dart b/lib/src/rive_core/shapes/rectangle.dart
new file mode 100644
index 0000000..95f3ac6
--- /dev/null
+++ b/lib/src/rive_core/shapes/rectangle.dart
@@ -0,0 +1,28 @@
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
+import 'package:rive/src/generated/shapes/rectangle_base.dart';
+export 'package:rive/src/generated/shapes/rectangle_base.dart';
+
+class Rectangle extends RectangleBase {
+ @override
+ List get vertices => [
+ StraightVertex()
+ ..x = -width / 2
+ ..y = -height / 2
+ ..radius = cornerRadius,
+ StraightVertex()
+ ..x = width / 2
+ ..y = -height / 2
+ ..radius = cornerRadius,
+ StraightVertex()
+ ..x = width / 2
+ ..y = height / 2
+ ..radius = cornerRadius,
+ StraightVertex()
+ ..x = -width / 2
+ ..y = height / 2
+ ..radius = cornerRadius
+ ];
+ @override
+ void cornerRadiusChanged(double from, double to) => markPathDirty();
+}
diff --git a/lib/src/rive_core/shapes/render_cubic_vertex.dart b/lib/src/rive_core/shapes/render_cubic_vertex.dart
new file mode 100644
index 0000000..ca561a4
--- /dev/null
+++ b/lib/src/rive_core/shapes/render_cubic_vertex.dart
@@ -0,0 +1,18 @@
+import 'dart:collection';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/shapes/cubic_vertex.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_writer.dart';
+
+class RenderCubicVertex extends CubicVertex {
+ @override
+ void changeNonNull() {}
+ @override
+ Vec2D inPoint;
+ @override
+ Vec2D outPoint;
+ @override
+ void onAddedDirty() {}
+ @override
+ void writeRuntimeProperties(
+ BinaryWriter writer, HashMap idLookup) {}
+}
diff --git a/lib/src/rive_core/shapes/shape.dart b/lib/src/rive_core/shapes/shape.dart
new file mode 100644
index 0000000..4abb181
--- /dev/null
+++ b/lib/src/rive_core/shapes/shape.dart
@@ -0,0 +1,265 @@
+import 'dart:ui';
+import 'package:rive/src/rive_core/bounds_delegate.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/component_dirt.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/shapes/paint/fill.dart';
+import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart' as core;
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/rive_core/shapes/paint/stroke.dart';
+import 'package:rive/src/rive_core/shapes/path.dart';
+import 'package:rive/src/rive_core/shapes/path_composer.dart';
+import 'package:rive/src/rive_core/shapes/shape_paint_container.dart';
+import 'package:rive/src/generated/shapes/shape_base.dart';
+export 'package:rive/src/generated/shapes/shape_base.dart';
+
+class Shape extends ShapeBase with ShapePaintContainer {
+ final Set paths = {};
+ bool _wantWorldPath = false;
+ bool _wantLocalPath = false;
+ bool get wantWorldPath => _wantWorldPath;
+ bool get wantLocalPath => _wantLocalPath;
+ bool _fillInWorld = false;
+ bool get fillInWorld => _fillInWorld;
+ PathComposer _pathComposer;
+ PathComposer get pathComposer => _pathComposer;
+ set pathComposer(PathComposer value) {
+ if (_pathComposer == value) {
+ return;
+ }
+ _pathComposer = value;
+ transformAffectsStrokeChanged();
+ }
+
+ AABB _worldBounds;
+ AABB _localBounds;
+ BoundsDelegate _delegate;
+ @override
+ AABB get worldBounds => _worldBounds ??= computeWorldBounds();
+ @override
+ AABB get localBounds => _localBounds ??= computeLocalBounds();
+ void markBoundsDirty() {
+ _worldBounds = _localBounds = null;
+ _delegate?.boundsChanged();
+ for (final path in paths) {
+ path.markBoundsDirty();
+ }
+ }
+
+ @override
+ void childAdded(Component child) {
+ super.childAdded(child);
+ switch (child.coreType) {
+ case FillBase.typeKey:
+ addFill(child as Fill);
+ break;
+ case StrokeBase.typeKey:
+ addStroke(child as Stroke);
+ break;
+ }
+ }
+
+ @override
+ void childRemoved(Component child) {
+ super.childRemoved(child);
+ switch (child.coreType) {
+ case FillBase.typeKey:
+ removeFill(child as Fill);
+ break;
+ case StrokeBase.typeKey:
+ removeStroke(child as Stroke);
+ break;
+ }
+ }
+
+ bool addPath(Path path) {
+ transformAffectsStrokeChanged();
+ return paths.add(path);
+ }
+
+ void pathChanged(Path path) {
+ _pathComposer?.addDirt(ComponentDirt.path);
+ }
+
+ void transformAffectsStrokeChanged() {
+ addDirt(ComponentDirt.path);
+ _pathComposer?.addDirt(ComponentDirt.path);
+ }
+
+ @override
+ bool addStroke(Stroke stroke) {
+ transformAffectsStrokeChanged();
+ return super.addStroke(stroke);
+ }
+
+ @override
+ bool removeStroke(Stroke stroke) {
+ transformAffectsStrokeChanged();
+ return super.removeStroke(stroke);
+ }
+
+ @override
+ void update(int dirt) {
+ super.update(dirt);
+ if (dirt & ComponentDirt.paint != 0) {
+ for (final fill in fills) {
+ fill.blendMode = blendMode;
+ }
+ for (final stroke in strokes) {
+ stroke.blendMode = blendMode;
+ }
+ }
+ if (dirt & ComponentDirt.worldTransform != 0) {
+ for (final fill in fills) {
+ fill.renderOpacity = renderOpacity;
+ }
+ for (final stroke in strokes) {
+ stroke.renderOpacity = renderOpacity;
+ }
+ }
+ if (dirt & ComponentDirt.path != 0) {
+ _wantWorldPath = false;
+ _wantLocalPath = false;
+ for (final stroke in strokes) {
+ if (stroke.transformAffectsStroke) {
+ _wantLocalPath = true;
+ } else {
+ _wantWorldPath = true;
+ }
+ }
+ _fillInWorld = _wantWorldPath || !_wantLocalPath;
+ var mustFillLocal = fills.firstWhere(
+ (fill) => fill.paintMutator is core.LinearGradient,
+ orElse: () => null) !=
+ null;
+ if (mustFillLocal) {
+ _fillInWorld = false;
+ _wantLocalPath = true;
+ }
+ for (final fill in fills) {
+ var mutator = fill.paintMutator;
+ if (mutator is core.LinearGradient) {
+ mutator.paintsInWorldSpace = _fillInWorld;
+ }
+ }
+ for (final stroke in strokes) {
+ var mutator = stroke.paintMutator;
+ if (mutator is core.LinearGradient) {
+ mutator.paintsInWorldSpace = !stroke.transformAffectsStroke;
+ }
+ }
+ }
+ }
+
+ bool removePath(Path path) {
+ transformAffectsStrokeChanged();
+ return paths.remove(path);
+ }
+
+ AABB computeWorldBounds() {
+ if (paths.isEmpty) {
+ return AABB.fromMinMax(worldTranslation, worldTranslation);
+ }
+ var path = paths.first;
+ var renderPoints = path.renderVertices;
+ if (renderPoints.isEmpty) {
+ return AABB.fromMinMax(worldTranslation, worldTranslation);
+ }
+ AABB worldBounds =
+ path.preciseComputeBounds(renderPoints, path.pathTransform);
+ for (final path in paths.skip(1)) {
+ var renderPoints = path.renderVertices;
+ AABB.combine(worldBounds, worldBounds,
+ path.preciseComputeBounds(renderPoints, path.pathTransform));
+ }
+ return worldBounds;
+ }
+
+ AABB computeLocalBounds() {
+ if (paths.isEmpty) {
+ return AABB();
+ }
+ var path = paths.first;
+ var renderPoints = path.renderVertices;
+ if (renderPoints.isEmpty) {
+ return AABB();
+ }
+ var toShapeTransform = Mat2D();
+ if (!Mat2D.invert(toShapeTransform, worldTransform)) {
+ Mat2D.identity(toShapeTransform);
+ }
+ AABB localBounds = path.preciseComputeBounds(renderPoints,
+ Mat2D.multiply(Mat2D(), toShapeTransform, path.pathTransform));
+ for (final path in paths.skip(1)) {
+ var renderPoints = path.renderVertices;
+ AABB.combine(
+ localBounds,
+ localBounds,
+ path.preciseComputeBounds(renderPoints,
+ Mat2D.multiply(Mat2D(), toShapeTransform, path.pathTransform)));
+ }
+ return localBounds;
+ }
+
+ @override
+ void userDataChanged(dynamic from, dynamic to) {
+ if (to is BoundsDelegate) {
+ _delegate = to;
+ } else {
+ _delegate = null;
+ }
+ }
+
+ @override
+ void blendModeValueChanged(int from, int to) => _markBlendModeDirty();
+ @override
+ void draw(Canvas canvas) {
+ assert(_pathComposer != null);
+ var path = _pathComposer.fillPath;
+ assert(path != null, 'path should\'ve been generated by the time we draw');
+ if (!_fillInWorld) {
+ canvas.save();
+ canvas.transform(worldTransform.mat4);
+ }
+ for (final fill in fills) {
+ fill.draw(canvas, path);
+ }
+ if (!_fillInWorld) {
+ canvas.restore();
+ }
+ for (final stroke in strokes) {
+ var transformAffectsStroke = stroke.transformAffectsStroke;
+ var path = transformAffectsStroke
+ ? _pathComposer.localPath
+ : _pathComposer.worldPath;
+ if (transformAffectsStroke) {
+ canvas.save();
+ canvas.transform(worldTransform.mat4);
+ stroke.draw(canvas, path);
+ canvas.restore();
+ } else {
+ stroke.draw(canvas, path);
+ }
+ }
+ }
+
+ void _markBlendModeDirty() => addDirt(ComponentDirt.paint);
+ @override
+ void onPaintMutatorChanged(ShapePaintMutator mutator) {
+ transformAffectsStrokeChanged();
+ _markBlendModeDirty();
+ }
+
+ @override
+ void onStrokesChanged() {
+ transformAffectsStrokeChanged();
+ _markBlendModeDirty();
+ }
+
+ @override
+ void onFillsChanged() {
+ transformAffectsStrokeChanged();
+ _markBlendModeDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/shape_paint_container.dart b/lib/src/rive_core/shapes/shape_paint_container.dart
new file mode 100644
index 0000000..868a984
--- /dev/null
+++ b/lib/src/rive_core/shapes/shape_paint_container.dart
@@ -0,0 +1,61 @@
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+import 'package:rive/src/rive_core/shapes/paint/fill.dart';
+import 'package:meta/meta.dart';
+import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
+import 'package:rive/src/rive_core/shapes/paint/stroke.dart';
+
+abstract class ShapePaintContainer {
+ final Set fills = {};
+ final Set strokes = {};
+ void onPaintMutatorChanged(ShapePaintMutator mutator);
+ @protected
+ void onFillsChanged();
+ @protected
+ void onStrokesChanged();
+ @protected
+ bool addFill(Fill fill) {
+ if (fills.add(fill)) {
+ onFillsChanged();
+ return true;
+ }
+ return false;
+ }
+
+ @protected
+ bool removeFill(Fill fill) {
+ if (fills.remove(fill)) {
+ onFillsChanged();
+ return true;
+ }
+ return false;
+ }
+
+ @protected
+ bool addStroke(Stroke stroke) {
+ if (strokes.add(stroke)) {
+ onStrokesChanged();
+ return true;
+ }
+ return false;
+ }
+
+ @protected
+ bool removeStroke(Stroke stroke) {
+ if (strokes.remove(stroke)) {
+ onStrokesChanged();
+ return true;
+ }
+ return false;
+ }
+
+ AABB get worldBounds;
+ AABB get localBounds;
+ bool addDirt(int value, {bool recurse = false});
+ bool addDependent(Component dependent);
+ void appendChild(Component child);
+ Mat2D get worldTransform;
+ Vec2D get worldTranslation;
+}
diff --git a/lib/src/rive_core/shapes/straight_vertex.dart b/lib/src/rive_core/shapes/straight_vertex.dart
new file mode 100644
index 0000000..c51b97f
--- /dev/null
+++ b/lib/src/rive_core/shapes/straight_vertex.dart
@@ -0,0 +1,11 @@
+import 'package:rive/src/generated/shapes/straight_vertex_base.dart';
+export 'package:rive/src/generated/shapes/straight_vertex_base.dart';
+
+class StraightVertex extends StraightVertexBase {
+ @override
+ String toString() => 'x[$x], y[$y], r[$radius]';
+ @override
+ void radiusChanged(double from, double to) {
+ path?.markPathDirty();
+ }
+}
diff --git a/lib/src/rive_core/shapes/triangle.dart b/lib/src/rive_core/shapes/triangle.dart
new file mode 100644
index 0000000..949e74f
--- /dev/null
+++ b/lib/src/rive_core/shapes/triangle.dart
@@ -0,0 +1,19 @@
+import 'package:rive/src/rive_core/shapes/path_vertex.dart';
+import 'package:rive/src/rive_core/shapes/straight_vertex.dart';
+import 'package:rive/src/generated/shapes/triangle_base.dart';
+export 'package:rive/src/generated/shapes/triangle_base.dart';
+
+class Triangle extends TriangleBase {
+ @override
+ List get vertices => [
+ StraightVertex()
+ ..x = 0
+ ..y = -height / 2,
+ StraightVertex()
+ ..x = width / 2
+ ..y = height / 2,
+ StraightVertex()
+ ..x = -width / 2
+ ..y = height / 2
+ ];
+}
diff --git a/lib/src/rive_core/transform_space.dart b/lib/src/rive_core/transform_space.dart
new file mode 100644
index 0000000..72acc44
--- /dev/null
+++ b/lib/src/rive_core/transform_space.dart
@@ -0,0 +1 @@
+enum TransformSpace { world, local }
diff --git a/lib/src/rive_file.dart b/lib/src/rive_file.dart
new file mode 100644
index 0000000..68171cf
--- /dev/null
+++ b/lib/src/rive_file.dart
@@ -0,0 +1,182 @@
+import 'dart:typed_data';
+
+import 'package:rive/src/rive_core/animation/keyframe_draw_order.dart';
+import 'package:rive/src/rive_core/animation/keyframe_draw_order_value.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/runtime/runtime_header.dart';
+import 'package:rive/src/rive_core/backboard.dart';
+import 'package:rive/src/core/core.dart';
+import 'package:rive/src/utilities/binary_buffer/binary_reader.dart';
+import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart';
+import 'package:rive/src/rive_core/animation/animation.dart';
+import 'package:rive/src/rive_core/animation/keyed_object.dart';
+import 'package:rive/src/rive_core/animation/keyed_property.dart';
+import 'package:rive/src/rive_core/animation/keyframe.dart';
+import 'package:rive/src/rive_core/animation/linear_animation.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+
+class RiveFile {
+ RuntimeHeader _header;
+ RuntimeHeader get header => _header;
+ Backboard _backboard;
+ Backboard get backboard => _backboard;
+
+ final List _artboards = [];
+ List get artboards => _artboards;
+
+ Artboard get mainArtboard => _artboards.first;
+
+ bool import(ByteData bytes) {
+ assert(_header == null, 'can only import once');
+ var reader = BinaryReader(bytes);
+ _header = RuntimeHeader.read(reader);
+
+ _backboard = readRuntimeObject(reader);
+ if (_backboard == null) {
+ throw const RiveFormatErrorException(
+ 'expected first object to be a Backboard');
+ }
+
+ int numArtboards = reader.readVarUint();
+ for (int i = 0; i < numArtboards; i++) {
+ var numObjects = reader.readVarUint();
+ if (numObjects == 0) {
+ throw const RiveFormatErrorException(
+ 'artboards must contain at least one object (themselves)');
+ }
+ var artboard = readRuntimeObject(reader, RuntimeArtboard());
+ // Kind of weird, but the artboard is the core context at runtime, so we
+ // want other objects to be able to resolve it. It's always at the 0
+ // index.
+ artboard?.addObject(artboard);
+ _artboards.add(artboard);
+ // var objects = List>(numObjects);
+ for (int i = 1; i < numObjects; i++) {
+ Core object = readRuntimeObject(reader);
+ // N.B. we add objects that don't load (null) too as we need to look
+ // them up by index.
+ artboard.addObject(object);
+ }
+
+ // Animations also need to reference objects, so make sure they get read
+ // in before the hierarchy resolves (batch add completes).
+ var numAnimations = reader.readVarUint();
+ for (int i = 0; i < numAnimations; i++) {
+ var animation = readRuntimeObject(reader);
+ if (animation == null) {
+ continue;
+ }
+ artboard.addObject(animation);
+ animation.artboard = artboard;
+ if (animation is LinearAnimation) {
+ var numKeyedObjects = reader.readVarUint();
+ var keyedObjects = List(numKeyedObjects);
+ for (int j = 0; j < numKeyedObjects; j++) {
+ var keyedObject = readRuntimeObject(reader);
+ if (keyedObject == null) {
+ continue;
+ }
+ keyedObjects[j] = keyedObject;
+ artboard.addObject(keyedObject);
+
+ animation.internalAddKeyedObject(keyedObject);
+
+ var numKeyedProperties = reader.readVarUint();
+ for (int k = 0; k < numKeyedProperties; k++) {
+ var keyedProperty = readRuntimeObject(reader);
+ if (keyedProperty == null) {
+ continue;
+ }
+ artboard.addObject(keyedProperty);
+ keyedObject.internalAddKeyedProperty(keyedProperty);
+
+ var numKeyframes = reader.readVarUint();
+ for (int l = 0; l < numKeyframes; l++) {
+ var keyframe = readRuntimeObject(reader);
+ if (keyframe == null) {
+ continue;
+ } else if (keyframe is KeyFrameDrawOrder) {
+ int numValues = reader.readVarUint();
+ for (int i = 0; i < numValues; i++) {
+ var valueObject = KeyFrameDrawOrderValue();
+ valueObject.drawableId = reader.readVarInt();
+ valueObject.value = i;
+ keyframe.internalAddValue(valueObject);
+ }
+ }
+ artboard.addObject(keyframe);
+ keyedProperty.internalAddKeyFrame(keyframe);
+ keyframe.computeSeconds(animation);
+ }
+ }
+ }
+
+ for (final keyedObject in keyedObjects) {
+ keyedObject?.objectId ??= artboard.id;
+ }
+ }
+ }
+
+ // Any component objects with no id map to the artboard. Skip first item
+ // as it's the artboard itself.
+ for (final object in artboard.objects.skip(1)) {
+ if (object is Component && object.parentId == null) {
+ object.parent = artboard;
+ }
+ object?.onAddedDirty();
+ }
+
+ assert(!artboard.children.contains(artboard),
+ 'artboard should never contain itself as a child');
+ for (final object in artboard.objects) {
+ object?.onAdded();
+ }
+ artboard.clean();
+ }
+
+ return true;
+ }
+}
+
+T readRuntimeObject>(BinaryReader reader,
+ [T instance]) {
+ int coreObjectKey = reader.readVarUint();
+
+ var object = instance ?? RiveCoreContext.makeCoreInstance(coreObjectKey);
+ if (object is! T) {
+ return null;
+ }
+
+ while (true) {
+ int propertyKey = reader.readVarUint();
+ if (propertyKey == 0) {
+ // Terminator. https://media.giphy.com/media/7TtvTUMm9mp20/giphy.gif
+ break;
+ }
+ int propertyLength = reader.readVarUint();
+ Uint8List valueBytes = reader.read(propertyLength);
+
+ var fieldType = RiveCoreContext.coreType(propertyKey);
+ if (fieldType == null) {
+ // This is considered an acceptable failure. A runtime may not support
+ // the same properties that were exported. The older object could still
+ // function without them, however, so it's up to the implementation to
+ // make sure that major versions are revved when breaking properties are
+ // added. Note that we intentionally first read the entire value bytes
+ // for the property so we can advance as expected even if we are
+ // skipping this value.
+ continue;
+ }
+
+ // We know what to expect, let's try to read the value. We instance a new
+ // reader here so that we don't overflow the exact length we're allowed to
+ // read.
+ var valueReader = BinaryReader.fromList(valueBytes);
+
+ // This will attempt to set the object property, but failure here is
+ // acceptable.
+ RiveCoreContext.setObjectProperty(
+ object, propertyKey, fieldType.deserialize(valueReader));
+ }
+ return object as T;
+}
diff --git a/lib/src/rive_render_box.dart b/lib/src/rive_render_box.dart
new file mode 100644
index 0000000..851240a
--- /dev/null
+++ b/lib/src/rive_render_box.dart
@@ -0,0 +1,195 @@
+import 'dart:math';
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter/scheduler.dart';
+import 'package:rive/src/rive_core/math/aabb.dart';
+import 'package:rive/src/rive_core/math/mat2d.dart';
+import 'package:rive/src/rive_core/math/vec2d.dart';
+
+abstract class RiveRenderBox extends RenderBox {
+ final Stopwatch _stopwatch = Stopwatch();
+ BoxFit _fit;
+ Alignment _alignment;
+ bool _useIntrinsicSize = false;
+
+ bool get useIntrinsicSize => _useIntrinsicSize;
+ set useIntrinsicSize(bool value) {
+ if (_useIntrinsicSize == value) {
+ return;
+ }
+ _useIntrinsicSize = value;
+ if (parent != null) {
+ markNeedsLayoutForSizedByParentChange();
+ }
+ }
+
+ Size _intrinsicSize;
+ Size get intrinsicSize => _intrinsicSize;
+ set intrinsicSize(Size value) {
+ if (_intrinsicSize == value) {
+ return;
+ }
+ _intrinsicSize = value;
+ if (parent != null) {
+ markNeedsLayoutForSizedByParentChange();
+ }
+ }
+
+ BoxFit get fit => _fit;
+ set fit(BoxFit value) {
+ if (value != _fit) {
+ _fit = value;
+ markNeedsPaint();
+ }
+ }
+
+ Alignment get alignment => _alignment;
+ set alignment(Alignment value) {
+ if (value != _alignment) {
+ _alignment = value;
+ markNeedsPaint();
+ }
+ }
+
+ @override
+ bool get sizedByParent => !_useIntrinsicSize || _intrinsicSize == null;
+
+ @override
+ void performLayout() {
+ if (!sizedByParent) {
+ size = constraints.constrain(_intrinsicSize);
+ }
+ }
+
+ @override
+ bool hitTestSelf(Offset screenOffset) => true;
+
+ @override
+ void performResize() {
+ size = _useIntrinsicSize ? constraints.smallest : constraints.biggest;
+ }
+
+ @override
+ void detach() {
+ _stopwatch.stop();
+ super.detach();
+ }
+
+ @override
+ void attach(PipelineOwner owner) {
+ _stopwatch.start();
+ super.attach(owner);
+ }
+
+ /// Get the Axis Aligned Bounding Box that encompasses the world space scene
+ AABB get aabb;
+
+ void draw(Canvas canvas, Mat2D viewTransform);
+ void beforeDraw(Canvas canvas, Offset offset) {}
+ void afterDraw(Canvas canvas, Offset offset) {}
+
+ double _elapsedSeconds = 0;
+ void _frameCallback(Duration duration) {
+ _elapsedSeconds = _stopwatch.elapsedTicks / _stopwatch.frequency;
+ _stopwatch.reset();
+ markNeedsPaint();
+ }
+
+ int _frameCallbackId;
+ void scheduleRepaint() {
+ if (_frameCallbackId != null) {
+ return;
+ }
+ _frameCallbackId =
+ SchedulerBinding.instance.scheduleFrameCallback(_frameCallback);
+ }
+
+ @override
+ void paint(PaintingContext context, Offset offset) {
+ _frameCallbackId = null;
+ if (advance(_elapsedSeconds)) {
+ scheduleRepaint();
+ }
+ _elapsedSeconds = 0;
+
+ final Canvas canvas = context.canvas;
+
+ AABB bounds = aabb;
+ if (bounds != null) {
+ double contentWidth = bounds[2] - bounds[0];
+ double contentHeight = bounds[3] - bounds[1];
+ double x = -1 * bounds[0] -
+ contentWidth / 2.0 -
+ (_alignment.x * contentWidth / 2.0);
+ double y = -1 * bounds[1] -
+ contentHeight / 2.0 -
+ (_alignment.y * contentHeight / 2.0);
+
+ double scaleX = 1.0, scaleY = 1.0;
+
+ canvas.save();
+ beforeDraw(canvas, offset);
+
+ switch (_fit) {
+ case BoxFit.fill:
+ scaleX = size.width / contentWidth;
+ scaleY = size.height / contentHeight;
+ break;
+ case BoxFit.contain:
+ double minScale =
+ min(size.width / contentWidth, size.height / contentHeight);
+ scaleX = scaleY = minScale;
+ break;
+ case BoxFit.cover:
+ double maxScale =
+ max(size.width / contentWidth, size.height / contentHeight);
+ scaleX = scaleY = maxScale;
+ break;
+ case BoxFit.fitHeight:
+ double minScale = size.height / contentHeight;
+ scaleX = scaleY = minScale;
+ break;
+ case BoxFit.fitWidth:
+ double minScale = size.width / contentWidth;
+ scaleX = scaleY = minScale;
+ break;
+ case BoxFit.none:
+ scaleX = scaleY = 1.0;
+ break;
+ case BoxFit.scaleDown:
+ double minScale =
+ min(size.width / contentWidth, size.height / contentHeight);
+ scaleX = scaleY = minScale < 1.0 ? minScale : 1.0;
+ break;
+ }
+
+ Mat2D transform = Mat2D();
+ transform[4] =
+ offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0);
+ transform[5] =
+ offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0);
+ Mat2D.scale(transform, transform, Vec2D.fromValues(scaleX, scaleY));
+ Mat2D center = Mat2D();
+ center[4] = x;
+ center[5] = y;
+ Mat2D.multiply(transform, transform, center);
+
+ canvas.translate(
+ offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0),
+ offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0),
+ );
+
+ canvas.scale(scaleX, scaleY);
+ canvas.translate(x, y);
+
+ draw(canvas, transform);
+
+ canvas.restore();
+ afterDraw(canvas, offset);
+ }
+ }
+
+ /// Advance animations, physics, etc by elapsedSeconds, returns true if it
+ /// wants to run again.
+ bool advance(double elapsedSeconds);
+}
diff --git a/lib/src/runtime_artboard.dart b/lib/src/runtime_artboard.dart
new file mode 100644
index 0000000..4327e9c
--- /dev/null
+++ b/lib/src/runtime_artboard.dart
@@ -0,0 +1,92 @@
+import 'package:flutter/foundation.dart';
+import 'package:rive/src/rive_core/artboard.dart';
+import 'package:rive/src/rive_core/component.dart';
+import 'package:rive/src/rive_core/event.dart';
+import 'package:rive/src/core/core.dart';
+
+class RuntimeArtboard extends Artboard implements CoreContext {
+ final _redraw = Event();
+ ChangeNotifier get redraw => _redraw;
+
+ final List _objects = [];
+
+ Iterable get objects => _objects;
+ final Set _needDependenciesBuilt = {};
+
+ @override
+ T addObject(T object) {
+ object.context = this;
+ object.id = _objects.length;
+ _objects.add(object);
+ return object;
+ }
+
+ @override
+ void removeObject(T object) {
+ _objects.remove(object);
+ }
+
+ @override
+ void markDependencyOrderDirty() {
+ // TODO: implement markDependencyOrderDirty
+ }
+
+ @override
+ bool markDependenciesDirty(covariant Core object) {
+ if (object is Component) {
+ _needDependenciesBuilt.add(object);
+ return true;
+ }
+
+ return false;
+ }
+
+ void clean() {
+ if (_needDependenciesBuilt.isNotEmpty) {
+ // Copy it in case it is changed during the building (meaning this process
+ // needs to recurse).
+ Set needDependenciesBuilt =
+ Set.from(_needDependenciesBuilt);
+ _needDependenciesBuilt.clear();
+
+ // First resolve the artboards
+ for (final component in needDependenciesBuilt) {
+ component.resolveArtboard();
+ }
+
+ // Then build the dependencies
+ for (final component in needDependenciesBuilt) {
+ component.buildDependencies();
+ }
+
+ sortDependencies();
+ }
+ }
+
+ @override
+ T resolve(int id) {
+ if (id >= _objects.length) {
+ return null;
+ }
+ var object = _objects[id];
+ if (object is T) {
+ return object as T;
+ }
+ return null;
+ }
+
+ @override
+ Core makeCoreInstance(int typeKey) {
+ return null;
+ }
+
+ @override
+ void dirty(void Function() dirt) {
+ // TODO: Schedule a debounced callback for next frame
+ }
+
+ @override
+ void markNeedsAdvance() {
+ _redraw.notify();
+ }
+}
diff --git a/lib/src/utilities/binary_buffer/binary_reader.dart b/lib/src/utilities/binary_buffer/binary_reader.dart
new file mode 100644
index 0000000..eb529b1
--- /dev/null
+++ b/lib/src/utilities/binary_buffer/binary_reader.dart
@@ -0,0 +1,142 @@
+import 'dart:convert';
+import 'dart:typed_data';
+
+var _utf8Decoder = const Utf8Decoder();
+
+class BinaryReader {
+ final ByteData buffer;
+ final Endian endian;
+ int _readIndex = 0;
+
+ BinaryReader(this.buffer, {this.endian = Endian.little});
+
+ BinaryReader.fromList(Uint8List list, {this.endian = Endian.little})
+ : buffer =
+ ByteData.view(list.buffer, list.offsetInBytes, list.lengthInBytes);
+
+ bool get isEOF => _readIndex >= buffer.lengthInBytes;
+
+ double readFloat32() {
+ double value = buffer.getFloat32(_readIndex, endian);
+ _readIndex += 4;
+ return value;
+ }
+
+ double readFloat64() {
+ double value = buffer.getFloat64(_readIndex, endian);
+ _readIndex += 8;
+ return value;
+ }
+
+ int readInt8() {
+ int value = buffer.getInt8(_readIndex);
+ _readIndex += 1;
+ return value;
+ }
+
+ int readUint8() {
+ int value = buffer.getUint8(_readIndex);
+ _readIndex += 1;
+ return value;
+ }
+
+ int readInt16() {
+ int value = buffer.getInt16(_readIndex, endian);
+ _readIndex += 2;
+ return value;
+ }
+
+ int readUint16() {
+ int value = buffer.getUint16(_readIndex, endian);
+ _readIndex += 2;
+ return value;
+ }
+
+ int readInt32() {
+ int value = buffer.getInt32(_readIndex, endian);
+ _readIndex += 4;
+ return value;
+ }
+
+ int readUint32() {
+ int value = buffer.getUint32(_readIndex, endian);
+ _readIndex += 4;
+ return value;
+ }
+
+ int readInt64() {
+ int value = buffer.getInt64(_readIndex, endian);
+ _readIndex += 8;
+ return value;
+ }
+
+ int readUint64() {
+ int value = buffer.getUint64(_readIndex, endian);
+ _readIndex += 8;
+ return value;
+ }
+
+ /// Read a variable length signed integer from the buffer encoded as an LEB128
+ /// signed integer.
+ int readVarInt() {
+ int result = 0;
+ int shift = 0;
+ while (true) {
+ int byte = buffer.getUint8(_readIndex);
+ result |= (byte & 0x7f) << shift;
+ shift += 7;
+ if ((byte & 0x80) == 0) {
+ break;
+ } else {
+ _readIndex++;
+ }
+ }
+ if ((shift < 64) && (buffer.getUint8(_readIndex) & 0x40) != 0) {
+ result |= ~0 << shift;
+ }
+ _readIndex += 1;
+ return result;
+ }
+
+ /// Read a variable length unsigned integer from the buffer encoded as an
+ /// LEB128 unsigned integer.
+ int readVarUint() {
+ int result = 0;
+ int shift = 0;
+ while (true) {
+ int byte = buffer.getUint8(_readIndex++) & 0xff;
+ result |= (byte & 0x7f) << shift;
+ if ((byte & 0x80) == 0) break;
+ shift += 7;
+ }
+ return result;
+ }
+
+ /// Read a string encoded into the stream. Strings are encoded with a varuint
+ /// integer length written first followed by length number of utf8 encoded
+ /// bytes.
+ String readString() {
+ int length = readVarUint();
+ String value = _utf8Decoder.convert(Uint8List.view(
+ buffer.buffer, buffer.offsetInBytes + _readIndex, length));
+ _readIndex += length;
+ return value;
+ }
+
+ Uint8List read(int length, [bool allocNew = false]) {
+ var view = Uint8List.view(
+ buffer.buffer, buffer.offsetInBytes + _readIndex, length);
+ _readIndex += length;
+ return allocNew ? Uint8List.fromList(view) : view;
+ }
+
+ /// Read a list of encoded integers.
+ List readIntList() {
+ int length = readVarUint();
+ var list = List(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = readVarInt();
+ }
+ return list;
+ }
+}
diff --git a/lib/src/utilities/binary_buffer/binary_writer.dart b/lib/src/utilities/binary_buffer/binary_writer.dart
new file mode 100644
index 0000000..5c9a4af
--- /dev/null
+++ b/lib/src/utilities/binary_buffer/binary_writer.dart
@@ -0,0 +1,166 @@
+import 'dart:convert';
+import 'dart:math';
+
+import 'dart:typed_data';
+
+var _variableEncodeList = Uint8List(8);
+var _utf8Encoder = const Utf8Encoder();
+
+class BinaryWriter {
+ /// Stride we allocate buffer in chunks of.
+ final int _alignment;
+ int get alignment => _alignment;
+
+ final Endian endian;
+ Uint8List _buffer;
+ ByteData get buffer =>
+ ByteData.view(_buffer.buffer, _buffer.offsetInBytes, size);
+ Uint8List get uint8Buffer =>
+ Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, size);
+
+ ByteData _byteData;
+ int _writeIndex = 0;
+ int get size => _writeIndex;
+
+ BinaryWriter({int alignment = 1024, this.endian = Endian.little})
+ : _alignment = max(1, alignment) {
+ _buffer = Uint8List(_alignment);
+ _byteData = ByteData.view(_buffer.buffer);
+ }
+
+ void _ensureAvailable(int byteLength) {
+ if (_writeIndex + byteLength > _buffer.length) {
+ do {
+ _buffer = Uint8List(_buffer.length + _alignment)
+ ..setRange(0, _buffer.length, _buffer);
+ } while (_writeIndex + byteLength > _buffer.length);
+ _byteData = ByteData.view(_buffer.buffer);
+ }
+ }
+
+ void writeFloat32(double value) {
+ _ensureAvailable(4);
+ _byteData.setFloat32(_writeIndex, value, endian);
+ _writeIndex += 4;
+ }
+
+ void writeFloat64(double value) {
+ _ensureAvailable(8);
+ _byteData.setFloat64(_writeIndex, value, endian);
+ _writeIndex += 8;
+ }
+
+ void writeInt8(int value) {
+ _ensureAvailable(1);
+ _byteData.setInt8(_writeIndex, value);
+ _writeIndex += 1;
+ }
+
+ void writeUint8(int value) {
+ _ensureAvailable(1);
+ _byteData.setUint8(_writeIndex, value);
+ _writeIndex += 1;
+ }
+
+ void writeInt16(int value) {
+ _ensureAvailable(2);
+ _byteData.setInt16(_writeIndex, value, endian);
+ _writeIndex += 2;
+ }
+
+ void writeUint16(int value) {
+ _ensureAvailable(2);
+ _byteData.setUint16(_writeIndex, value, endian);
+ _writeIndex += 2;
+ }
+
+ void writeInt32(int value) {
+ _ensureAvailable(4);
+ _byteData.setInt32(_writeIndex, value, endian);
+ _writeIndex += 4;
+ }
+
+ void writeUint32(int value) {
+ _ensureAvailable(4);
+ _byteData.setUint32(_writeIndex, value, endian);
+ _writeIndex += 4;
+ }
+
+ void writeInt64(int value) {
+ _ensureAvailable(8);
+ _byteData.setInt64(_writeIndex, value, endian);
+ _writeIndex += 8;
+ }
+
+ void writeUint64(int value) {
+ _ensureAvailable(8);
+ _byteData.setUint64(_writeIndex, value, endian);
+ _writeIndex += 8;
+ }
+
+ /// Write bytes into the buffer. Optional [length] to write a specific number
+ /// of [bytes], otherwise the length from [bytes] is used.
+ void write(Uint8List bytes, [int length]) {
+ length ??= bytes.length;
+ _ensureAvailable(length);
+ _buffer.setRange(_writeIndex, _writeIndex + length, bytes);
+ _writeIndex += length;
+ }
+
+ /// Write an integer as a list of bytes that contain an LEB128 signed integer.
+ /// The size of the integer is decided automatically.
+ void writeVarInt(int value) {
+ var more = true;
+ int index = 0;
+ while (more) {
+ var byte = value & 0x7f;
+ //ignore: parameter_assignments
+ value >>= 7;
+ if (value == 0 && (byte & 0x40) == 0) {
+ more = false;
+ } else if (value == -1 && (byte & 0x40) > 0) {
+ more = false;
+ } else {
+ byte |= 0x80;
+ }
+ _variableEncodeList[index++] = byte;
+ }
+
+ write(_variableEncodeList, index);
+ }
+
+ /// Write an integer as a list of bytes that contain an LEB128 unsigned
+ /// integer. The size of the integer is decided automatically.
+ void writeVarUint(int value) {
+ int size = (value.toRadixString(2).length / 7.0).ceil();
+ int index = 0;
+ int i = 0;
+ while (i < size) {
+ int part = value & 0x7f;
+ //ignore: parameter_assignments
+ value >>= 7;
+ _variableEncodeList[index++] = part;
+ i += 1;
+ }
+ for (var i = 0; i < index - 1; i++) {
+ _variableEncodeList[i] |= 0x80;
+ }
+ write(_variableEncodeList, index);
+ }
+
+ /// Encode a string into the buffer. Strings are encoded with a varuint
+ /// integer length written first followed by length number of utf8 encoded
+ /// bytes.
+ void writeString(String value) {
+ var list = _utf8Encoder.convert(value);
+ writeVarUint(list.length);
+ write(list);
+ }
+
+ /// Write a list of integers as varint.
+ void writeIntList(List list) {
+ assert(list != null);
+ writeVarUint(list.length);
+ list.forEach(writeVarInt);
+ }
+}
diff --git a/lib/src/utilities/dependency_sorter.dart b/lib/src/utilities/dependency_sorter.dart
new file mode 100644
index 0000000..35212a4
--- /dev/null
+++ b/lib/src/utilities/dependency_sorter.dart
@@ -0,0 +1,114 @@
+import 'dart:collection';
+import 'package:graphs/graphs.dart';
+
+/// Interface for a node in the dependency graph.
+abstract class DependencyGraphNode {
+ Set get dependents;
+}
+
+/// A simple dependency sorter which will solve well formed dependency
+/// structures. It'll detect dependency cycles but it will not help find what
+/// caused the cycle or provide any attempt at a best guess for order in cyclic
+/// scenarios. Use this as a best case first run and fall back to a more complex
+/// solver if this one finds a cycle.
+class DependencySorter> {
+ HashSet _perm;
+ HashSet _temp;
+ List _order;
+
+ DependencySorter() {
+ _perm = HashSet();
+ _temp = HashSet();
+ }
+
+ List sort(T root) {
+ _order = [];
+ if (!visit(root)) {
+ return null;
+ }
+ return _order;
+ }
+
+ bool visit(T n) {
+ if (_perm.contains(n)) {
+ return true;
+ }
+ if (_temp.contains(n)) {
+ // cycle detected!
+ return false;
+ }
+
+ _temp.add(n);
+
+ Set dependents = n.dependents;
+ if (dependents != null) {
+ for (final T d in dependents) {
+ if (!visit(d)) {
+ return false;
+ }
+ }
+ }
+ _perm.add(n);
+ _order.insert(0, n);
+
+ return true;
+ }
+}
+
+/// Sorts dependencies for Actors even when cycles are present
+///
+/// Any nodes that form part of a cycle can be found in `cycleNodes` after
+/// `sort`. NOTE: Nodes isolated by cycles will not be found in `_order` or
+/// `cycleNodes` e.g. `A -> B <-> C -> D` isolates D when running a sort based
+/// on A
+class TarjansDependencySorter>
+ extends DependencySorter {
+ HashSet _cycleNodes;
+ TarjansDependencySorter() {
+ _perm = HashSet();
+ _temp = HashSet();
+ _cycleNodes = HashSet();
+ }
+
+ HashSet get cycleNodes => _cycleNodes;
+
+ @override
+ List sort(T root) {
+ _order = [];
+
+ if (!visit(root)) {
+ // if we detect cycles, go find them all
+ _perm.clear();
+ _temp.clear();
+ _cycleNodes.clear();
+ _order.clear();
+
+ var cycles =
+ stronglyConnectedComponents([root], (T node) => node.dependents);
+
+ cycles.forEach((cycle) {
+ // cycles of len 1 are not cycles.
+ if (cycle.length > 1) {
+ cycle.forEach((cycleMember) {
+ _cycleNodes.add(cycleMember);
+ });
+ }
+ });
+
+ // revisit the tree, skipping nodes on any cycle.
+ visit(root);
+ }
+
+ return _order;
+ }
+
+ @override
+ bool visit(T n) {
+ if (cycleNodes.contains(n)) {
+ // skip any nodes on a known cycle.
+ return true;
+ }
+
+ return super.visit(n);
+ }
+}
diff --git a/lib/src/utilities/tops.dart b/lib/src/utilities/tops.dart
new file mode 100644
index 0000000..5c2e617
--- /dev/null
+++ b/lib/src/utilities/tops.dart
@@ -0,0 +1,19 @@
+abstract class Parentable {
+ T get parent;
+}
+
+/// Get the top most components (any child that has an ancestor in the set
+/// should be pruned).
+Set tops>(Iterable parentables) {
+ var tips = {};
+ outerLoop:
+ for (final item in parentables) {
+ for (var parent = item.parent; parent != null; parent = parent.parent) {
+ if (parentables.contains(parent)) {
+ continue outerLoop;
+ }
+ }
+ tips.add(item);
+ }
+ return tips;
+}
diff --git a/pubspec.lock b/pubspec.lock
new file mode 100644
index 0000000..a26fcda
--- /dev/null
+++ b/pubspec.lock
@@ -0,0 +1,153 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.4.2"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.0"
+ charcode:
+ dependency: transitive
+ description:
+ name: charcode
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.3"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.14.13"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ graphs:
+ dependency: "direct main"
+ description:
+ name: graphs
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.8"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.8"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.7.0"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.7.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.9.5"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.5"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.17"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.8"
+sdks:
+ dart: ">=2.9.0-14.0.dev <3.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 0000000..e6f7f48
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,18 @@
+name: rive
+description: Rive Flutter Runtime
+version: 0.0.1
+author:
+
+environment:
+ sdk: ">=2.2.2 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ graphs: ^0.2.0
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+flutter:
\ No newline at end of file