From 62a9069b3b0b3fc92d2fb72cfb044c539a2f35f7 Mon Sep 17 00:00:00 2001 From: Raouf Rahiche Date: Mon, 17 Jun 2024 20:44:29 +0100 Subject: [PATCH] wip just for deplyment on the web --- .idea/libraries/Dart_Packages.xml | 208 +++++++++++++++++ .idea/libraries/Flutter_Plugins.xml | 11 +- .idea/vcs.xml | 6 + flutter_custom_visuals.iml | 1 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 44 ++++ lib/main.dart | 88 +++++-- lib/ripple/blur_demo.dart | 147 ++++++++++++ lib/ripple/electro_demo.dart | 147 ++++++++++++ lib/ripple/gradient_flow_demo.dart | 212 +++++++++++++++++ lib/ripple/lightning_demo.dart | 147 ++++++++++++ lib/ripple/meatballs_demo.dart | 220 ++++++++++++++++++ lib/ripple/mesh_gradient_demo.dart | 147 ++++++++++++ lib/ripple/ripple_demo.dart | 31 ++- lib/ripple/sparkles_demo.dart | 109 +++++++++ lib/ripple/sweep_demo.dart | 147 ++++++++++++ macos/Flutter/Flutter-Debug.xcconfig | 1 + macos/Flutter/Flutter-Release.xcconfig | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile | 43 ++++ macos/Podfile.lock | 23 ++ macos/Runner.xcodeproj/project.pbxproj | 98 +++++++- .../contents.xcworkspacedata | 3 + pubspec.yaml | 5 +- shaders/blur.frag | 0 shaders/bubbles.frag | 40 ++++ shaders/electro.frag | 0 shaders/gradient_flow.frag | 86 +++++++ shaders/lightning.frag | 5 + shaders/mesh_gradient.frag | 0 shaders/sparkles.frag | 52 +++++ shaders/sweep.frag | 0 33 files changed, 1995 insertions(+), 31 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 ios/Podfile create mode 100644 lib/ripple/blur_demo.dart create mode 100644 lib/ripple/electro_demo.dart create mode 100644 lib/ripple/gradient_flow_demo.dart create mode 100644 lib/ripple/lightning_demo.dart create mode 100644 lib/ripple/meatballs_demo.dart create mode 100644 lib/ripple/mesh_gradient_demo.dart create mode 100644 lib/ripple/sparkles_demo.dart create mode 100644 lib/ripple/sweep_demo.dart create mode 100644 macos/Podfile create mode 100644 macos/Podfile.lock create mode 100644 shaders/blur.frag create mode 100644 shaders/bubbles.frag create mode 100644 shaders/electro.frag create mode 100644 shaders/gradient_flow.frag create mode 100644 shaders/lightning.frag create mode 100644 shaders/mesh_gradient.frag create mode 100644 shaders/sparkles.frag create mode 100644 shaders/sweep.frag diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 40956c9..0ba3a74 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -44,6 +44,20 @@ + + + + + + + + + + + + @@ -51,6 +65,20 @@ + + + + + + + + + + + + @@ -65,6 +93,13 @@ + + + + + + @@ -79,6 +114,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -128,6 +191,13 @@ + + + + + + @@ -135,6 +205,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -198,6 +359,27 @@ + + + + + + + + + + + + + + + + + + @@ -207,9 +389,16 @@ + + + + + + + @@ -217,7 +406,21 @@ + + + + + + + + + + + + + + @@ -226,9 +429,14 @@ + + + + + diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml index b0f6971..86004d3 100644 --- a/.idea/libraries/Flutter_Plugins.xml +++ b/.idea/libraries/Flutter_Plugins.xml @@ -1,6 +1,15 @@ - + + + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/flutter_custom_visuals.iml b/flutter_custom_visuals.iml index a461e81..b3a2b0c 100644 --- a/flutter_custom_visuals.iml +++ b/flutter_custom_visuals.iml @@ -10,5 +10,6 @@ + \ No newline at end of file diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..d97f17e --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '12.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/lib/main.dart b/lib/main.dart index c8b2ae0..3f69d9e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,50 +1,73 @@ import 'package:flutter/material.dart'; +import 'package:flutter_custom_visuals/ripple/blur_demo.dart'; +import 'package:flutter_custom_visuals/ripple/electro_demo.dart'; +import 'package:flutter_custom_visuals/ripple/gradient_flow_demo.dart'; +import 'package:flutter_custom_visuals/ripple/lightning_demo.dart'; +import 'package:flutter_custom_visuals/ripple/meatballs_demo.dart'; +import 'package:flutter_custom_visuals/ripple/mesh_gradient_demo.dart'; import 'package:flutter_custom_visuals/ripple/ripple_demo.dart'; +import 'package:flutter_custom_visuals/ripple/sparkles_demo.dart'; +import 'package:flutter_custom_visuals/ripple/sweep_demo.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( title: 'FlutterCustomVisuals', - theme: ThemeData( - primarySwatch: Colors.blue, - ), + theme: ThemeData(primarySwatch: Colors.blue), home: DemoGridPage(), ); } } -class DemoGridPage extends StatelessWidget { +class DemoGridPage extends StatefulWidget { + const DemoGridPage({super.key}); + + @override + State createState() => _DemoGridPageState(); +} + +class _DemoGridPageState extends State { + final examples = [ + "Ripple", + "BoxBlur", + "Meatballs", + "GradientFlow", + "MeshGradient", + "Waterr?", + "Noise?", + "Sparkles", + "Stars", + "PageCurl", + "lightning", + ]; + @override Widget build(BuildContext context) { + return GradientFlowDemoPage(); return Scaffold( appBar: AppBar( - title: Text('Flutter Custom Visuals'), + title: const Text('Flutter Custom Visuals'), ), body: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, ), - itemCount: 1, + itemCount: examples.length, itemBuilder: (context, index) { return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RippleDemoPage(), - ), - ); - }, + onTap: () => _showDemo(context, examples[index]), child: Card( child: Center( child: Padding( padding: const EdgeInsets.all(8.0), - child: Text("Ripple"), + child: Text(examples[index]), ), ), ), @@ -53,4 +76,35 @@ class DemoGridPage extends StatelessWidget { ), ); } + + void _showDemo(BuildContext context, String demo) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + switch (demo) { + case "Ripple": + return const RippleDemoPage(); + case "lightning": + return const LightningDemoPage(); + case "BoxBlur": + return const BlurDemoPage(); + case "Meatballs": + return const MeatballsDemoPage(); + case "GradientFlow": + return const GradientFlowDemoPage(); + case "MeshGradient": + return const MeshGradientDemoPage(); + case "Sweep": + return const SweepDemoPage(); + case "Sparkles": + return const SparklesDemoPage(); + case "electro": + return const ElectroDemoPage(); + } + return const SizedBox(); + }, + ), + ); + } } diff --git a/lib/ripple/blur_demo.dart b/lib/ripple/blur_demo.dart new file mode 100644 index 0000000..2ec1a37 --- /dev/null +++ b/lib/ripple/blur_demo.dart @@ -0,0 +1,147 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class BlurDemoPage extends StatefulWidget { + const BlurDemoPage({super.key}); + + @override + State createState() => _BlurDemoPageState(); +} + +class _BlurDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, + ), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/electro_demo.dart b/lib/ripple/electro_demo.dart new file mode 100644 index 0000000..e9e6133 --- /dev/null +++ b/lib/ripple/electro_demo.dart @@ -0,0 +1,147 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class ElectroDemoPage extends StatefulWidget { + const ElectroDemoPage({super.key}); + + @override + State createState() => _ElectroDemoPageState(); +} + +class _ElectroDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, + ), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/gradient_flow_demo.dart b/lib/ripple/gradient_flow_demo.dart new file mode 100644 index 0000000..713d3ed --- /dev/null +++ b/lib/ripple/gradient_flow_demo.dart @@ -0,0 +1,212 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class GradientFlowDemoPage extends StatefulWidget { + const GradientFlowDemoPage({super.key}); + + @override + State createState() => _GradientFlowDemoPageState(); +} + +class _GradientFlowDemoPageState extends State + with SingleTickerProviderStateMixin { + late final AnimationController animationController; + + @override + void initState() { + super.initState(); + animationController = + AnimationController(vsync: this, duration: Duration(milliseconds: 800)); + animationController.repeat(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + double value = 0; + + int currentColorSetIndex = 0; + + final List> colorSets = [ + { + 'colorPrimary': Color(0xFFFDF5E6), // Old Lace + 'colorSecondary': Color(0xFFC0392B), // Dark Red + 'colorAccent1': Color(0xFFFFE4E1), // Misty Rose + 'colorAccent2': Color(0xFF2980B9), // Dark Sky Blue + }, + { + 'colorPrimary': Color(0xFFFFDAB9), // Peach Puff + 'colorSecondary': Color(0xFF000080), // Navy + 'colorAccent1': Color(0xFFFFFAF0), // Floral White + 'colorAccent2': Color(0xFF2E8B57), // Sea Green + }, + { + 'colorPrimary': Color(0xFFFAFAD2), // Light Goldenrod Yellow + 'colorSecondary': Color(0xFF2C3E50), // Dark Blue + 'colorAccent1': Color(0xFFFFF8DC), // Cornsilk + 'colorAccent2': Color(0xFF27AE60), // Dark Green + }, + { + 'colorPrimary': Color(0xFFFFE4C4), // Bisque + 'colorSecondary': Color(0xFF7F8C8D), // Dark Gray + 'colorAccent1': Color(0xFFFFFAF0), // Floral White + 'colorAccent2': Color(0xFFC0392B), // Dark Red + }, + { + 'colorPrimary': Color(0xFFFFF0F5), // Lavender Blush + 'colorSecondary': Color(0xFF8E44AD), // Dark Purple + 'colorAccent1': Color(0xFFFFF8E1), // Beige + 'colorAccent2': Color(0xFFE67E22), // Dark Orange + }, + { + 'colorPrimary': Color(0xFFFFFACD), // Lemon Chiffon + 'colorSecondary': Color(0xFF2C3E50), // Dark Blue + 'colorAccent1': Color(0xFFF0FFFF), // Azure + 'colorAccent2': Color(0xFF16A085), // Dark Teal + }, + + // dark + { + 'colorPrimary': Color(0xFF2C3E50), // Dark Blue + 'colorSecondary': Color(0xFF8E44AD), // Dark Purple + 'colorAccent1': Color(0xFF2980B9), // Dark Sky Blue + 'colorAccent2': Color(0xFF27AE60), // Dark Green + }, + + { + 'colorPrimary': Color(0xFF34495E), // Dark Slate Blue + 'colorSecondary': Color(0xFFD35400), // Dark Orange + 'colorAccent1': Color(0xFF16A085), // Dark Teal + 'colorAccent2': Color(0xFF2ECC71), // Dark Green + }, + ]; + + void _changeColorSet() { + setState(() { + currentColorSetIndex = (currentColorSetIndex + 1) % colorSets.length; + }); + } + + @override + Widget build(BuildContext context) { + final currentColorSet = colorSets[currentColorSetIndex]; + final colorPrimary = currentColorSet['colorPrimary']!; + final colorSecondary = currentColorSet['colorSecondary']!; + final colorAccent1 = currentColorSet['colorAccent1']!; + final colorAccent2 = currentColorSet['colorAccent2']!; + + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return AnimatedBuilder( + animation: animationController, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + shader.setFloat(0, size.width); + shader.setFloat(1, size.height); + shader.setFloat(2, value); + + shader.setFloat(3, colorPrimary.red / 255); + shader.setFloat(4, colorPrimary.green / 255); + shader.setFloat(5, colorPrimary.blue / 255); + + shader.setFloat(6, colorSecondary.red / 255); + shader.setFloat(7, colorSecondary.green / 255); + shader.setFloat(8, colorSecondary.blue / 255); + + shader.setFloat(9, colorAccent1.red / 255); + shader.setFloat(10, colorAccent1.green / 255); + shader.setFloat(11, colorAccent1.blue / 255); + + shader.setFloat(12, colorAccent2.red / 255); + shader.setFloat(13, colorAccent2.green / 255); + shader.setFloat(14, colorAccent2.blue / 255); + + value += 0.02; + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint()..shader = shader, + ); + }, + child: Container(), + ); + }, + assetKey: "shaders/gradient_flow.frag", + ); + }, + ); + }, + ), + floatingActionButton: Row( + mainAxisSize: MainAxisSize.min, + children: [ + // Flexible( + // child: Padding( + // padding: const EdgeInsets.all(8.0), + // child: Text( + // currentColorSet.toString(), + // maxLines: 5, + // ), + // ), + // ), + FloatingActionButton( + onPressed: _changeColorSet, + child: Icon(Icons.color_lens), + ), + ], + ), + ), + ), + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/lightning_demo.dart b/lib/ripple/lightning_demo.dart new file mode 100644 index 0000000..b042169 --- /dev/null +++ b/lib/ripple/lightning_demo.dart @@ -0,0 +1,147 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class LightningDemoPage extends StatefulWidget { + const LightningDemoPage({super.key}); + + @override + State createState() => _LightningDemoPageState(); +} + +class _LightningDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, + ), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/meatballs_demo.dart b/lib/ripple/meatballs_demo.dart new file mode 100644 index 0000000..43bd7f8 --- /dev/null +++ b/lib/ripple/meatballs_demo.dart @@ -0,0 +1,220 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class MeatballsDemoPage extends StatefulWidget { + const MeatballsDemoPage({super.key}); + + @override + State createState() => _MeatballsDemoPageState(); +} + +class _MeatballsDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: Center(child: Bubbles()), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} + +class Bubbles extends StatefulWidget { + const Bubbles({Key? key}) : super(key: key); + + @override + State createState() => _BubblesState(); +} + +class _BubblesState extends State with SingleTickerProviderStateMixin { + late final AnimationController animationController; + @override + void initState() { + super.initState(); + animationController = + AnimationController(vsync: this, duration: Duration(milliseconds: 800)); + animationController.repeat(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + double value = 0; + double count = 0.01; + + @override + Widget build(BuildContext context) { + final screenSize = MediaQuery.sizeOf(context); + final child = Center( + child: AnimatedBuilder( + animation: animationController, + builder: (context, child) { + return ShaderBuilder( + (context, shader, child) { + return AnimatedSampler( + (image, size, canvas) { + // Set the values for resolution and iTime + shader.setFloat(0, size.width * 2); + shader.setFloat(1, size.height * 2); + shader.setFloat(2, value); + shader.setFloat(3, count); + + value += 0.03; + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint()..shader = shader, + ); + }, + child: SizedBox( + width: screenSize.width, + height: screenSize.height, + ), + ); + }, + assetKey: 'shaders/bubbles.frag', + ); + }, + ), + ); + return Scaffold( + body: Stack( + children: [ + child, + // Center( + // child: FilledButton( + // onPressed: () { + // count = count + 0.001; + // setState(() {}); + // }, + // child: const Text( + // "Click here", + // style: TextStyle(fontSize: 40), + // ), + // ), + // ) + ], + ), + ); + } +} diff --git a/lib/ripple/mesh_gradient_demo.dart b/lib/ripple/mesh_gradient_demo.dart new file mode 100644 index 0000000..895236a --- /dev/null +++ b/lib/ripple/mesh_gradient_demo.dart @@ -0,0 +1,147 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class MeshGradientDemoPage extends StatefulWidget { + const MeshGradientDemoPage({super.key}); + + @override + State createState() => _MeshGradientDemoPageState(); +} + +class _MeshGradientDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, + ), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/ripple_demo.dart b/lib/ripple/ripple_demo.dart index 8a8ad32..a33cf77 100644 --- a/lib/ripple/ripple_demo.dart +++ b/lib/ripple/ripple_demo.dart @@ -1,7 +1,6 @@ import 'dart:ui' as ui; -import 'package:flutter/cupertino.dart'; +import 'package:device_preview/device_preview.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; import 'package:flutter_shaders/flutter_shaders.dart'; class RippleDemoPage extends StatefulWidget { @@ -32,16 +31,26 @@ class _RippleDemoPageState extends State @override Widget build(BuildContext context) { - return Scaffold( - body: PageView.builder( - itemBuilder: (BuildContext context, int index) { - return Center( - child: Padding( - padding: const EdgeInsets.all(24.0), - child: buildImage(), + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, ), - ); - }, + ), + ), ), ); } diff --git a/lib/ripple/sparkles_demo.dart b/lib/ripple/sparkles_demo.dart new file mode 100644 index 0000000..a1b814a --- /dev/null +++ b/lib/ripple/sparkles_demo.dart @@ -0,0 +1,109 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class SparklesDemoPage extends StatefulWidget { + const SparklesDemoPage({super.key}); + + @override + State createState() => _SparklesDemoPageState(); +} + +class _SparklesDemoPageState extends State + with SingleTickerProviderStateMixin { + late final AnimationController animationController; + @override + void initState() { + super.initState(); + animationController = + AnimationController(vsync: this, duration: Duration(milliseconds: 800)); + animationController.repeat(); + } + + @override + void dispose() { + animationController.dispose(); + super.dispose(); + } + + double value = 0; + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return AnimatedBuilder( + animation: animationController, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + shader.setFloat(0, size.width); + shader.setFloat(1, size.height); + shader.setFloat(2, value); + + value += 0.03; + canvas.drawRect( + Rect.fromLTWH(0, 0, size.width, size.height), + Paint()..shader = shader, + ); + }, + child: Container(), + ); + }, + assetKey: "shaders/sparkles.frag", + ); + }, + ); + }, + ), + ), + ), + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/lib/ripple/sweep_demo.dart b/lib/ripple/sweep_demo.dart new file mode 100644 index 0000000..13902ac --- /dev/null +++ b/lib/ripple/sweep_demo.dart @@ -0,0 +1,147 @@ +import 'dart:ui' as ui; +import 'package:device_preview/device_preview.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_shaders/flutter_shaders.dart'; + +class SweepDemoPage extends StatefulWidget { + const SweepDemoPage({super.key}); + + @override + State createState() => _SweepDemoPageState(); +} + +class _SweepDemoPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(seconds: 5), + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Material( + child: Padding( + padding: const EdgeInsets.all(32.0), + child: DeviceFrame( + device: Devices.ios.iPhone13ProMax, + isFrameVisible: true, + orientation: Orientation.portrait, + screen: Scaffold( + body: PageView.builder( + itemBuilder: (BuildContext context, int index) { + return Center( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: buildImage(), + ), + ); + }, + ), + ), + ), + ), + ); + } + + Offset _pointer = Offset.zero; + + void _updatePointer(PointerEvent details) { + // _controller.animateTo(1.0); + _controller.reset(); + _controller.forward(); + setState(() { + _pointer = details.localPosition; + }); + } + + Widget buildImage() { + return Listener( + onPointerMove: _updatePointer, + onPointerDown: _updatePointer, + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return ShaderBuilder( + (context, shader, _) { + return AnimatedSampler( + (image, size, canvas) { + ShaderHelper.configureShader( + shader, + size, + image, + time: _controller.value * 10.0, + pointer: _pointer, + ); + ShaderHelper.drawShaderRect(shader, size, canvas); + }, + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: AspectRatio( + aspectRatio: 0.7, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.asset( + "assets/palm_tree_cropped.jpeg", + fit: BoxFit.cover, + ), + ), + ), + ), + ), + ); + }, + assetKey: "shaders/ripple.frag", + ); + }, + ), + ); + } +} + +class ShaderHelper { + static void configureShader( + ui.FragmentShader shader, + ui.Size size, + ui.Image image, { + required double time, + required Offset pointer, + }) { + shader + ..setFloat(0, size.width) // iResolution + ..setFloat(1, size.height) // iResolution + ..setFloat(2, pointer.dx) // iMouse + ..setFloat(3, pointer.dy) // iMouse + ..setFloat(4, time) // iTime + ..setImageSampler(0, image); // image + } + + static void drawShaderRect( + ui.FragmentShader shader, + ui.Size size, + ui.Canvas canvas, + ) { + canvas.drawRect( + Rect.fromLTWH( + 0, + 0, + size.width, + size.height, + ), + Paint()..shader = shader, + ); + } +} diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b..4b81f9b 100644 --- a/macos/Flutter/Flutter-Debug.xcconfig +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig index c2efd0b..5caa9d1 100644 --- a/macos/Flutter/Flutter-Release.xcconfig +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..724bb2a 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..c795730 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..a0b35b4 --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - FlutterMacOS (1.0.0) + - shared_preferences_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + shared_preferences_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + +PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 + +COCOAPODS: 1.13.0 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 2224e51..84ef1b0 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -21,12 +21,14 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 2E574F14A5B6E333B3085517 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D81B26D674A21EE61A16955 /* Pods_RunnerTests.framework */; }; 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 61CB8A4B75C2273C41520050 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B3EB1AF899140F1A4E5158D /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 2D81B26D674A21EE61A16955 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* flutter_custom_visuals.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "flutter_custom_visuals.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* flutter_custom_visuals.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flutter_custom_visuals.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -76,8 +79,15 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 3B3EB1AF899140F1A4E5158D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4880E05129EE4F1E35393629 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 4B952110EAC9EA095EF5E472 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 74EAA85A7C439B177EC2EA2A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 88A3CF90CA2C3F29A5A40348 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + B614CA229DEAF412049ABA3A /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + CB363009861A3CA2F647068F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2E574F14A5B6E333B3085517 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,12 +103,27 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 61CB8A4B75C2273C41520050 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0BFDB36559F27E0E2EBF2B53 /* Pods */ = { + isa = PBXGroup; + children = ( + CB363009861A3CA2F647068F /* Pods-Runner.debug.xcconfig */, + 88A3CF90CA2C3F29A5A40348 /* Pods-Runner.release.xcconfig */, + 74EAA85A7C439B177EC2EA2A /* Pods-Runner.profile.xcconfig */, + 4880E05129EE4F1E35393629 /* Pods-RunnerTests.debug.xcconfig */, + B614CA229DEAF412049ABA3A /* Pods-RunnerTests.release.xcconfig */, + 4B952110EAC9EA095EF5E472 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 331C80D6294CF71000263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( @@ -125,6 +151,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 0BFDB36559F27E0E2EBF2B53 /* Pods */, ); sourceTree = ""; }; @@ -175,6 +202,8 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 3B3EB1AF899140F1A4E5158D /* Pods_Runner.framework */, + 2D81B26D674A21EE61A16955 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 0EC4CEF8B60F87F4874E73DE /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + BF1CDDB71361259E0930C49F /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 8D8864F1991CFD437D31EF55 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0EC4CEF8B60F87F4874E73DE /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +383,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 8D8864F1991CFD437D31EF55 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + BF1CDDB71361259E0930C49F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4880E05129EE4F1E35393629 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = B614CA229DEAF412049ABA3A /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4B952110EAC9EA095EF5E472 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/pubspec.yaml b/pubspec.yaml index d033ddb..2641361 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 flutter_shaders: ^0.1.2 - + device_preview: ^1.2.0 dev_dependencies: flutter_test: sdk: flutter @@ -60,6 +60,9 @@ flutter: uses-material-design: true shaders: - shaders/ripple.frag + - shaders/bubbles.frag + - shaders/sparkles.frag + - shaders/gradient_flow.frag # To add assets to your application, add an assets section, like this: assets: - assets/ diff --git a/shaders/blur.frag b/shaders/blur.frag new file mode 100644 index 0000000..e69de29 diff --git a/shaders/bubbles.frag b/shaders/bubbles.frag new file mode 100644 index 0000000..c5e5d36 --- /dev/null +++ b/shaders/bubbles.frag @@ -0,0 +1,40 @@ +#version 460 core + +precision mediump float; + +#include + +uniform vec2 iResolution; +uniform float iTime; +uniform float countTimes; + +out vec4 fragColor; +#define COUNT 10. +#define COL1 vec3(0, 0, 0)/255. +#define COL2 vec3(82, 255, 161)/255. + + +#define rand1(p) fract(sin(p* 78.233)* 43758.5453) + + +void main() { + vec2 fragCoord = FlutterFragCoord().xy; + + vec2 uv = fragCoord / iResolution.xy ; + + float sum = 0.; + + for(float i=0.; i + +uniform vec2 iResolution; +uniform float iTime; +// Uniforms for the gradient colors +uniform vec3 colorPrimary; +uniform vec3 colorSecondary; +uniform vec3 colorAccent1; +uniform vec3 colorAccent2; +out vec4 fragColor; + +#define S(a,b,t) smoothstep(a,b,t) + +mat2 Rot(float a) +{ + float s = sin(a); + float c = cos(a); + return mat2(c, -s, s, c); +} + +// Created by inigo quilez - iq/2014 +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. +vec2 hash( vec2 p ) +{ + p = vec2( dot(p,vec2(2127.1,81.17)), dot(p,vec2(1269.5,283.37)) ); + return fract(sin(p)*43758.5453); +} + +float noise( in vec2 p ) +{ + vec2 i = floor( p ); + vec2 f = fract( p ); + + vec2 u = f*f*(3.0-2.0*f); + + float n = mix( mix( dot( -1.0+2.0*hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ), + dot( -1.0+2.0*hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x), + mix( dot( -1.0+2.0*hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ), + dot( -1.0+2.0*hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y); + return 0.5 + 0.5*n; +} + + + + +void main() +{ + vec2 fragCoord = FlutterFragCoord().xy; + + vec2 uv = fragCoord / iResolution.xy ; + float ratio = iResolution.x / iResolution.y; + + vec2 tuv = uv; + tuv -= .5; + + // rotate with Noise + float degree = noise(vec2(iTime*.1, tuv.x*tuv.y)); + + tuv.y *= 1./ratio; + tuv *= Rot(radians((degree-.5)*720.+180.)); + tuv.y *= ratio; + + // Wave warp with sin + float frequency = 5.; + float amplitude = 30.; + float speed = iTime * 2.; + tuv.x += sin(tuv.y*frequency+speed)/amplitude; + tuv.y += sin(tuv.x*frequency*1.5+speed)/(amplitude*.5); + + // draw the image + vec3 layer1 = mix(colorPrimary, colorSecondary, S(-.3, .2, (tuv*Rot(radians(-5.))).x)); + vec3 layer2 = mix(colorAccent1, colorAccent2, S(-.3, .2, (tuv*Rot(radians(-5.))).x)); + + vec3 finalComp = mix(layer1, layer2, S(.5, -.3, tuv.y)); + + vec3 col = finalComp; + + fragColor = vec4(col, 1.0); +} diff --git a/shaders/lightning.frag b/shaders/lightning.frag new file mode 100644 index 0000000..7e58b92 --- /dev/null +++ b/shaders/lightning.frag @@ -0,0 +1,5 @@ +#version 120 + +void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/shaders/mesh_gradient.frag b/shaders/mesh_gradient.frag new file mode 100644 index 0000000..e69de29 diff --git a/shaders/sparkles.frag b/shaders/sparkles.frag new file mode 100644 index 0000000..dda79d8 --- /dev/null +++ b/shaders/sparkles.frag @@ -0,0 +1,52 @@ +#version 460 core + +precision mediump float; + +#include + +uniform vec2 uSize; +uniform float iTime; + + +out vec4 fragColor; + + +float Hash31(in vec3 p) { + return fract(937.276 * cos(836.826 * p.x + 263.736 * p.y + 374.723 * p.z + 637.839)); +} + +void main() { + vec2 uv = (FlutterFragCoord() - 0.5 * uSize.xy) / uSize.y * 9.0; + + float time = iTime * 2.0; + vec3 color = vec3(0.0); + + for (float i=-3.0; i <= 3.0; i += 1.25) { + for (float j=-2.0; j <= 2.0; j += 1.25) { + vec2 p = uv; + + float freq = fract(643.376 * cos(264.863 * i + 136.937)) + 1.0; + vec2 pos = 5.0 * vec2(i, j) + vec2(sin(freq * (iTime + 10.0 * j) - i), freq * iTime); + pos.y = mod(pos.y + 15.0, 30.0) - 15.0; + pos.x *= 0.1 * pos.y + 1.0; + p -= 0.2 * pos; + + float an = mod(atan(p.y, p.x) + 6.2831 / 3.0, 6.2831 / 6.0) - 6.2831 / 3.0; + p = vec2(cos(an), sin(an)) * length(p); + + float sec = floor(time); + float frac = fract(time); + float flicker = mix(Hash31(vec3(i, j, sec)), Hash31(vec3(i, j, sec + 1.0)), frac); + + float rad = 25.0 + 20.0 * flicker; + float br = 250.0 * pow(1.0 / max(10.0, rad * (sqrt(abs(p.x)) + sqrt(abs(p.y))) + 0.9), 2.5); + float rand = fract(847.384 * cos(483.846 * i + 737.487 * j + 264.836)); + if (rand > 0.5) color += mix(vec3(br, 0.4 * br, 0.0), vec3(1.0), br); + else color += mix(vec3(0.0, 0.0, 0.6 * br), vec3(1.0), br); + + color *= 0.955 + 0.1 * flicker; + } + } + + fragColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/shaders/sweep.frag b/shaders/sweep.frag new file mode 100644 index 0000000..e69de29