├── .gitignore ├── .metadata ├── README.md ├── android ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── water_cellular_automata │ │ │ │ └── MainActivity.java │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── _src │ ├── button.psd │ └── icons.ai └── images │ ├── block.png │ ├── button_bottom.png │ ├── button_bottom_left.png │ ├── button_bottom_right.png │ ├── button_left.png │ ├── button_right.png │ ├── button_top.png │ ├── button_top_left.png │ ├── button_top_right.png │ ├── debug.png │ ├── flow_debug_icons │ ├── 00.png │ ├── 01.png │ ├── 02.png │ ├── 03.png │ ├── 04.png │ ├── 05.png │ ├── 06.png │ ├── 07.png │ ├── 08.png │ ├── 09.png │ ├── 10.png │ ├── 11.png │ ├── 12.png │ ├── 13.png │ ├── 14.png │ └── 15.png │ ├── liquid.png │ └── reset.png ├── ios ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ └── contents.xcworkspacedata └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── components │ ├── button.dart │ ├── cell.dart │ ├── fps_counter.dart │ ├── grid.dart │ └── liquid_simulator.dart ├── game_app.dart ├── input.dart ├── main.dart ├── palette.dart └── util │ ├── color_util.dart │ └── math_util.dart ├── pubspec.lock └── pubspec.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # Visual Studio Code related 19 | .vscode/ 20 | 21 | # Flutter/Dart/Pub related 22 | **/doc/api/ 23 | .dart_tool/ 24 | .flutter-plugins 25 | .packages 26 | .pub-cache/ 27 | .pub/ 28 | /build/ 29 | 30 | # Android related 31 | **/android/**/gradle-wrapper.jar 32 | **/android/.gradle 33 | **/android/captures/ 34 | **/android/gradlew 35 | **/android/gradlew.bat 36 | **/android/local.properties 37 | **/android/**/GeneratedPluginRegistrant.java 38 | 39 | # iOS/XCode related 40 | **/ios/**/*.mode1v3 41 | **/ios/**/*.mode2v3 42 | **/ios/**/*.moved-aside 43 | **/ios/**/*.pbxuser 44 | **/ios/**/*.perspectivev3 45 | **/ios/**/*sync/ 46 | **/ios/**/.sconsign.dblite 47 | **/ios/**/.tags* 48 | **/ios/**/.vagrant/ 49 | **/ios/**/DerivedData/ 50 | **/ios/**/Icon? 51 | **/ios/**/Pods/ 52 | **/ios/**/.symlinks/ 53 | **/ios/**/profile 54 | **/ios/**/xcuserdata 55 | **/ios/.generated/ 56 | **/ios/Flutter/App.framework 57 | **/ios/Flutter/Flutter.framework 58 | **/ios/Flutter/Generated.xcconfig 59 | **/ios/Flutter/app.flx 60 | **/ios/Flutter/app.zip 61 | **/ios/Flutter/flutter_assets/ 62 | **/ios/ServiceDefinitions.json 63 | **/ios/Runner/GeneratedPluginRegistrant.* 64 | 65 | # Exceptions to above rules. 66 | !**/ios/**/default.mode1v3 67 | !**/ios/**/default.mode2v3 68 | !**/ios/**/default.pbxuser 69 | !**/ios/**/default.perspectivev3 70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 71 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8661d8aecd626f7f57ccbcb735553edc05a2e713 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_fluid_cellular_automata 2 | 3 | An implementation of [this Unity3D fluid physics using cellular automata](http://www.jgallant.com/2d-liquid-simulator-with-cellular-automaton-in-unity/) in Flutter. This project uses the [Flame engine](https://github.com/luanpotter/flame) to function. On a Samsung Galaxy Note 9, this demo runs at a smooth 60 FPS. 4 | 5 | ![app demo](https://i.imgur.com/jsDtqrY.gif) -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.example.water_cellular_automata" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | testImplementation 'junit:junit:4.12' 59 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 61 | } 62 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 13 | 20 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/example/water_cellular_automata/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.water_cellular_automata; 2 | 3 | import android.os.Bundle; 4 | import io.flutter.app.FlutterActivity; 5 | import io.flutter.plugins.GeneratedPluginRegistrant; 6 | 7 | public class MainActivity extends FlutterActivity { 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | GeneratedPluginRegistrant.registerWith(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.2.1' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /assets/_src/button.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/_src/button.psd -------------------------------------------------------------------------------- /assets/_src/icons.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/_src/icons.ai -------------------------------------------------------------------------------- /assets/images/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/block.png -------------------------------------------------------------------------------- /assets/images/button_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_bottom.png -------------------------------------------------------------------------------- /assets/images/button_bottom_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_bottom_left.png -------------------------------------------------------------------------------- /assets/images/button_bottom_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_bottom_right.png -------------------------------------------------------------------------------- /assets/images/button_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_left.png -------------------------------------------------------------------------------- /assets/images/button_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_right.png -------------------------------------------------------------------------------- /assets/images/button_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_top.png -------------------------------------------------------------------------------- /assets/images/button_top_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_top_left.png -------------------------------------------------------------------------------- /assets/images/button_top_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/button_top_right.png -------------------------------------------------------------------------------- /assets/images/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/debug.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/00.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/01.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/02.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/03.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/04.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/05.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/06.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/07.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/08.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/09.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/10.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/11.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/12.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/13.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/14.png -------------------------------------------------------------------------------- /assets/images/flow_debug_icons/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/flow_debug_icons/15.png -------------------------------------------------------------------------------- /assets/images/liquid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/liquid.png -------------------------------------------------------------------------------- /assets/images/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/assets/images/reset.png -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 18 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 19 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 20 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = ""; 28 | dstSubfolderSpec = 10; 29 | files = ( 30 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 31 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 32 | ); 33 | name = "Embed Frameworks"; 34 | runOnlyForDeploymentPostprocessing = 0; 35 | }; 36 | /* End PBXCopyFilesBuildPhase section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 40 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 41 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 42 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 43 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 44 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 45 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 46 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 47 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 48 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 49 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 53 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 62 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 9740EEB11CF90186004384FC /* Flutter */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 3B80C3931E831B6300D905FE /* App.framework */, 73 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 74 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 75 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 76 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 77 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 78 | ); 79 | name = Flutter; 80 | sourceTree = ""; 81 | }; 82 | 97C146E51CF9000F007C117D = { 83 | isa = PBXGroup; 84 | children = ( 85 | 9740EEB11CF90186004384FC /* Flutter */, 86 | 97C146F01CF9000F007C117D /* Runner */, 87 | 97C146EF1CF9000F007C117D /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | 97C146EF1CF9000F007C117D /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 97C146EE1CF9000F007C117D /* Runner.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 97C146F01CF9000F007C117D /* Runner */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 103 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 104 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 105 | 97C147021CF9000F007C117D /* Info.plist */, 106 | 97C146F11CF9000F007C117D /* Supporting Files */, 107 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 108 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 109 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 110 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 111 | ); 112 | path = Runner; 113 | sourceTree = ""; 114 | }; 115 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | ); 119 | name = "Supporting Files"; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 97C146ED1CF9000F007C117D /* Runner */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 128 | buildPhases = ( 129 | 9740EEB61CF901F6004384FC /* Run Script */, 130 | 97C146EA1CF9000F007C117D /* Sources */, 131 | 97C146EB1CF9000F007C117D /* Frameworks */, 132 | 97C146EC1CF9000F007C117D /* Resources */, 133 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 134 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 135 | ); 136 | buildRules = ( 137 | ); 138 | dependencies = ( 139 | ); 140 | name = Runner; 141 | productName = Runner; 142 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 143 | productType = "com.apple.product-type.application"; 144 | }; 145 | /* End PBXNativeTarget section */ 146 | 147 | /* Begin PBXProject section */ 148 | 97C146E61CF9000F007C117D /* Project object */ = { 149 | isa = PBXProject; 150 | attributes = { 151 | LastUpgradeCheck = 0910; 152 | ORGANIZATIONNAME = "The Chromium Authors"; 153 | TargetAttributes = { 154 | 97C146ED1CF9000F007C117D = { 155 | CreatedOnToolsVersion = 7.3.1; 156 | LastSwiftMigration = 0910; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 161 | compatibilityVersion = "Xcode 3.2"; 162 | developmentRegion = English; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 97C146E51CF9000F007C117D; 169 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 170 | projectDirPath = ""; 171 | projectRoot = ""; 172 | targets = ( 173 | 97C146ED1CF9000F007C117D /* Runner */, 174 | ); 175 | }; 176 | /* End PBXProject section */ 177 | 178 | /* Begin PBXResourcesBuildPhase section */ 179 | 97C146EC1CF9000F007C117D /* Resources */ = { 180 | isa = PBXResourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 184 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 185 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 186 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 187 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXResourcesBuildPhase section */ 192 | 193 | /* Begin PBXShellScriptBuildPhase section */ 194 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 195 | isa = PBXShellScriptBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | inputPaths = ( 200 | ); 201 | name = "Thin Binary"; 202 | outputPaths = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; 207 | }; 208 | 9740EEB61CF901F6004384FC /* Run Script */ = { 209 | isa = PBXShellScriptBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | ); 213 | inputPaths = ( 214 | ); 215 | name = "Run Script"; 216 | outputPaths = ( 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | shellPath = /bin/sh; 220 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 221 | }; 222 | /* End PBXShellScriptBuildPhase section */ 223 | 224 | /* Begin PBXSourcesBuildPhase section */ 225 | 97C146EA1CF9000F007C117D /* Sources */ = { 226 | isa = PBXSourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 230 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | /* End PBXSourcesBuildPhase section */ 235 | 236 | /* Begin PBXVariantGroup section */ 237 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | 97C146FB1CF9000F007C117D /* Base */, 241 | ); 242 | name = Main.storyboard; 243 | sourceTree = ""; 244 | }; 245 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 97C147001CF9000F007C117D /* Base */, 249 | ); 250 | name = LaunchScreen.storyboard; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 257 | isa = XCBuildConfiguration; 258 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_COMMA = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INFINITE_RECURSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 276 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 279 | CLANG_WARN_STRICT_PROTOTYPES = YES; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_NS_ASSERTIONS = NO; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | SDKROOT = iphoneos; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | VALIDATE_PRODUCT = YES; 301 | }; 302 | name = Profile; 303 | }; 304 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 305 | isa = XCBuildConfiguration; 306 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 307 | buildSettings = { 308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 309 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 310 | DEVELOPMENT_TEAM = S8QB4VV633; 311 | ENABLE_BITCODE = NO; 312 | FRAMEWORK_SEARCH_PATHS = ( 313 | "$(inherited)", 314 | "$(PROJECT_DIR)/Flutter", 315 | ); 316 | INFOPLIST_FILE = Runner/Info.plist; 317 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 318 | LIBRARY_SEARCH_PATHS = ( 319 | "$(inherited)", 320 | "$(PROJECT_DIR)/Flutter", 321 | ); 322 | PRODUCT_BUNDLE_IDENTIFIER = com.example.waterCellularAutomata; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | SWIFT_VERSION = 4.0; 325 | VERSIONING_SYSTEM = "apple-generic"; 326 | }; 327 | name = Profile; 328 | }; 329 | 97C147031CF9000F007C117D /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 332 | buildSettings = { 333 | ALWAYS_SEARCH_USER_PATHS = NO; 334 | CLANG_ANALYZER_NONNULL = YES; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 376 | MTL_ENABLE_DEBUG_INFO = YES; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Debug; 382 | }; 383 | 97C147041CF9000F007C117D /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 386 | buildSettings = { 387 | ALWAYS_SEARCH_USER_PATHS = NO; 388 | CLANG_ANALYZER_NONNULL = YES; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_COMMA = YES; 396 | CLANG_WARN_CONSTANT_CONVERSION = YES; 397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 398 | CLANG_WARN_EMPTY_BODY = YES; 399 | CLANG_WARN_ENUM_CONVERSION = YES; 400 | CLANG_WARN_INFINITE_RECURSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 404 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 405 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 406 | CLANG_WARN_STRICT_PROTOTYPES = YES; 407 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 413 | ENABLE_NS_ASSERTIONS = NO; 414 | ENABLE_STRICT_OBJC_MSGSEND = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_NO_COMMON_BLOCKS = YES; 417 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 418 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 419 | GCC_WARN_UNDECLARED_SELECTOR = YES; 420 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 421 | GCC_WARN_UNUSED_FUNCTION = YES; 422 | GCC_WARN_UNUSED_VARIABLE = YES; 423 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 424 | MTL_ENABLE_DEBUG_INFO = NO; 425 | SDKROOT = iphoneos; 426 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 427 | TARGETED_DEVICE_FAMILY = "1,2"; 428 | VALIDATE_PRODUCT = YES; 429 | }; 430 | name = Release; 431 | }; 432 | 97C147061CF9000F007C117D /* Debug */ = { 433 | isa = XCBuildConfiguration; 434 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 435 | buildSettings = { 436 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 437 | CLANG_ENABLE_MODULES = YES; 438 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 439 | ENABLE_BITCODE = NO; 440 | FRAMEWORK_SEARCH_PATHS = ( 441 | "$(inherited)", 442 | "$(PROJECT_DIR)/Flutter", 443 | ); 444 | INFOPLIST_FILE = Runner/Info.plist; 445 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 446 | LIBRARY_SEARCH_PATHS = ( 447 | "$(inherited)", 448 | "$(PROJECT_DIR)/Flutter", 449 | ); 450 | PRODUCT_BUNDLE_IDENTIFIER = com.example.waterCellularAutomata; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 453 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 454 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 455 | SWIFT_VERSION = 4.0; 456 | VERSIONING_SYSTEM = "apple-generic"; 457 | }; 458 | name = Debug; 459 | }; 460 | 97C147071CF9000F007C117D /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 463 | buildSettings = { 464 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 465 | CLANG_ENABLE_MODULES = YES; 466 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 467 | ENABLE_BITCODE = NO; 468 | FRAMEWORK_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "$(PROJECT_DIR)/Flutter", 471 | ); 472 | INFOPLIST_FILE = Runner/Info.plist; 473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 474 | LIBRARY_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "$(PROJECT_DIR)/Flutter", 477 | ); 478 | PRODUCT_BUNDLE_IDENTIFIER = com.example.waterCellularAutomata; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 481 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 482 | SWIFT_VERSION = 4.0; 483 | VERSIONING_SYSTEM = "apple-generic"; 484 | }; 485 | name = Release; 486 | }; 487 | /* End XCBuildConfiguration section */ 488 | 489 | /* Begin XCConfigurationList section */ 490 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 491 | isa = XCConfigurationList; 492 | buildConfigurations = ( 493 | 97C147031CF9000F007C117D /* Debug */, 494 | 97C147041CF9000F007C117D /* Release */, 495 | 249021D3217E4FDB00AE95B9 /* Profile */, 496 | ); 497 | defaultConfigurationIsVisible = 0; 498 | defaultConfigurationName = Release; 499 | }; 500 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 501 | isa = XCConfigurationList; 502 | buildConfigurations = ( 503 | 97C147061CF9000F007C117D /* Debug */, 504 | 97C147071CF9000F007C117D /* Release */, 505 | 249021D4217E4FDB00AE95B9 /* Profile */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | /* End XCConfigurationList section */ 511 | 512 | }; 513 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 514 | } 515 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewackerman/flutter_fluid_cellular_automata/9f099f11a06238f2c06661414c9a0bf363291a54/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | 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. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | water_cellular_automata 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/components/button.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'dart:math' as Math; 3 | 4 | import 'package:flame/components/component.dart'; 5 | import 'package:flame/palette.dart'; 6 | import 'package:flame/sprite.dart'; 7 | import 'package:water_cellular_automata/input.dart'; 8 | 9 | class Button extends PositionComponent { 10 | Sprite icon; 11 | ButtonRenderData renderData; 12 | void Function() callback; 13 | 14 | Button({ 15 | double x, 16 | double y, 17 | double width, 18 | double height, 19 | String iconPath, 20 | this.renderData, 21 | this.callback, 22 | }) : this.icon = Sprite(iconPath) { 23 | this.x = x; 24 | this.y = y; 25 | this.width = width; 26 | this.height = height; 27 | } 28 | 29 | bool _isPressed = false; 30 | bool _wasPressed = false; 31 | 32 | @override 33 | void update(double dt) { 34 | _isPressed = Input.isTapDown && this.toRect().contains(Input.position.toOffset()); 35 | 36 | if (_isPressed && !_wasPressed) { 37 | if (callback != null) { 38 | callback(); 39 | } 40 | } 41 | } 42 | 43 | @override 44 | void render(Canvas c) { 45 | if (renderData.size == null) { 46 | renderData.recalculateBounds(); 47 | if (renderData.size == null) { 48 | return; 49 | } 50 | } 51 | 52 | final rx = this.width / renderData.size.width; 53 | final ry = this.height / renderData.size.height; 54 | 55 | // Button Border 56 | double x, y, w, h; 57 | 58 | // Top-Left 59 | x = this.x; 60 | y = this.y; 61 | w = renderData.topLeft.size.x * rx; 62 | h = renderData.topLeft.size.y * ry; 63 | renderData.topLeft.renderRect(c, Rect.fromLTWH(x, y, w, h)); 64 | 65 | // Top 66 | x = x + w; 67 | y = y; 68 | w = renderData.top.size.x * rx; 69 | h = renderData.top.size.y * ry; 70 | renderData.top.renderRect(c, Rect.fromLTWH(x, y, w, h)); 71 | 72 | // Top-Right 73 | x = x + w; 74 | y = y; 75 | w = renderData.topRight.size.x * rx; 76 | h = renderData.topRight.size.y * ry; 77 | renderData.topRight.renderRect(c, Rect.fromLTWH(x, y, w, h)); 78 | 79 | // Left 80 | x = this.x; 81 | y = y + h; 82 | w = renderData.left.size.x * rx; 83 | h = renderData.left.size.y * ry; 84 | renderData.left.renderRect(c, Rect.fromLTWH(x, y, w, h)); 85 | 86 | // Right 87 | y = y; 88 | w = renderData.right.size.x * rx; 89 | h = renderData.right.size.y * ry; 90 | x = this.x + (this.width - w); 91 | renderData.right.renderRect(c, Rect.fromLTWH(x, y, w, h)); 92 | 93 | // Bottom-Left 94 | x = this.x; 95 | y = y + h; 96 | w = renderData.bottomLeft.size.x * rx; 97 | h = renderData.bottomLeft.size.y * ry; 98 | renderData.bottomLeft.renderRect(c, Rect.fromLTWH(x, y, w, h)); 99 | 100 | // Top 101 | x = x + w; 102 | y = y; 103 | w = renderData.bottom.size.x * rx; 104 | h = renderData.bottom.size.y * ry; 105 | renderData.bottom.renderRect(c, Rect.fromLTWH(x, y, w, h)); 106 | 107 | // Top-Right 108 | x = x + w; 109 | y = y; 110 | w = renderData.bottomRight.size.x * rx; 111 | h = renderData.bottomRight.size.y * ry; 112 | renderData.bottomRight.renderRect(c, Rect.fromLTWH(x, y, w, h)); 113 | 114 | // Background 115 | final paint = renderData.background.paint; 116 | final bgX = this.x + (renderData.topLeft.size.x * rx); 117 | final bgY = this.y + (renderData.topLeft.size.y * ry); 118 | final bgW = this.width - (renderData.left.size.x * rx) - (renderData.right.size.x * rx); 119 | final bgH = this.height - (renderData.top.size.y * ry) - (renderData.bottom.size.y * ry); 120 | 121 | c.drawRect(Rect.fromLTWH(bgX, bgY, bgW, bgH), paint); 122 | 123 | // Icon 124 | if (icon.loaded()) { 125 | icon.renderRect(c, Rect.fromLTWH(bgX, bgY, bgW, bgH)); 126 | } 127 | } 128 | 129 | } 130 | 131 | class ButtonRenderData { 132 | Sprite topLeft; 133 | Sprite top; 134 | Sprite topRight; 135 | Sprite left; 136 | Sprite right; 137 | Sprite bottomLeft; 138 | Sprite bottom; 139 | Sprite bottomRight; 140 | PaletteEntry background; 141 | 142 | ButtonRenderData({ 143 | this.topLeft, 144 | this.top, 145 | this.topRight, 146 | this.left, 147 | this.right, 148 | this.bottomLeft, 149 | this.bottom, 150 | this.bottomRight, 151 | this.background, 152 | }); 153 | 154 | Size _size; 155 | Size get size => _size; 156 | 157 | void setBackground(Color color) => background = PaletteEntry(color); 158 | void setTopLeft(String filename) => topLeft = Sprite(filename); 159 | void setTop(String filename) => top = Sprite(filename); 160 | void setTopRight(String filename) => topRight = Sprite(filename); 161 | void setLeft(String filename) => left = Sprite(filename); 162 | void setRight(String filename) => right = Sprite(filename); 163 | void setBottomLeft(String filename) => bottomLeft = Sprite(filename); 164 | void setBottom(String filename) => bottom = Sprite(filename); 165 | void setBottomRight(String filename) => bottomRight = Sprite(filename); 166 | 167 | bool sizeAvailable() { 168 | return topLeft != null && topLeft.loaded() && 169 | top != null && top.loaded() && 170 | topRight != null && topRight.loaded() && 171 | left != null && left.loaded() && 172 | right != null && right.loaded() && 173 | bottomLeft != null && bottomLeft.loaded() && 174 | bottom != null && bottom.loaded() && 175 | bottomRight != null && bottomRight.loaded(); 176 | } 177 | 178 | void recalculateBounds() async { 179 | if (!sizeAvailable()) { 180 | _size = null; 181 | return; 182 | } 183 | 184 | double width = Math.max(Math.max(topLeft.size.x, left.size.x), bottomLeft.size.x) + Math.max(top.size.x, bottom.size.x) + Math.max(Math.max(topRight.size.x, right.size.x), bottomRight.size.x); 185 | double height = Math.max(Math.max(topLeft.size.y, top.size.y), topRight.size.y) + Math.max(left.size.y, right.size.y) + Math.max(Math.max(bottomLeft.size.y, bottom.size.y), bottomRight.size.y); 186 | _size = Size(width, height); 187 | } 188 | } -------------------------------------------------------------------------------- /lib/components/cell.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'dart:math' as Math; 3 | 4 | import 'package:flame/components/component.dart'; 5 | import 'package:flame/position.dart'; 6 | import 'package:flame/sprite.dart'; 7 | import 'package:water_cellular_automata/palette.dart'; 8 | import 'package:water_cellular_automata/util/color_util.dart'; 9 | 10 | class Cell { 11 | int x = 0; 12 | int y = 0; 13 | Position position = Position.empty(); 14 | double cellSize = 0; 15 | CellType type = CellType.blank; 16 | bool showFlow = false; 17 | bool renderDownFlowingLiquid = false; 18 | bool renderFloatingLiquid = false; 19 | List flowSprites; 20 | 21 | double liquid = 0; 22 | 23 | int settleCount = 0; 24 | 25 | bool _settled; 26 | bool get settled => _settled; 27 | set settled(bool value) { 28 | _settled = value; 29 | if (!_settled) { 30 | settleCount = 0; 31 | } 32 | } 33 | 34 | int bitMask = 0; 35 | List flowDirections = [false, false, false, false]; 36 | double localScaleY = 1; 37 | 38 | Cell left; 39 | Cell top; 40 | Cell right; 41 | Cell bottom; 42 | 43 | Color color; 44 | 45 | Cell() { 46 | color = Palette.waterLight.color; 47 | } 48 | 49 | void set({ 50 | int x, 51 | int y, 52 | Position position, 53 | double cellSize, 54 | CellType type, 55 | bool showFlow, 56 | List flowSprites, 57 | bool renderDownFlowingLiquid, 58 | bool renderFloatingLiquid, 59 | }) { 60 | if (x != null) this.x = x; 61 | if (y != null) this.y = y; 62 | if (position != null) this.position = position; 63 | if (cellSize != null) this.cellSize = cellSize; 64 | if (type != null) this.type = type; 65 | if (showFlow != null) this.showFlow = showFlow; 66 | if (flowSprites != null) this.flowSprites = flowSprites; 67 | if (renderDownFlowingLiquid != null) this.renderDownFlowingLiquid = renderDownFlowingLiquid; 68 | if (renderFloatingLiquid != null) this.renderFloatingLiquid = renderFloatingLiquid; 69 | } 70 | 71 | void setType(CellType type) { 72 | this.type = type; 73 | if (type == CellType.solid) { 74 | liquid = 0; 75 | } 76 | 77 | unsettleNeighbors(); 78 | } 79 | 80 | void addLiquid(double amount) { 81 | liquid += amount; 82 | settled = false; 83 | } 84 | 85 | void resetFlowDirections() { 86 | flowDirections = [false, false, false, false]; 87 | } 88 | 89 | void unsettleNeighbors() { 90 | if (top != null) top.settled = false; 91 | if (bottom != null) bottom.settled = false; 92 | if (left != null) left.settled = false; 93 | if (right != null) right.settled = false; 94 | } 95 | 96 | Rect getBounds() { 97 | return Rect.fromLTWH(position.x, position.y, cellSize, cellSize); 98 | } 99 | 100 | void update(double dt) { 101 | if (type == CellType.solid) return; 102 | 103 | bitMask = 0; 104 | if (flowDirections[FlowDirection.top]) bitMask += 1; 105 | if (flowDirections[FlowDirection.right]) bitMask += 2; 106 | if (flowDirections[FlowDirection.bottom]) bitMask += 4; 107 | if (flowDirections[FlowDirection.left]) bitMask += 8; 108 | 109 | localScaleY = Math.min(liquid, 1); 110 | 111 | if (!renderFloatingLiquid) { 112 | if (bottom != null && bottom.type != CellType.solid && bottom.liquid < 1) { 113 | localScaleY = 0; 114 | } 115 | } 116 | 117 | if (renderDownFlowingLiquid) { 118 | if (type ==CellType.blank && top != null && (top.liquid > 0.01 || top.bitMask == 4)) { 119 | localScaleY = 1; 120 | } 121 | } 122 | 123 | color = lerpColor(Palette.waterLight.color, Palette.waterDark.color, liquid / 4); 124 | } 125 | 126 | void render(Canvas c) { 127 | if (type == CellType.solid) { 128 | c.drawRect(Rect.fromLTWH(position.x, position.y, cellSize, cellSize), Palette.solidTile.paint); 129 | } else if (liquid > 0) { 130 | 131 | if (!renderFloatingLiquid) { 132 | if (bottom != null && bottom.type != CellType.solid && bottom.liquid < 1) { 133 | return; 134 | } 135 | } 136 | 137 | final paint = Paint() 138 | ..color = color 139 | ..style = PaintingStyle.fill; 140 | 141 | final h = cellSize * localScaleY; 142 | final y = position.y + cellSize - h; 143 | 144 | final rect = Rect.fromLTWH(position.x, y, cellSize, h); 145 | c.drawRect(rect, paint); 146 | 147 | if (showFlow) { 148 | // print(flowSprites); 149 | final sprite = flowSprites[bitMask]; 150 | if (sprite.loaded()) { 151 | sprite.renderRect(c, rect); 152 | } 153 | } 154 | } 155 | } 156 | 157 | } 158 | 159 | enum CellType { 160 | blank, 161 | solid, 162 | } 163 | 164 | class FlowDirection { 165 | static const top = 0; 166 | static const right = 1; 167 | static const bottom = 2; 168 | static const left = 3; 169 | } 170 | -------------------------------------------------------------------------------- /lib/components/fps_counter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flame/components/component.dart'; 4 | import 'package:flame/flame.dart'; 5 | import 'package:flutter/material.dart' as Material; 6 | 7 | class FpsCounter extends PositionComponent { 8 | static const _sampleCount = 20; 9 | 10 | List _samples; 11 | int _index = 0; 12 | 13 | double fontSize; 14 | double averageDt; 15 | 16 | FpsCounter(double x, double y, this.fontSize) { 17 | this.x = x; 18 | this.y = y; 19 | 20 | _samples = List.filled(_sampleCount, 0, growable: false); 21 | } 22 | 23 | @override 24 | void update(double dt) { 25 | _index = (_index + 1) % _sampleCount; 26 | _samples[_index] = dt; 27 | 28 | double total = 0; 29 | for (var sample in _samples) { 30 | total += sample; 31 | } 32 | 33 | averageDt = total / _samples.length; 34 | } 35 | 36 | @override 37 | void render(Canvas c) { 38 | prepareCanvas(c); 39 | 40 | final fps = 1 / averageDt; 41 | 42 | final builder = ParagraphBuilder(ParagraphStyle(fontSize: fontSize)) 43 | ..pushStyle(TextStyle(color: Material.Colors.black)) 44 | ..addText('FPS: ${fps.toStringAsFixed(2)}\nDelta: ${averageDt.toStringAsFixed(4)}ms'); 45 | 46 | final paragraph = builder.build(); 47 | paragraph.layout(ParagraphConstraints(width: 9999)); 48 | 49 | c.drawParagraph(paragraph, Offset(0, 0)); 50 | } 51 | } -------------------------------------------------------------------------------- /lib/components/grid.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flame/components/component.dart'; 4 | import 'package:flame/position.dart'; 5 | import 'package:flame/sprite.dart'; 6 | import 'package:water_cellular_automata/components/cell.dart'; 7 | import 'package:water_cellular_automata/components/liquid_simulator.dart'; 8 | import 'package:water_cellular_automata/input.dart'; 9 | import 'package:water_cellular_automata/palette.dart'; 10 | 11 | class Grid extends PositionComponent { 12 | static const gridWidth = 40; 13 | static const gridHeight = 60; 14 | 15 | double cellSize = 10; 16 | 17 | double lineWidth = 0.0; 18 | 19 | Color lineColor = Palette.gridLine.color; 20 | 21 | GridInputMode inputMode = GridInputMode.block; 22 | 23 | bool showFlow = true; 24 | bool renderDownFlowingLiquid = true; 25 | bool renderFloatingLiquid = true; 26 | 27 | LiquidSimulator simulator; 28 | List cells; 29 | List flowSprites; 30 | 31 | Cell getCell(int x, int y) => cells[y * gridWidth + x]; 32 | void setCell(int x, int y, Cell cell) => cells[y * gridWidth + x] = cell; 33 | 34 | Grid() { 35 | flowSprites = [ 36 | Sprite('flow_debug_icons/00.png'), 37 | Sprite('flow_debug_icons/01.png'), 38 | Sprite('flow_debug_icons/02.png'), 39 | Sprite('flow_debug_icons/03.png'), 40 | Sprite('flow_debug_icons/04.png'), 41 | Sprite('flow_debug_icons/05.png'), 42 | Sprite('flow_debug_icons/06.png'), 43 | Sprite('flow_debug_icons/07.png'), 44 | Sprite('flow_debug_icons/08.png'), 45 | Sprite('flow_debug_icons/09.png'), 46 | Sprite('flow_debug_icons/10.png'), 47 | Sprite('flow_debug_icons/11.png'), 48 | Sprite('flow_debug_icons/12.png'), 49 | Sprite('flow_debug_icons/13.png'), 50 | Sprite('flow_debug_icons/14.png'), 51 | Sprite('flow_debug_icons/15.png'), 52 | ]; 53 | 54 | createGrid(); 55 | 56 | simulator = LiquidSimulator(); 57 | simulator.initialize(cells); 58 | } 59 | 60 | void createGrid() { 61 | cells = List(gridWidth * gridHeight); 62 | 63 | width = gridWidth * cellSize; 64 | height = gridHeight * cellSize; 65 | 66 | double px, py; 67 | for (int x = 0; x < gridWidth; x++) { 68 | for (int y = 0; y < gridHeight; y++) { 69 | px = x * cellSize + this.x; 70 | py = y * cellSize + this.y; 71 | 72 | Cell cell = Cell() 73 | ..set( 74 | x: x, 75 | y: y, 76 | position: Position(px, py), 77 | cellSize: cellSize, 78 | showFlow: showFlow, 79 | flowSprites: flowSprites, 80 | renderDownFlowingLiquid: renderDownFlowingLiquid, 81 | renderFloatingLiquid: renderFloatingLiquid, 82 | ); 83 | 84 | if (x == 0 || y == 0 || x == gridWidth - 1 || y == gridHeight - 1) { 85 | cell.type = CellType.solid; 86 | } 87 | 88 | setCell(x, y, cell); 89 | } 90 | } 91 | 92 | updateNeighbors(); 93 | } 94 | 95 | void toggleFlowIcons() { 96 | showFlow = !showFlow; 97 | 98 | for (int x = 1; x < gridWidth - 1; x++) { 99 | for (int y = 1; y < gridHeight - 1; y++) { 100 | getCell(x, y).set(showFlow: showFlow); 101 | } 102 | } 103 | } 104 | 105 | void reset() { 106 | for (int x = 1; x < gridWidth - 1; x++) { 107 | for (int y = 1; y < gridHeight - 1; y++) { 108 | Cell cell = getCell(x, y); 109 | cell.addLiquid(-cell.liquid); 110 | cell.type = CellType.blank; 111 | } 112 | } 113 | } 114 | 115 | void refreshGrid() { 116 | double px, py; 117 | for (int x = 0; x < gridWidth; x++) { 118 | for (int y = 0; y < gridHeight; y++) { 119 | px = x * cellSize + this.x; 120 | py = y * cellSize + this.y; 121 | 122 | getCell(x, y).set( 123 | x: x, 124 | y: y, 125 | position: Position(px, py), 126 | showFlow: showFlow, 127 | renderDownFlowingLiquid: renderDownFlowingLiquid, 128 | renderFloatingLiquid: renderFloatingLiquid, 129 | ); 130 | } 131 | } 132 | } 133 | 134 | void updateNeighbors() { 135 | for (int x = 0; x < gridWidth; x++) { 136 | for (int y = 0; y < gridHeight; y++) { 137 | if (x > 0) { 138 | getCell(x, y).left = getCell(x-1, y); 139 | } 140 | if (x < gridWidth - 1) { 141 | getCell(x, y).right = getCell(x+1, y); 142 | } 143 | if (y > 0) { 144 | getCell(x, y).top = getCell(x, y-1); 145 | } 146 | if (y < gridHeight - 1) { 147 | getCell(x, y).bottom = getCell(x, y+1); 148 | } 149 | } 150 | } 151 | } 152 | 153 | @override 154 | void resize(Size size) { 155 | x = (size.width / 2) - (width / 2); 156 | y = (size.height / 2) - (height / 2); 157 | 158 | refreshGrid(); 159 | 160 | print('X: $x - Y: $y - Width: $width - Height: $height'); 161 | } 162 | 163 | CellType targetType; 164 | 165 | @override 166 | void update(double dt) { 167 | 168 | if (inputMode == GridInputMode.block) { 169 | if (Input.isDragging && this.toRect().contains(Input.position.toOffset())) { 170 | final pos = Input.position; 171 | var targetX = (pos.x - this.x).toInt() ~/ cellSize; 172 | var targetY = (pos.y - this.y).toInt() ~/ cellSize; 173 | 174 | if (targetX > 0 && targetX < gridWidth - 1 && targetY > 0 && targetY < gridHeight - 1) { 175 | Cell cell = getCell(targetX, targetY); 176 | 177 | if (!Input.wasDragging) { 178 | targetType = cell.type == CellType.solid ? CellType.blank : CellType.solid; 179 | } 180 | 181 | cell.type = targetType; 182 | } 183 | } 184 | } 185 | else if (inputMode == GridInputMode.liquid) { 186 | if (Input.isDragging && this.toRect().contains(Input.position.toOffset())) { 187 | final pos = Input.position; 188 | var targetX = (pos.x - this.x).toInt() ~/ cellSize; 189 | var targetY = (pos.y - this.y).toInt() ~/ cellSize; 190 | 191 | if (targetX > 0 && targetX < gridWidth - 1 && targetY > 0 && targetY < gridHeight - 1) { 192 | Cell cell = getCell(targetX, targetY); 193 | cell.addLiquid(5); 194 | } 195 | } 196 | } 197 | 198 | simulator.simulate(cells); 199 | cells.forEach((cell) => cell.update(dt)); 200 | } 201 | 202 | @override 203 | void render(Canvas c) { 204 | final gridPaint = Paint() 205 | ..color = lineColor 206 | ..style = PaintingStyle.stroke 207 | ..strokeWidth = lineWidth; 208 | 209 | double px, py; 210 | for (int x = 0; x < gridWidth; x++) { 211 | for (int y = 0; y < gridHeight; y++) { 212 | px = this.x + (x * cellSize); 213 | py = this.y + (y * cellSize); 214 | 215 | if (lineWidth > 0) { 216 | c.drawRect(Rect.fromLTWH(px, py, cellSize, cellSize), gridPaint); 217 | } 218 | } 219 | } 220 | 221 | cells.forEach((cell) => cell.render(c)); 222 | } 223 | 224 | } 225 | 226 | enum GridInputMode { 227 | block, 228 | liquid, 229 | } -------------------------------------------------------------------------------- /lib/components/liquid_simulator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | import 'dart:math' as Math; 3 | 4 | import 'package:water_cellular_automata/components/cell.dart'; 5 | import 'package:water_cellular_automata/components/grid.dart'; 6 | 7 | class LiquidSimulator { 8 | double minValue = 0.005; 9 | double maxValue = 1.0; 10 | 11 | double maxCompression = 0.25; 12 | 13 | double minFlow = 0.005; 14 | double maxFlow = 4; 15 | 16 | double flowSpeed = 1; 17 | 18 | List diffs; 19 | double getDiff(int x, int y) => diffs[y * Grid.gridWidth + x]; 20 | void setDiff(int x, int y, double value) => diffs[y * Grid.gridWidth + x] = value; 21 | 22 | void initialize(List cells) { 23 | diffs = List.filled(Grid.gridWidth * Grid.gridHeight, 0, growable: false); 24 | } 25 | 26 | double calculateVerticalFlowValue(double remainingLiquid, Cell destination) 27 | { 28 | double sum = remainingLiquid + destination.liquid; 29 | double value = 0; 30 | 31 | if (sum <= maxValue) { 32 | value = maxValue; 33 | } else if (sum < 2 * maxValue + maxCompression) { 34 | value = (maxValue * maxValue + sum * maxCompression) / (maxValue + maxCompression); 35 | } else { 36 | value = (sum + maxCompression) / 2; 37 | } 38 | 39 | return value; 40 | } 41 | 42 | void simulate(List cells) { 43 | Cell getCell(int x, int y) => cells[y * Grid.gridWidth + x]; 44 | 45 | double flow = 0; 46 | 47 | diffs = List.filled(Grid.gridWidth * Grid.gridHeight, 0, growable: false); 48 | 49 | for (int x = 0; x < Grid.gridWidth; x++) { 50 | for (int y = 0; y < Grid.gridHeight; y++) { 51 | Cell cell = getCell(x, y); 52 | cell.resetFlowDirections(); 53 | 54 | if (cell.type == CellType.solid) { 55 | cell.liquid = 0; 56 | continue; 57 | } 58 | if (cell.liquid == 0) { 59 | continue; 60 | } 61 | if (cell.settled) { 62 | continue; 63 | } 64 | if (cell.liquid < minValue) { 65 | cell.liquid = 0; 66 | continue; 67 | } 68 | 69 | final startValue = cell.liquid; 70 | double remainingValue = cell.liquid; 71 | flow = 0; 72 | 73 | // Flow to bottom cell 74 | if (cell.bottom != null && cell.bottom.type == CellType.blank) { 75 | // Determine rate of flow 76 | flow = calculateVerticalFlowValue(cell.liquid, cell.bottom) - cell.bottom.liquid; 77 | if (cell.bottom.liquid > 0 && flow > minFlow) { 78 | flow *= flowSpeed; 79 | } 80 | 81 | // Constrain flow 82 | flow = Math.max(flow, 0); 83 | if (flow > Math.min(maxFlow, remainingValue)) { 84 | flow = Math.min(maxFlow, remainingValue); 85 | } 86 | 87 | // Update temp values 88 | if (flow != 0) { 89 | remainingValue -= flow; 90 | setDiff(x, y, getDiff(x, y) - flow); 91 | setDiff(x, y+1, getDiff(x, y+1) + flow); 92 | cell.flowDirections[FlowDirection.bottom] = true; 93 | cell.bottom.settled = false; 94 | } 95 | } 96 | 97 | if (remainingValue < minValue) { 98 | setDiff(x, y, getDiff(x, y) - remainingValue); 99 | continue; 100 | } 101 | 102 | // Flow to left cell 103 | if (cell.left != null && cell.left.type == CellType.blank) { 104 | // Determine rate of flow 105 | flow = (remainingValue - cell.left.liquid) / 4; 106 | if (flow > minFlow) { 107 | flow *= flowSpeed; 108 | } 109 | 110 | // Constrain flow 111 | flow = Math.max(flow, 0); 112 | if (flow > Math.min(maxFlow, remainingValue)) { 113 | flow = Math.min(maxFlow, remainingValue); 114 | } 115 | 116 | // Update temp values 117 | if (flow != 0) { 118 | remainingValue -= flow; 119 | setDiff(x, y, getDiff(x, y) - flow); 120 | setDiff(x-1, y, getDiff(x-1, y) + flow); 121 | cell.flowDirections[FlowDirection.left] = true; 122 | cell.left.settled = false; 123 | } 124 | } 125 | 126 | if (remainingValue < minValue) { 127 | setDiff(x, y, getDiff(x, y) - remainingValue); 128 | continue; 129 | } 130 | 131 | // Flow to right cell 132 | if (cell.right != null && cell.right.type == CellType.blank) { 133 | // Determine rate of flow 134 | flow = (remainingValue - cell.right.liquid) / 4; 135 | if (flow > minFlow) { 136 | flow *= flowSpeed; 137 | } 138 | 139 | // Constrain flow 140 | flow = Math.max(flow, 0); 141 | if (flow > Math.min(maxFlow, remainingValue)) { 142 | flow = Math.min(maxFlow, remainingValue); 143 | } 144 | 145 | // Update temp values 146 | if (flow != 0) { 147 | remainingValue -= flow; 148 | setDiff(x, y, getDiff(x, y) - flow); 149 | setDiff(x+1, y, getDiff(x+1, y) + flow); 150 | cell.flowDirections[FlowDirection.right] = true; 151 | cell.right.settled = false; 152 | } 153 | } 154 | 155 | if (remainingValue < minValue) { 156 | setDiff(x, y, getDiff(x, y) - remainingValue); 157 | continue; 158 | } 159 | 160 | // Flow to top cell 161 | if (cell.top != null && cell.top.type == CellType.blank) { 162 | // Determine rate of flow 163 | flow = remainingValue - calculateVerticalFlowValue(remainingValue, cell.top); 164 | if (flow > minFlow) { 165 | flow *= flowSpeed; 166 | } 167 | 168 | // Constrain flow 169 | flow = Math.max(flow, 0); 170 | if (flow > Math.min(maxFlow, remainingValue)) { 171 | flow = Math.min(maxFlow, remainingValue); 172 | } 173 | 174 | // Update temp values 175 | if (flow != 0) { 176 | remainingValue -= flow; 177 | setDiff(x, y, getDiff(x, y) - flow); 178 | setDiff(x, y-1, getDiff(x, y-1) + flow); 179 | cell.flowDirections[FlowDirection.top] = true; 180 | cell.top.settled = false; 181 | } 182 | } 183 | 184 | if (remainingValue < minValue) { 185 | setDiff(x, y, getDiff(x, y) - remainingValue); 186 | continue; 187 | } 188 | 189 | // Check if cell is settled 190 | if (startValue == remainingValue) { 191 | cell.settleCount++; 192 | if (cell.settleCount >= 10) { 193 | cell.resetFlowDirections(); 194 | cell.settled = true; 195 | } 196 | } else { 197 | cell.unsettleNeighbors(); 198 | } 199 | } 200 | } 201 | 202 | // Update cell values 203 | for (int x = 0; x < Grid.gridWidth; x++) { 204 | for (int y = 0; y < Grid.gridHeight; y++) { 205 | Cell cell = getCell(x, y); 206 | cell.liquid += getDiff(x, y); 207 | if (cell.liquid < minValue) { 208 | cell.liquid = 0; 209 | cell.settled = false; 210 | } 211 | } 212 | } 213 | } 214 | 215 | } -------------------------------------------------------------------------------- /lib/game_app.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as Math; 2 | import 'dart:ui'; 3 | 4 | import 'package:flame/anchor.dart'; 5 | import 'package:flame/components/component.dart'; 6 | import 'package:flame/game.dart'; 7 | import 'package:flame/palette.dart'; 8 | import 'package:flutter/material.dart'; 9 | import 'package:water_cellular_automata/components/button.dart'; 10 | import 'package:water_cellular_automata/components/fps_counter.dart'; 11 | import 'package:water_cellular_automata/components/grid.dart'; 12 | import 'package:water_cellular_automata/input.dart'; 13 | 14 | class GameApp extends BaseGame { 15 | Size size; 16 | 17 | Grid grid; 18 | 19 | GameApp() { 20 | add(Input.getInstance()); 21 | add(FpsCounter(5, 25, 22)); 22 | 23 | grid = Grid(); 24 | add(grid); 25 | 26 | final buttonSize = 40.0; 27 | final buttonData = ButtonRenderData() 28 | ..setBackground(Color(0xFFB2B2B2)) 29 | ..setTopLeft('button_top_left.png') 30 | ..setTop('button_top.png') 31 | ..setTopRight('button_top_right.png') 32 | ..setLeft('button_left.png') 33 | ..setRight('button_right.png') 34 | ..setBottomLeft('button_bottom_left.png') 35 | ..setBottom('button_bottom.png') 36 | ..setBottomRight('button_bottom_right.png'); 37 | 38 | final blockButton = Button( 39 | x: 280, 40 | y: 20, 41 | width: buttonSize, 42 | height: buttonSize, 43 | iconPath: 'block.png', 44 | renderData: buttonData, 45 | callback: () => grid.inputMode = GridInputMode.block, 46 | ); 47 | 48 | final liquidButton = Button( 49 | x: 330, 50 | y: 20, 51 | width: buttonSize, 52 | height: buttonSize, 53 | iconPath: 'liquid.png', 54 | renderData: buttonData, 55 | callback: () => grid.inputMode = GridInputMode.liquid, 56 | ); 57 | 58 | final debugButton = Button( 59 | x: 280, 60 | y: 70, 61 | width: buttonSize, 62 | height: buttonSize, 63 | iconPath: 'debug.png', 64 | renderData: buttonData, 65 | callback: () => grid.toggleFlowIcons(), 66 | ); 67 | 68 | final resetButton = Button( 69 | x: 330, 70 | y: 70, 71 | width: buttonSize, 72 | height: buttonSize, 73 | iconPath: 'reset.png', 74 | renderData: buttonData, 75 | callback: () => grid.reset(), 76 | ); 77 | 78 | add(blockButton); 79 | add(liquidButton); 80 | add(debugButton); 81 | add(resetButton); 82 | } 83 | 84 | @override 85 | void resize(Size size) { 86 | super.resize(size); 87 | this.size = size; 88 | } 89 | 90 | @override 91 | void render(Canvas c) { 92 | c.drawPaint(BasicPalette.white.paint); 93 | super.render(c); 94 | } 95 | } 96 | 97 | // class Cell extends PositionComponent { 98 | // static const speed = 2; 99 | 100 | // double x; 101 | // double y; 102 | 103 | // Cell({ 104 | // @required double size, 105 | // this.x = 0, 106 | // this.y = 0, 107 | // }) { 108 | // width = height = size; 109 | // } 110 | 111 | // @override 112 | // void resize(Size size) { 113 | // x = size.width / 2; 114 | // y = size.height / 2; 115 | // anchor = Anchor.center; 116 | // } 117 | 118 | // @override 119 | // void update(double dt) { 120 | // angle += dt * speed; 121 | // angle %= 2 * Math.pi; 122 | // } 123 | 124 | // @override 125 | // void render(Canvas c) { 126 | // prepareCanvas(c); 127 | 128 | // c.drawRect(Rect.fromLTWH(0, 0, width, height), BasicPalette.white.paint); 129 | // } 130 | // } -------------------------------------------------------------------------------- /lib/input.dart: -------------------------------------------------------------------------------- 1 | import 'package:flame/components/component.dart'; 2 | import 'package:flame/flame.dart'; 3 | import 'package:flame/position.dart'; 4 | import 'package:flutter/gestures.dart'; 5 | 6 | const double _defaultTapThreshold = 200000; 7 | 8 | class Input extends Component { 9 | static Input _instance; 10 | static Input getInstance() { 11 | if (_instance == null) { 12 | _instance = Input(); 13 | } 14 | 15 | return _instance; 16 | } 17 | 18 | static void bindListeners() => _instance._bindListeners(); 19 | void _bindListeners() { 20 | final dragger = PanGestureRecognizer() 21 | ..onStart = _instance._onDragStart 22 | ..onUpdate = _instance._onDragUpdate 23 | ..onEnd = _instance._onDragEnd 24 | ..onDown = _instance._onDragDown 25 | ..onCancel = _instance._onDragCancel; 26 | 27 | Flame.util.addGestureRecognizer(dragger); 28 | } 29 | 30 | static void setTapThreshold(double timeInMilliseconds) => _instance._setTapThreshold(timeInMilliseconds); 31 | void _setTapThreshold(double timeInMilliseconds) { 32 | _tapThreshold = timeInMilliseconds * 1000; 33 | } 34 | 35 | static void setDebugMode(bool debug) => _instance._setDebugMode(debug); 36 | void _setDebugMode(bool debug) { 37 | _debugMode = debug; 38 | } 39 | 40 | static bool wasComponentTapped(PositionComponent component) => _instance._wasComponentTapped(component); 41 | bool _wasComponentTapped(PositionComponent component) { 42 | return _wasTapped && component.toRect().contains(_position.toOffset()); 43 | } 44 | 45 | double _tapThreshold = _defaultTapThreshold; 46 | bool _debugMode = false; 47 | 48 | bool _isTapDown = false; 49 | bool _wasTapDown = false; 50 | 51 | bool _isTapUp = false; 52 | bool _wasTapUp = false; 53 | 54 | bool _wasTapped = false; 55 | 56 | bool _isDragging = false; 57 | bool _wasDragging = false; 58 | 59 | Position _position; 60 | Offset _dragOffset; 61 | 62 | static bool get isTapDown => _instance._isTapDown; 63 | static bool get wasTapDown => _instance._wasTapDown; 64 | 65 | static bool get isTapUp => _instance._isTapUp; 66 | static bool get wasTapUp => _instance._wasTapUp; 67 | 68 | static bool get wasTapped => _instance._wasTapped; 69 | 70 | static bool get isDragging => _instance._isDragging; 71 | static bool get wasDragging => _instance._wasDragging; 72 | 73 | static Position get position => _instance._position; 74 | static Offset get dragOffset => _instance._dragOffset; 75 | 76 | bool _inputWasGestureDown = false; 77 | bool _inputWasGestureUp = false; 78 | bool _inputIsDragging = false; 79 | Position _inputPosition; 80 | Offset _inputOffset; 81 | bool _inputChanged = false; 82 | double _inputDownTimeStamp = 0; 83 | double _inputUpTimeStamp = 0; 84 | 85 | void _onDragDown(DragDownDetails d) { 86 | _inputWasGestureDown = true; 87 | _inputPosition = Position(d.globalPosition.dx, d.globalPosition.dy); 88 | _inputDownTimeStamp = DateTime.now().microsecondsSinceEpoch.toDouble(); 89 | _inputChanged = true; 90 | } 91 | 92 | void _onDragStart(DragStartDetails d) { 93 | _inputIsDragging = true; 94 | _inputPosition = Position(d.globalPosition.dx, d.globalPosition.dy); 95 | _inputChanged = true; 96 | } 97 | 98 | void _onDragUpdate(DragUpdateDetails d) { 99 | _inputPosition = Position(d.globalPosition.dx, d.globalPosition.dy); 100 | _inputOffset = d.delta; 101 | _inputChanged = true; 102 | } 103 | 104 | void _onDragEnd(DragEndDetails d) { 105 | _inputUpTimeStamp = DateTime.now().microsecondsSinceEpoch.toDouble(); 106 | _inputWasGestureUp = true; 107 | _inputIsDragging = false; 108 | _inputChanged = true; 109 | } 110 | 111 | void _onDragCancel() { 112 | _inputUpTimeStamp = DateTime.now().microsecondsSinceEpoch.toDouble(); 113 | _inputWasGestureUp = true; 114 | _inputIsDragging = false; 115 | _inputChanged = true; 116 | } 117 | 118 | @override 119 | void update(double dt) { 120 | // Tap Down 121 | _wasTapDown =_isTapDown; 122 | _isTapDown = _inputWasGestureDown; 123 | _inputWasGestureDown = false; 124 | 125 | // Tap Up 126 | _wasTapUp =_isTapUp; 127 | _isTapUp = _inputWasGestureUp; 128 | _inputWasGestureUp = false; 129 | 130 | // Dragging 131 | _wasDragging = _isDragging; 132 | _isDragging = _inputIsDragging; 133 | 134 | // Tapped 135 | _wasTapped = _isTapUp && !_wasTapUp && (!_wasDragging || (_inputUpTimeStamp > _inputDownTimeStamp && _inputUpTimeStamp - _inputDownTimeStamp < _tapThreshold)); 136 | 137 | // Position 138 | _position = _inputPosition; 139 | 140 | // Offset 141 | _dragOffset = _inputOffset; 142 | _inputOffset = Offset.zero; 143 | 144 | // Debug 145 | if (_debugMode && _inputChanged) { 146 | print({ 147 | 'isTapDown': isTapDown, 148 | 'wasTapDown': wasTapDown, 149 | 'isTapUp': isTapUp, 150 | 'wasTapUp': wasTapUp, 151 | 'wasTapped': wasTapped, 152 | 'isDragging': isDragging, 153 | 'wasDragging': wasDragging, 154 | 'position': position, 155 | 'offset': dragOffset, 156 | }); 157 | 158 | _inputChanged = false; 159 | } 160 | } 161 | 162 | @override render(c) {} 163 | } -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flame/flame.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | 6 | import 'package:water_cellular_automata/game_app.dart'; 7 | import 'package:water_cellular_automata/input.dart'; 8 | 9 | void main() async { 10 | await Flame.util.fullScreen(); 11 | await Flame.util.setOrientation(DeviceOrientation.portraitUp); 12 | 13 | final game = GameApp(); 14 | runApp(game.widget); 15 | 16 | Input.bindListeners(); 17 | } -------------------------------------------------------------------------------- /lib/palette.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flame/palette.dart'; 4 | 5 | class Palette { 6 | static const white = BasicPalette.white; 7 | static const gridLine = PaletteEntry(Color(0x80808080)); 8 | 9 | static const solidTile =PaletteEntry(Color(0xFF654321)); 10 | static const waterLight = PaletteEntry(Color(0xFF0CA4FF)); 11 | static const waterDark = PaletteEntry(Color(0xFF004772)); 12 | } -------------------------------------------------------------------------------- /lib/util/color_util.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:water_cellular_automata/util/math_util.dart'; 4 | 5 | lerpColor(Color a, Color b, double t) { 6 | final alpha = (lerp(a.alpha / 255, b.alpha / 255, t) * 255).toInt().clamp(0, 255); 7 | final red = (lerp(a.red / 255, b.red / 255, t) * 255).toInt().clamp(0, 255); 8 | final green = (lerp(a.green / 255, b.green / 255, t) * 255).toInt().clamp(0, 255); 9 | final blue = (lerp(a.blue / 255, b.blue / 255, t) * 255).toInt().clamp(0, 255); 10 | return Color.fromARGB(alpha, red, green, blue); 11 | } -------------------------------------------------------------------------------- /lib/util/math_util.dart: -------------------------------------------------------------------------------- 1 | double lerp(num a, num b, double t) { 2 | return (1 - t) * a.toDouble() + t * b.toDouble(); 3 | } -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.8" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.1" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.8" 25 | audioplayers: 26 | dependency: transitive 27 | description: 28 | name: audioplayers 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "0.7.8" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.0.4" 39 | box2d_flame: 40 | dependency: transitive 41 | description: 42 | name: box2d_flame 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "0.4.3" 46 | charcode: 47 | dependency: transitive 48 | description: 49 | name: charcode 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.1.2" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.14.11" 60 | convert: 61 | dependency: transitive 62 | description: 63 | name: convert 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.1.1" 67 | crypto: 68 | dependency: transitive 69 | description: 70 | name: crypto 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.0.6" 74 | cupertino_icons: 75 | dependency: "direct main" 76 | description: 77 | name: cupertino_icons 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "0.1.2" 81 | flame: 82 | dependency: "direct main" 83 | description: 84 | name: flame 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "0.10.2" 88 | flutter: 89 | dependency: "direct main" 90 | description: flutter 91 | source: sdk 92 | version: "0.0.0" 93 | flutter_test: 94 | dependency: "direct dev" 95 | description: flutter 96 | source: sdk 97 | version: "0.0.0" 98 | matcher: 99 | dependency: transitive 100 | description: 101 | name: matcher 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.12.3+1" 105 | meta: 106 | dependency: transitive 107 | description: 108 | name: meta 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "1.1.6" 112 | ordered_set: 113 | dependency: transitive 114 | description: 115 | name: ordered_set 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "1.1.2" 119 | path: 120 | dependency: transitive 121 | description: 122 | name: path 123 | url: "https://pub.dartlang.org" 124 | source: hosted 125 | version: "1.6.2" 126 | path_provider: 127 | dependency: transitive 128 | description: 129 | name: path_provider 130 | url: "https://pub.dartlang.org" 131 | source: hosted 132 | version: "0.4.1" 133 | pedantic: 134 | dependency: transitive 135 | description: 136 | name: pedantic 137 | url: "https://pub.dartlang.org" 138 | source: hosted 139 | version: "1.4.0" 140 | petitparser: 141 | dependency: transitive 142 | description: 143 | name: petitparser 144 | url: "https://pub.dartlang.org" 145 | source: hosted 146 | version: "2.1.1" 147 | quiver: 148 | dependency: transitive 149 | description: 150 | name: quiver 151 | url: "https://pub.dartlang.org" 152 | source: hosted 153 | version: "2.0.1" 154 | sky_engine: 155 | dependency: transitive 156 | description: flutter 157 | source: sdk 158 | version: "0.0.99" 159 | source_span: 160 | dependency: transitive 161 | description: 162 | name: source_span 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "1.5.4" 166 | stack_trace: 167 | dependency: transitive 168 | description: 169 | name: stack_trace 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.9.3" 173 | stream_channel: 174 | dependency: transitive 175 | description: 176 | name: stream_channel 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "1.6.8" 180 | string_scanner: 181 | dependency: transitive 182 | description: 183 | name: string_scanner 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "1.0.4" 187 | synchronized: 188 | dependency: transitive 189 | description: 190 | name: synchronized 191 | url: "https://pub.dartlang.org" 192 | source: hosted 193 | version: "1.5.3+2" 194 | term_glyph: 195 | dependency: transitive 196 | description: 197 | name: term_glyph 198 | url: "https://pub.dartlang.org" 199 | source: hosted 200 | version: "1.1.0" 201 | test_api: 202 | dependency: transitive 203 | description: 204 | name: test_api 205 | url: "https://pub.dartlang.org" 206 | source: hosted 207 | version: "0.2.2" 208 | tiled: 209 | dependency: transitive 210 | description: 211 | name: tiled 212 | url: "https://pub.dartlang.org" 213 | source: hosted 214 | version: "0.2.1" 215 | typed_data: 216 | dependency: transitive 217 | description: 218 | name: typed_data 219 | url: "https://pub.dartlang.org" 220 | source: hosted 221 | version: "1.1.6" 222 | uuid: 223 | dependency: transitive 224 | description: 225 | name: uuid 226 | url: "https://pub.dartlang.org" 227 | source: hosted 228 | version: "1.0.3" 229 | vector_math: 230 | dependency: transitive 231 | description: 232 | name: vector_math 233 | url: "https://pub.dartlang.org" 234 | source: hosted 235 | version: "2.0.8" 236 | xml: 237 | dependency: transitive 238 | description: 239 | name: xml 240 | url: "https://pub.dartlang.org" 241 | source: hosted 242 | version: "3.3.1" 243 | sdks: 244 | dart: ">=2.1.0 <3.0.0" 245 | flutter: ">=0.1.4 <2.0.0" 246 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: water_cellular_automata 2 | description: A new Flutter project. 3 | version: 1.0.0+1 4 | 5 | environment: 6 | sdk: ">=2.1.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | flame: ^0.10.2 12 | cupertino_icons: ^0.1.2 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | flutter: 19 | assets: 20 | - assets/audio/ 21 | - assets/images/ 22 | - assets/images/flow_debug_icons/ 23 | --------------------------------------------------------------------------------