Skip to main content

Migration Guide: 0.2.x to 0.3.x

This guide will help you migrate your Newton particle effects from version 0.2.x to 0.3.x. The new version introduces a more organized API using grouped properties, which provides better type safety and code organization.

Overview of Changes

Breaking Changes

  1. RelativisticEffectConfiguration renamed to PhysicsEffectConfiguration

    • The class name has been changed to better reflect its purpose.
  2. activeEffects parameter renamed to effectConfigurations

    • The Newton widget now uses effectConfigurations instead of activeEffects.
  3. Properties are now grouped into dedicated classes

    • Individual properties are now organized into grouped property classes for better organization and validation.

Step-by-Step Migration

1. Update Newton Widget Parameter

Before (0.2.x):

Newton(
activeEffects: [
// effects...
],
)

After (0.3.x):

Newton(
effectConfigurations: [
// effects...
],
)

2. Rename RelativisticEffectConfiguration

Before (0.2.x):

RelativisticEffectConfiguration(
// properties...
)

After (0.3.x):

PhysicsEffectConfiguration(
// properties...
)

3. Migrate Properties to Grouped Classes

The biggest change is that properties are now organized into grouped classes. Here's how to migrate:

Physics-Based Effects

Before (0.2.x):

RelativisticEffectConfiguration(
gravity: Gravity.earthGravity,
minAngle: 90,
maxAngle: 90,
minVelocity: Velocity.stationary,
maxVelocity: Velocity.stationary,
minEndScale: 1,
maxEndScale: 1,
minFadeOutThreshold: 0.6,
maxFadeOutThreshold: 0.8,
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
minParticleLifespan: Duration(seconds: 7),
maxParticleLifespan: Duration(seconds: 10),
particleConfiguration: ParticleConfiguration(...),
)

After (0.3.x):

PhysicsEffectConfiguration(
physicsProperties: PhysicsProperties(
gravity: Gravity.earthGravity,
angle: NumRange.single(90),
velocity: NumRange.between(Velocity.stationary, Velocity.stationary),
),
visualProperties: VisualProperties(
endScale: NumRange.single(1),
fadeOutThreshold: NumRange.between(0.6, 0.8),
),
emissionProperties: EmissionProperties(
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
particleLifespan: DurationRange.between(Duration(seconds: 7), Duration(seconds: 10)),
),
particleConfiguration: ParticleConfiguration(...),
)

Deterministic Effects

Before (0.2.x):

DeterministicEffectConfiguration(
minAngle: 90,
maxAngle: 90,
minDistance: 200,
maxDistance: 200,
minEndScale: 1,
maxEndScale: 1,
minFadeOutThreshold: 0.6,
maxFadeOutThreshold: 0.8,
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
minParticleLifespan: Duration(seconds: 4),
maxParticleLifespan: Duration(seconds: 7),
particleConfiguration: ParticleConfiguration(...),
)

After (0.3.x):

DeterministicEffectConfiguration(
deterministicProperties: DeterministicProperties(
angle: NumRange.single(90),
distance: NumRange.single(200),
),
visualProperties: VisualProperties(
endScale: NumRange.single(1),
fadeOutThreshold: NumRange.between(0.6, 0.8),
),
emissionProperties: EmissionProperties(
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
particleLifespan: DurationRange.between(Duration(seconds: 4), Duration(seconds: 7)),
),
particleConfiguration: ParticleConfiguration(...),
)

Property Group Mapping

PhysicsProperties

Groups all physics-related properties:

  • gravityphysicsProperties.gravity
  • minAngle / maxAnglephysicsProperties.angle: NumRange.between(min, max) or NumRange.single(value)
  • minVelocity / maxVelocityphysicsProperties.velocity: NumRange.between(min, max)
  • minDensity / maxDensityphysicsProperties.density: NumRange.between(min, max)
  • minFriction / maxFrictionphysicsProperties.friction: NumRange.between(min, max)
  • minRestitution / maxRestitutionphysicsProperties.restitution: NumRange.between(min, max)
  • onlyInteractWithEdgesphysicsProperties.onlyInteractWithEdges
  • solidEdgesphysicsProperties.solidEdges

VisualProperties

Groups all visual appearance properties:

  • minEndScale / maxEndScalevisualProperties.endScale: NumRange.between(min, max) or NumRange.single(value)
  • minFadeInThreshold / maxFadeInThresholdvisualProperties.fadeInThreshold: NumRange.between(min, max)
  • minFadeOutThreshold / maxFadeOutThresholdvisualProperties.fadeOutThreshold: NumRange.between(min, max)
  • scaleCurvevisualProperties.scaleCurve
  • fadeInCurvevisualProperties.fadeInCurve
  • fadeOutCurvevisualProperties.fadeOutCurve

