diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba2546b..b42b61b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,4 +34,4 @@ jobs: with: node-version: 18 - run: npm install -g markdownlint-cli - - run: markdownlint . -c .markdownlint.yaml \ No newline at end of file + - run: markdownlint . -p .markdownlintignore -c .markdownlint.yaml \ No newline at end of file diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000..72a5d76 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1 @@ +**/macos/** diff --git a/README.md b/README.md index 76f7f64..ade5874 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,29 @@ # Flutter & Friends 2025 - flame_3d Workshop -This is a central hub for all materials related to @luanpotter and @wolfenrain's Flame 3D Workshop on Flutter & Friends 2025, including slides, templates and examples. -The goal of the workshop is to get everyone set up and running with a basis for creating 3D games or applications using the `flame_3d` package. +This is a central hub for all materials related to @luanpotter and @wolfenrain's Flame 3D Workshop +on Flutter & Friends 2025, including slides, templates and examples. + +The goal of the workshop is to get everyone set up and running with a basis for creating 3D games or +applications using the `flame_3d` package. + ## Requirements -* impeller, flutter gpu and especially flame_3d are highly experimental; join if you want to trailblaze, pave new paths, work and discover together. Do not join if you want production ready, out-of-box, stable and tested frameworks. -* currently, we only extensively tested flame_3d on macOS. Sadly, flutter_gpu does not work on Linux (or Windows) yet. We are highly anticipating the moment that the gods of Flutter bestown Linux support upon us. In the meantime, we are relegated to using macOS. We've heard that it should work on Android and iOS but have not tested it thoroughly. -* no prior knowledge about 3D rendering, how games or Flame work is required. + +- impeller, flutter gpu and especially flame_3d are highly experimental; join if you want to +trailblaze, pave new paths, work and discover together. Do not join if you want production ready, +out-of-box, stable and tested frameworks. +- currently, we only extensively tested flame_3d on macOS. Sadly, flutter_gpu does not work on +Linux (or Windows) yet. We are highly anticipating the moment that the gods of Flutter bestow Linux +support upon us. In the meantime, we are relegated to using macOS. We've heard that it should work +on Android and iOS but have not tested it thoroughly. +- no prior knowledge about 3D rendering, how games or Flame work is required. + ## Outcome -We will start from scratch and get some 3D objects into the world, a player-controlled character, camera and lighting. Then, depending on what each atendee wants to accomplish, we can cover textures, skeletal animations, and more. + +We will start from scratch and get some 3D objects into the world, a player-controlled character, +camera and lighting. Then, depending on what each attendee wants to accomplish, we can cover +textures, skeletal animations, and more. diff --git a/packages/slides/README.md b/packages/slides/README.md index a705e68..bb231f4 100644 --- a/packages/slides/README.md +++ b/packages/slides/README.md @@ -1,16 +1,32 @@ # slides -A new Flutter project. -## Getting Started +An interactive slide deck for the Flame 3D Workshop. -This project is a starting point for a Flutter application. -A few resources to get you started if this is your first Flutter project: +## Setup -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Clone this monorepo to get started, or use `ignite` to generate your own Flame 3D project. + +In order to run, you will need to follow +[the pre-requisites for setting up flame_3d](https://github.com/flame-engine/flame/tree/main/packages/flame_3d#prerequisites) +; notably: + +- Run it on macOS; + +- Enable Impeller by adding the following key to `/macos/Runner/Info.plist`: + +```xml + + ... + FLTEnableImpeller + + +``` + +- And then run with: + +```bash +flutter run -d macos --enable-flutter-gpu +``` diff --git a/packages/slides/lib/game/components/room_bounds.dart b/packages/slides/lib/game/components/room_bounds.dart new file mode 100644 index 0000000..0ee17ea --- /dev/null +++ b/packages/slides/lib/game/components/room_bounds.dart @@ -0,0 +1,65 @@ +import 'dart:async'; + +import 'package:flame/components.dart'; +import 'package:flame/palette.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/resources.dart'; + +class RoomBounds extends Component { + @override + FutureOr onLoad() { + addAll([ + // Floor + MeshComponent( + mesh: PlaneMesh( + size: Vector2(32, 32), + material: SpatialMaterial( + albedoTexture: ColorTexture( + BasicPalette.gray.color, + ), + ), + ), + ), + + // Front wall + MeshComponent( + position: Vector3(16.5, 2.5, 0), + mesh: CuboidMesh( + size: Vector3(1, 5, 32), + material: SpatialMaterial( + albedoTexture: ColorTexture( + BasicPalette.yellow.color, + ), + ), + ), + ), + + // Left wall + MeshComponent( + position: Vector3(0, 2.5, 16.5), + mesh: CuboidMesh( + size: Vector3(32, 5, 1), + material: SpatialMaterial( + albedoTexture: ColorTexture( + BasicPalette.blue.color, + ), + ), + ), + ), + + // Right wall + MeshComponent( + position: Vector3(0, 2.5, -16.5), + mesh: CuboidMesh( + size: Vector3(32, 5, 1), + material: SpatialMaterial( + albedoTexture: ColorTexture( + BasicPalette.lime.color, + ), + ), + useFaceNormals: false, + ), + ), + ]); + } +} diff --git a/packages/slides/lib/game/player.dart b/packages/slides/lib/game/player.dart new file mode 100644 index 0000000..041fbbf --- /dev/null +++ b/packages/slides/lib/game/player.dart @@ -0,0 +1,105 @@ +import 'dart:math'; + +import 'package:flame/components.dart' show HasGameReference, KeyboardHandler; +import 'package:flame/geometry.dart'; +import 'package:flame/input.dart'; +import 'package:flame/palette.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d/resources.dart'; +import 'package:flame_3d_workshop_slides/game/playground.dart'; +import 'package:flame_3d_workshop_slides/game/util/keyboard_utils.dart'; +import 'package:flutter/services.dart'; + +class Player extends MeshComponent + with HasGameReference, KeyboardHandler { + final Vector2 _input = Vector2.zero(); + + bool isRunning = false; + double speedY = 0.0; + + double _lookAngle = 0.0; + double get lookAngle => _lookAngle; + set lookAngle(double value) { + _lookAngle = value % tau; + transform.rotation.setAxisAngle(_up, value); + } + + Vector3 get lookAt => Vector3(sin(_lookAngle), 0.0, cos(_lookAngle)); + + Player({required Vector3 position}) + : super( + position: position, + mesh: CuboidMesh( + size: Vector3(1, 2, 1), + material: SpatialMaterial( + albedoTexture: ColorTexture(BasicPalette.yellow.color), + ), + ), + ); + + @override + bool onKeyEvent(KeyEvent event, Set keysPressed) { + final shiftKeys = { + LogicalKeyboardKey.shift, + LogicalKeyboardKey.shiftLeft, + LogicalKeyboardKey.shiftRight, + }; + isRunning = shiftKeys.any(keysPressed.contains); + + final isDown = event is KeyDownEvent || event is KeyRepeatEvent; + if (isDown && event.logicalKey == LogicalKeyboardKey.space) { + jump(); + return false; + } + + return readArrowLikeKeysIntoVector2(event, keysPressed, _input); + } + + @override + void update(double dt) { + super.update(dt); + _handleMovement(dt); + } + + void reset() { + position.setFrom(Vector3(0, 1, 0)); + lookAngle = 0.0; + _input.setZero(); + } + + void jump() { + if (position.y == _floorHeight) { + speedY = _jumpSpeed; + } + } + + void _handleMovement(double dt) { + lookAngle += -_input.x * _rotationSpeed * dt; + + final runningModifier = isRunning ? 2.5 : 1.0; + final movement = lookAt.scaled( + -_input.y * runningModifier * _walkingSpeed * dt, + ); + position.add(movement); + + if (speedY != 0 || position.y > _floorHeight) { + position.y += speedY * dt + 0.5 * _accY * dt * dt; + speedY += _accY * dt; + if (position.y < _floorHeight) { + position.y = _floorHeight; + speedY = 0; + } + } else { + position.y = _floorHeight; + speedY = 0; + } + } + + static const double _rotationSpeed = 3.0; + static const double _walkingSpeed = 1.85; + static const double _floorHeight = 1.0; + static const double _jumpSpeed = 5.0; + static const double _accY = -9.81; + static final Vector3 _up = Vector3(0, 1, 0); +} diff --git a/packages/slides/lib/game/playground.dart b/packages/slides/lib/game/playground.dart new file mode 100644 index 0000000..5135300 --- /dev/null +++ b/packages/slides/lib/game/playground.dart @@ -0,0 +1,25 @@ +import 'dart:async'; + +import 'package:flame/events.dart'; +import 'package:flame_3d/components.dart'; +import 'package:flame_3d/game.dart'; +import 'package:flame_3d_workshop_slides/game/components/room_bounds.dart'; +import 'package:flame_3d_workshop_slides/game/player.dart'; + +class Playground extends FlameGame3D with HasKeyboardHandlerComponents { + late Player player; + + @override + FutureOr onLoad() async { + world.addAll([ + RoomBounds(), + LightComponent.ambient( + intensity: 1.0, + ), + player = Player( + position: Vector3(0, 1, 0), + ), + ]); + return super.onLoad(); + } +} diff --git a/packages/slides/lib/game/util/keyboard_utils.dart b/packages/slides/lib/game/util/keyboard_utils.dart new file mode 100644 index 0000000..7dc5c24 --- /dev/null +++ b/packages/slides/lib/game/util/keyboard_utils.dart @@ -0,0 +1,53 @@ +import 'package:flame_3d/core.dart'; +import 'package:flutter/services.dart'; + +// TODO(luan): add this as part of the input API +bool readArrowLikeKeysIntoVector2( + KeyEvent event, + Set keysPressed, + Vector2 vector, { + LogicalKeyboardKey up = LogicalKeyboardKey.keyW, + LogicalKeyboardKey down = LogicalKeyboardKey.keyS, + LogicalKeyboardKey left = LogicalKeyboardKey.keyA, + LogicalKeyboardKey right = LogicalKeyboardKey.keyD, +}) { + final isDown = event is KeyDownEvent || event is KeyRepeatEvent; + if (event.logicalKey == up) { + if (isDown) { + vector.y = -1; + } else if (keysPressed.contains(down)) { + vector.y = 1; + } else { + vector.y = 0; + } + return false; + } else if (event.logicalKey == down) { + if (isDown) { + vector.y = 1; + } else if (keysPressed.contains(up)) { + vector.y = -1; + } else { + vector.y = 0; + } + return false; + } else if (event.logicalKey == left) { + if (isDown) { + vector.x = -1; + } else if (keysPressed.contains(right)) { + vector.x = 1; + } else { + vector.x = 0; + } + return false; + } else if (event.logicalKey == right) { + if (isDown) { + vector.x = 1; + } else if (keysPressed.contains(left)) { + vector.x = -1; + } else { + vector.x = 0; + } + return false; + } + return true; +} diff --git a/packages/slides/lib/main.dart b/packages/slides/lib/main.dart index 8f1f6ca..12cd9b0 100644 --- a/packages/slides/lib/main.dart +++ b/packages/slides/lib/main.dart @@ -1,9 +1,12 @@ import 'package:flame_3d_workshop_slides/slides/slides.dart'; -import 'package:flutter/material.dart' show ThemeMode; -import 'package:flutter/widgets.dart'; +import 'package:flame_3d_workshop_slides/utils/code.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_deck/flutter_deck.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Code.init(); + runApp(const FlutterDeckExample()); } @@ -15,7 +18,15 @@ class FlutterDeckExample extends StatelessWidget { // This is an entry point for the Flutter Deck app. return FlutterDeckApp( themeMode: ThemeMode.dark, - darkTheme: FlutterDeckThemeData.dark(), + darkTheme: FlutterDeckThemeData.fromTheme( + ThemeData.from( + colorScheme: ColorScheme.fromSeed( + seedColor: const Color(0xFF16222A), + brightness: Brightness.dark, + ), + useMaterial3: true, + ), + ), configuration: const FlutterDeckConfiguration( background: FlutterDeckBackgroundConfiguration( dark: FlutterDeckBackground.solid(Color(0xFF16222A)), @@ -24,6 +35,8 @@ class FlutterDeckExample extends StatelessWidget { slides: const [ Slide00Intro(), Slide01Bg(), + Slide02Code(), + Slide03Game(), ], ); } diff --git a/packages/slides/lib/slides/slide_02_code.dart b/packages/slides/lib/slides/slide_02_code.dart new file mode 100644 index 0000000..378fa89 --- /dev/null +++ b/packages/slides/lib/slides/slide_02_code.dart @@ -0,0 +1,24 @@ +import 'package:flame_3d_workshop_slides/utils/code.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_deck/flutter_deck.dart'; + +class Slide02Code extends FlutterDeckSlideWidget { + const Slide02Code({super.key}) + : super( + configuration: const FlutterDeckSlideConfiguration( + route: '/slide_02_code', + header: FlutterDeckHeaderConfiguration(title: 'Flame 3D Workshop'), + ), + ); + + @override + Widget build(BuildContext context) { + return FlutterDeckSlide.blank( + builder: (context) => Center( + child: Text.rich( + Code.highlight('print("Hello, World!");'), + ), + ), + ); + } +} diff --git a/packages/slides/lib/slides/slide_03_game.dart b/packages/slides/lib/slides/slide_03_game.dart new file mode 100644 index 0000000..4c5d371 --- /dev/null +++ b/packages/slides/lib/slides/slide_03_game.dart @@ -0,0 +1,25 @@ +import 'package:flame/game.dart'; +import 'package:flame_3d_workshop_slides/game/playground.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_deck/flutter_deck.dart'; + +class Slide03Game extends FlutterDeckSlideWidget { + const Slide03Game({super.key}) + : super( + configuration: const FlutterDeckSlideConfiguration( + route: '/slide_03_game', + header: FlutterDeckHeaderConfiguration(title: 'Flame 3D Workshop'), + ), + ); + + @override + Widget build(BuildContext context) { + return FlutterDeckSlide.blank( + builder: (context) => const Center( + child: GameWidget.controlled( + gameFactory: Playground.new, + ), + ), + ); + } +} diff --git a/packages/slides/lib/slides/slides.dart b/packages/slides/lib/slides/slides.dart index fea35d8..515a271 100644 --- a/packages/slides/lib/slides/slides.dart +++ b/packages/slides/lib/slides/slides.dart @@ -1,2 +1,4 @@ export 'slide_00_intro.dart'; export 'slide_01_bg.dart'; +export 'slide_02_code.dart'; +export 'slide_03_game.dart'; diff --git a/packages/slides/lib/utils/code.dart b/packages/slides/lib/utils/code.dart new file mode 100644 index 0000000..fe08d80 --- /dev/null +++ b/packages/slides/lib/utils/code.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:syntax_highlight/syntax_highlight.dart'; + +class Code { + static late Highlighter _highlighter; + + static Future init() async { + await Highlighter.initialize(['dart']); + final theme = await HighlighterTheme.loadDarkTheme(); + _highlighter = Highlighter( + language: 'dart', + theme: theme, + ); + } + + static TextSpan highlight(String code) { + return _highlighter.highlight(code); + } +} diff --git a/packages/slides/macos/Flutter/GeneratedPluginRegistrant.swift b/packages/slides/macos/Flutter/GeneratedPluginRegistrant.swift index 89cd1d3..f1dfd22 100644 --- a/packages/slides/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/packages/slides/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,13 +6,19 @@ import FlutterMacOS import Foundation import audioplayers_darwin +import device_info_plus +import irondash_engine_context import path_provider_foundation import screen_retriever_macos +import super_native_extensions import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) + SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin")) WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin")) } diff --git a/packages/slides/macos/Podfile.lock b/packages/slides/macos/Podfile.lock index 17dabf3..e93d831 100644 --- a/packages/slides/macos/Podfile.lock +++ b/packages/slides/macos/Podfile.lock @@ -2,39 +2,57 @@ PODS: - audioplayers_darwin (0.0.1): - Flutter - FlutterMacOS + - device_info_plus (0.0.1): + - FlutterMacOS - FlutterMacOS (1.0.0) + - irondash_engine_context (0.0.1): + - FlutterMacOS - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - screen_retriever_macos (0.0.1): - FlutterMacOS + - super_native_extensions (0.0.1): + - FlutterMacOS - window_manager (0.2.0): - FlutterMacOS DEPENDENCIES: - audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/darwin`) + - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - FlutterMacOS (from `Flutter/ephemeral`) + - irondash_engine_context (from `Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`) + - super_native_extensions (from `Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) EXTERNAL SOURCES: audioplayers_darwin: :path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/darwin + device_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos FlutterMacOS: :path: Flutter/ephemeral + irondash_engine_context: + :path: Flutter/ephemeral/.symlinks/plugins/irondash_engine_context/macos path_provider_foundation: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin screen_retriever_macos: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos + super_native_extensions: + :path: Flutter/ephemeral/.symlinks/plugins/super_native_extensions/macos window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: audioplayers_darwin: 4027b33a8f471d996c13f71cb77f0b1583b5d923 + device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215 FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 + irondash_engine_context: da62996ee25616d2f01bbeb85dc115d813359478 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161 + super_native_extensions: 85efee3a7495b46b04befcfc86ed12069264ebf3 window_manager: 3a1844359a6295ab1e47659b1a777e36773cd6e8 PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009 diff --git a/packages/slides/macos/Runner/Info.plist b/packages/slides/macos/Runner/Info.plist index 4789daa..a72f798 100644 --- a/packages/slides/macos/Runner/Info.plist +++ b/packages/slides/macos/Runner/Info.plist @@ -28,5 +28,7 @@ MainMenu NSPrincipalClass NSApplication + FLTEnableImpeller + diff --git a/packages/slides/pubspec.yaml b/packages/slides/pubspec.yaml index 26ae86e..09446a4 100644 --- a/packages/slides/pubspec.yaml +++ b/packages/slides/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: flutter: sdk: flutter flutter_deck: ^0.21.0 + syntax_highlight: ^0.5.0 dev_dependencies: flame_lint: ^1.4.2 diff --git a/pubspec.lock b/pubspec.lock index e0b04fd..7e67a2b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -153,6 +153,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" + url: "https://pub.dev" + source: hosted + version: "11.5.0" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f + url: "https://pub.dev" + source: hosted + version: "7.0.3" ffi: dependency: transitive description: @@ -202,7 +218,7 @@ packages: source: hosted version: "2.11.9" flame_lint: - dependency: transitive + dependency: "direct dev" description: name: flame_lint sha256: "11c92624996dce2aeec2a41d44a61d7a560d551e4b5e447e2ad0b3812e8c2836" @@ -304,6 +320,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + irondash_engine_context: + dependency: transitive + description: + name: irondash_engine_context + sha256: "2bb0bc13dfda9f5aaef8dde06ecc5feb1379f5bb387d59716d799554f3f305d7" + url: "https://pub.dev" + source: hosted + version: "0.5.5" + irondash_message_channel: + dependency: transitive + description: + name: irondash_message_channel + sha256: b4101669776509c76133b8917ab8cfc704d3ad92a8c450b92934dd8884a2f060 + url: "https://pub.dev" + source: hosted + version: "0.7.0" json_annotation: dependency: transitive description: @@ -424,6 +456,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + pixel_snap: + dependency: transitive + description: + name: pixel_snap + sha256: "677410ea37b07cd37ecb6d5e6c0d8d7615a7cf3bd92ba406fd1ac57e937d1fb0" + url: "https://pub.dev" + source: hosted + version: "0.1.5" platform: dependency: transitive description: @@ -565,6 +605,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + super_clipboard: + dependency: transitive + description: + name: super_clipboard + sha256: e73f3bb7e66cc9260efa1dc507f979138e7e106c3521e2dda2d0311f6d728a16 + url: "https://pub.dev" + source: hosted + version: "0.9.1" + super_native_extensions: + dependency: transitive + description: + name: super_native_extensions + sha256: b9611dcb68f1047d6f3ef11af25e4e68a21b1a705bbcc3eb8cb4e9f5c3148569 + url: "https://pub.dev" + source: hosted + version: "0.9.1" synchronized: dependency: transitive description: @@ -573,6 +629,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.0" + syntax_highlight: + dependency: transitive + description: + name: syntax_highlight + sha256: "4d3ba40658cadba6ba55d697f29f00b43538ebb6eb4a0ca0e895c568eaced138" + url: "https://pub.dev" + source: hosted + version: "0.5.0" term_glyph: dependency: transitive description: @@ -613,6 +677,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + url: "https://pub.dev" + source: hosted + version: "5.14.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae" + url: "https://pub.dev" + source: hosted + version: "2.1.0" window_manager: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d59c5e9..523c802 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: ">=3.8.0 <4.0.0" dev_dependencies: + flame_lint: ^1.4.2 melos: ^7.1.0 melos: @@ -20,6 +21,7 @@ melos: steps: - analyze - format + - markdown-check description: Run all static analysis checks. analyze: @@ -31,9 +33,9 @@ melos: description: Run `dart format` checks for all packages. markdown-check: - run: markdownlint . --config .markdownlint.yaml + run: markdownlint . --ignore-path .markdownlintignore --config .markdownlint.yaml description: Runs the markdown linting check. markdown-fix: - run: markdownlint . --fix --config .markdownlint.yaml + run: markdownlint . --fix --ignore-path .markdownlintignore --config .markdownlint.yaml description: Fixes the markdown linting errors.