Update README and code to set default sparkle shape to 'none' and add opacity control

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-04-15 11:24:32 +02:00
parent 0fec97163d
commit c7382c11a5
7 changed files with 257 additions and 80 deletions
+3
View File
@@ -1,3 +1,6 @@
/// Public API exports for the holo_shiny package.
library;
export 'src/sensor_tilt_controller.dart';
export 'src/shiny_controller.dart';
export 'src/shiny_widget.dart';
+2
View File
@@ -1,9 +1,11 @@
import 'package:flutter/material.dart';
/// Local smoke-test entrypoint used when running the package directly.
void main() {
runApp(const MainApp());
}
/// Minimal app shell for package-level manual checks.
class MainApp extends StatelessWidget {
const MainApp({super.key});
+119 -3
View File
@@ -6,22 +6,45 @@ import 'package:flutter/scheduler.dart';
import 'shiny_controller.dart';
/// Available holographic material profiles rendered by the fragment shader.
enum HolographStyle {
/// Smooth silver foil with soft rainbow flow.
holographicSilver,
/// High-contrast crystalline foil with shard-like reflections.
crackedIce,
/// Tiled foil with radial diffraction in each tile.
silverMosaic,
/// Dense dot-grid gold foil with warm highlights.
superGoldVinyl,
}
/// Sparkle silhouette families used by the shader when drawing glints.
enum SparkleShapeKind {
/// Disables sparkle rendering entirely.
none,
/// Star-shaped sparkle with configurable point count and inner radius.
star,
/// Rectangular sparkle streak.
rectangle,
/// Fixed-side polygon sparkle.
polygon,
/// Randomized polygon sparkle per sparkle cell.
randomPolygon,
/// Confetti-like elongated rectangle with random rotation.
confetti,
}
/// Declarative sparkle shape configuration for [Shiny] and [ShinyCard].
class SparkleShapeSpec {
/// Internal constructor that maps directly to shader uniform values.
const SparkleShapeSpec._({
required this.kind,
required this.primary,
@@ -29,6 +52,15 @@ class SparkleShapeSpec {
required this.tertiary,
});
/// No sparkle output.
static const SparkleShapeSpec none = SparkleShapeSpec._(
kind: SparkleShapeKind.none,
primary: 0.0,
secondary: 0.0,
tertiary: 0.0,
);
/// Eight-point star sparkle preset.
static const SparkleShapeSpec eightPointStar = SparkleShapeSpec._(
kind: SparkleShapeKind.star,
primary: 8.0,
@@ -36,6 +68,7 @@ class SparkleShapeSpec {
tertiary: 0.0,
);
/// Five-point star sparkle preset.
static const SparkleShapeSpec fivePointStar = SparkleShapeSpec._(
kind: SparkleShapeKind.star,
primary: 5.0,
@@ -43,6 +76,7 @@ class SparkleShapeSpec {
tertiary: 0.0,
);
/// Rectangular sparkle preset.
static const SparkleShapeSpec rectangle = SparkleShapeSpec._(
kind: SparkleShapeKind.rectangle,
primary: 0.24,
@@ -50,6 +84,7 @@ class SparkleShapeSpec {
tertiary: 1.0,
);
/// Diamond sparkle preset.
static const SparkleShapeSpec diamond = SparkleShapeSpec._(
kind: SparkleShapeKind.polygon,
primary: 4.0,
@@ -57,6 +92,7 @@ class SparkleShapeSpec {
tertiary: 0.78539816339,
);
/// Hexagon sparkle preset.
static const SparkleShapeSpec hexagon = SparkleShapeSpec._(
kind: SparkleShapeKind.polygon,
primary: 6.0,
@@ -64,6 +100,7 @@ class SparkleShapeSpec {
tertiary: 0.0,
);
/// Randomized polygon sparkle preset.
static const SparkleShapeSpec randomPolygon = SparkleShapeSpec._(
kind: SparkleShapeKind.randomPolygon,
primary: 0.0,
@@ -71,6 +108,7 @@ class SparkleShapeSpec {
tertiary: 0.0,
);
/// Confetti sparkle preset.
static const SparkleShapeSpec confetti = SparkleShapeSpec._(
kind: SparkleShapeKind.confetti,
primary: 0.34,
@@ -78,6 +116,9 @@ class SparkleShapeSpec {
tertiary: 1.0,
);
/// Creates a custom star sparkle.
///
/// [points] is clamped to `[4, 12]` and [innerRatio] to `[0.15, 0.85]`.
factory SparkleShapeSpec.customStar(
{int points = 8, double innerRatio = 0.42}) {
return SparkleShapeSpec._(
@@ -88,6 +129,9 @@ class SparkleShapeSpec {
);
}
/// Creates a custom polygon sparkle.
///
/// [sides] is clamped to `[3, 10]` and [aspectRatio] to `[0.4, 2.0]`.
factory SparkleShapeSpec.customPolygon(
{int sides = 6, double aspectRatio = 1.0, double rotation = 0.0}) {
return SparkleShapeSpec._(
@@ -98,6 +142,9 @@ class SparkleShapeSpec {
);
}
/// Creates a custom rectangular sparkle.
///
/// Values are clamped to keep shapes visible and numerically stable.
factory SparkleShapeSpec.customRectangle(
{double halfWidth = 0.24,
double halfHeight = 0.055,
@@ -110,6 +157,9 @@ class SparkleShapeSpec {
);
}
/// Creates a custom confetti sparkle.
///
/// Values are clamped to keep geometry inside the sparkle cell.
factory SparkleShapeSpec.customConfetti(
{double length = 0.34,
double thickness = 0.045,
@@ -122,13 +172,22 @@ class SparkleShapeSpec {
);
}
/// Sparkle family used by the shader.
final SparkleShapeKind kind;
/// Shape parameter 1. Meaning depends on [kind].
final double primary;
/// Shape parameter 2. Meaning depends on [kind].
final double secondary;
/// Shape parameter 3. Meaning depends on [kind].
final double tertiary;
}
/// Applies holographic shader lighting to any child widget.
class Shiny extends StatefulWidget {
/// Creates a shiny wrapper.
const Shiny({
super.key,
required this.child,
@@ -138,22 +197,47 @@ class Shiny extends StatefulWidget {
this.sparkle = 0.8,
this.specular = 0.8,
this.diffraction = 0.8,
this.sparkleShape = SparkleShapeSpec.eightPointStar,
this.opacity = 1.0,
this.sparkleShape = SparkleShapeSpec.none,
this.style = HolographStyle.crackedIce,
this.blendMode = BlendMode.screen,
this.enableShader = true,
});
/// Child widget receiving the shader mask.
final Widget child;
/// Optional tilt controller stream source.
final ShinyController? controller;
/// Explicit tilt override in normalized `[-1.0, 1.0]` space.
final Offset? tilt;
/// Color separation strength.
final double prismatic;
/// Sparkle strength multiplier.
final double sparkle;
/// Main highlight intensity.
final double specular;
/// Micro-diffraction intensity.
final double diffraction;
/// Global shader opacity multiplier.
final double opacity;
/// Sparkle silhouette specification.
final SparkleShapeSpec sparkleShape;
/// Foil style preset.
final HolographStyle style;
/// Blend mode applied by [ShaderMask].
final BlendMode blendMode;
/// Toggles shader execution.
final bool enableShader;
@override
@@ -268,7 +352,8 @@ class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
..setFloat(10, widget.sparkleShape.kind.index.toDouble())
..setFloat(11, widget.sparkleShape.primary)
..setFloat(12, widget.sparkleShape.secondary)
..setFloat(13, widget.sparkleShape.tertiary);
..setFloat(13, widget.sparkleShape.tertiary)
..setFloat(14, widget.opacity);
return shader;
}
@@ -289,6 +374,7 @@ class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
}
class ShinyCard extends StatefulWidget {
/// Creates a card helper that combines clipping, tilt transform, and [Shiny].
const ShinyCard({
super.key,
this.background,
@@ -302,23 +388,52 @@ class ShinyCard extends StatefulWidget {
this.sparkle = 0.8,
this.specular = 0.8,
this.diffraction = 0.8,
this.sparkleShape = SparkleShapeSpec.eightPointStar,
this.opacity = 1.0,
this.sparkleShape = SparkleShapeSpec.none,
this.style = HolographStyle.crackedIce,
this.enableShader = true,
});
/// Optional card background; defaults to a dark fill.
final Widget? background;
/// Optional widget drawn above the shiny background.
final Widget? foreground;
/// Card clipping shape.
final ShapeBorder shape;
/// Card width.
final double width;
/// Card height.
final double height;
/// Optional sensor or custom tilt controller.
final ShinyController? controller;
/// Color separation strength.
final double prismatic;
/// Sparkle strength multiplier.
final double sparkle;
/// Main highlight intensity.
final double specular;
/// Micro-diffraction intensity.
final double diffraction;
/// Global shader opacity multiplier.
final double opacity;
/// Sparkle silhouette specification.
final SparkleShapeSpec sparkleShape;
/// Foil style preset.
final HolographStyle style;
/// Toggles shader execution.
final bool enableShader;
@override
@@ -451,6 +566,7 @@ class _ShinyCardState extends State<ShinyCard>
sparkle: widget.sparkle,
specular: widget.specular,
diffraction: widget.diffraction,
opacity: widget.opacity,
sparkleShape: widget.sparkleShape,
style: widget.style,
child: base,