EmissionProperties

Groups all emission-related properties. Note: EmissionProperties is now part of the base EffectConfiguration class, making it available to both PhysicsEffectConfiguration and DeterministicEffectConfiguration:

  • originemissionProperties.origin
  • minOriginOffset / maxOriginOffsetemissionProperties.minOriginOffset / maxOriginOffset
  • particleCountemissionProperties.particleCount
  • particlesPerEmitemissionProperties.particlesPerEmit
  • emitDurationemissionProperties.emitDuration
  • emitCurveemissionProperties.emitCurve
  • minParticleLifespan / maxParticleLifespanemissionProperties.particleLifespan: DurationRange.between(min, max)

DeterministicProperties

Groups deterministic-specific properties:

  • minAngle / maxAngledeterministicProperties.angle: NumRange.between(min, max)
  • minDistance / maxDistancedeterministicProperties.distance: NumRange.between(min, max)

AnimationProperties

Groups animation timing properties:

  • startDelayanimationProperties.startDelay

LayerProperties

Groups layer and trail properties:

  • particleLayerlayerProperties.particleLayer
  • traillayerProperties.trail

Using Range Helpers

The new API uses NumRange and DurationRange objects for min/max values. Use these helpers:

  • NumRange.single(value) - For a single numeric value (no variation)
  • NumRange.between(min, max) - For a numeric range between min and max
  • DurationRange.single(Duration(...)) - For a single duration value
  • DurationRange.between(Duration(...), Duration(...)) - For a duration range

Example:

// Single numeric value
endScale: NumRange.single(1)

// Numeric range
fadeOutThreshold: NumRange.between(0.6, 0.8)
velocity: NumRange.between(Velocity.custom(3), Velocity.custom(5))

// Duration range
particleLifespan: DurationRange.between(Duration(seconds: 3), Duration(seconds: 5))

Configuration Overrider Changes

If you're using configurationOverrider (formerly effectOverrider), update the copyWith call:

Before (0.2.x):

configurationOverrider: (effect) {
return effect.effectConfiguration.copyWith(
physicsProperties: effect.effectConfiguration.physicsProperties.copyWith(
angle: NumRange.single(angle),
),
);
}

After (0.3.x):

configurationOverrider: (effect) {
return effect.effectConfiguration.copyWith(
physicsProperties: effect.effectConfiguration.physicsProperties.copyWith(
angle: NumRange.single(angle),
),
);
}

Post Effect Builder Changes

When creating post effects in postEffectBuilder, use the new API:

Before (0.2.x):

postEffectBuilder: (particle, effect) {
return PhysicsEffectConfiguration(
physicsProperties: const PhysicsProperties(
gravity: Gravity.earthGravity,
angle: NumRange.between(-180, 180),
// ... other properties
);
}

After (0.3.x):

postEffectBuilder: (particle, effect) {
return PhysicsEffectConfiguration(
physicsProperties: const PhysicsProperties(
gravity: Gravity.earthGravity,
angle: NumRange.between(-180, 180),
),
// ... other grouped properties
);
}

Benefits of the New API

  1. Better Organization: Properties are logically grouped, making configurations easier to understand and maintain.

  2. Type Safety: Grouped properties provide better validation and type checking.

  3. Consistency: Both physics and deterministic effects use similar property grouping patterns.

  4. Extensibility: New properties can be added to appropriate groups without cluttering the main configuration class.

Common Patterns

Rain Effect Migration

Before:

RelativisticEffectConfiguration(
gravity: Gravity.earthGravity,
minAngle: 90,
maxAngle: 90,
minVelocity: Velocity.stationary,
maxVelocity: Velocity.stationary,
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
minParticleLifespan: Duration(seconds: 7),
maxParticleLifespan: Duration(seconds: 10),
particleConfiguration: ParticleConfiguration(...),
)

After:

PhysicsEffectConfiguration(
physicsProperties: const PhysicsProperties(
gravity: Gravity.earthGravity,
angle: NumRange.single(90),
velocity: NumRange.between(Velocity.stationary, Velocity.stationary),
),
emissionProperties: const EmissionProperties(
origin: Offset.zero,
maxOriginOffset: Offset(1, 0),
particleLifespan: DurationRange.between(Duration(seconds: 7), Duration(seconds: 10)),
),
particleConfiguration: ParticleConfiguration(...),
)

Need Help?

If you encounter issues during migration, please:

  1. Check the updated documentation
  2. Review the effect samples for examples
  3. Open an issue on GitHub