Skip to content

feat: Add HueEffect and HueDecorator#3852

Open
s1r1m1r1 wants to merge 7 commits intoflame-engine:mainfrom
s1r1m1r1:main
Open

feat: Add HueEffect and HueDecorator#3852
s1r1m1r1 wants to merge 7 commits intoflame-engine:mainfrom
s1r1m1r1:main

Conversation

@s1r1m1r1
Copy link
Contributor

@s1r1m1r1 s1r1m1r1 commented Mar 8, 2026

Description

This PR adds a new
HueEffect
to the Flame effects library. This effect allows animating the hue shift of a component's paint over time.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

@s1r1m1r1 s1r1m1r1 changed the title feat: Add HueEffect feat: Add HueEffect , add HueDecorator Mar 8, 2026
@spydon spydon changed the title feat: Add HueEffect , add HueDecorator feat: Add HueEffect and HueDecorator Mar 8, 2026
Copy link
Member

@spydon spydon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs and examples are missing, other than that it looks good!

@s1r1m1r1
Copy link
Contributor Author

s1r1m1r1 commented Mar 8, 2026

⚠️ Performance Warning: Decorators vs. Effects

This PR provides two ways to apply visual transformations: Decorators and Effects. It is crucial to understand their performance profiles:

Decorators (e.g., HueDecorator): This use canvas.saveLayer() to isolate the component's rendering and apply filters.

Pros: Highly flexible; supports complex chaining of multiple effects; works on any custom draw logic.
Cons: Significant performance overhead. Each saveLayer requires an off-screen buffer allocation and a GPU context switch. In high-density benchmarks (100+ sprites), this can be up to 20x slower than direct paint manipulation.

Effects (e.g., HueEffect): These modify the component's Paint(specifically colorFilter) directly.
Pros: Extremely fast. Hardware-accelerated directly in the fragment shader with zero memory allocation overhead.
Cons: Less flexible for complex layering; only works on components that expose a Paint.

Recommendation: Always prefer Effects for simple color/hue shifts on large numbers of units. Use Decorators only when you need complex visual composition or when targeting raw canvas drawing that isn't governed by a single

@spydon
Copy link
Member

spydon commented Mar 8, 2026

⚠️ Performance Warning: Decorators vs. Effects

This PR provides two ways to apply visual transformations: Decorators and Effects. It is crucial to understand their performance profiles:

Decorators (e.g., HueDecorator): This use canvas.saveLayer() to isolate the component's rendering and apply filters.

Pros: Highly flexible; supports complex chaining of multiple effects; works on any custom draw logic.
Cons: Significant performance overhead. Each saveLayer requires an off-screen buffer allocation and a GPU context switch. In high-density benchmarks (100+ sprites), this can be up to 20x slower than direct paint manipulation.

Effects (e.g., HueEffect): These modify the component's Paint(specifically colorFilter) directly.
Pros: Extremely fast. Hardware-accelerated directly in the fragment shader with zero memory allocation overhead.
Cons: Less flexible for complex layering; only works on components that expose a Paint.

Recommendation: Always prefer Effects for simple color/hue shifts on large numbers of units. Use Decorators only when you need complex visual composition or when targeting raw canvas drawing that isn't governed by a single

This should be a general comment on decorators in the docs, if it's not already in there.

'decorator_rotate3d': DecoratorRotate3DGame.new,
'decorator_shadow3d': DecoratorShadowGame.new,
'decorator_tint': DecoratorTintGame.new,
'decorator_hue': HueDecoratorGame.new,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow alphabetical order

Comment on lines +9 to +10
In this example we show how the `HueEffect` can be used.
Ember will shift its hue over time.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this example we show how the `HueEffect` can be used.
Ember will shift its hue over time.
In this example we show how the `HueEffect` can be used.
Ember will shift its hue over time.

Future<void> onLoad() async {
add(
Ember(
position: Vector2(size.x / 2, size.y / 2),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
position: Vector2(size.x / 2, size.y / 2),
position: size / 2,

Comment on lines +10 to +11
In this example we show how the `HueDecorator` can be used.
Click anywhere to cycle through different hue shifts on Ember.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this example we show how the `HueDecorator` can be used.
Click anywhere to cycle through different hue shifts on Ember.
In this example we show how the `HueDecorator` can be used.
Click anywhere to cycle through different hue shifts on Ember.

@override
Future<void> onLoad() async {
add(
ember = Ember(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to use nested components in this example to show when a decorator can be used when an effect doesn't work.

@@ -1,13 +1,17 @@
# Decorators
## Performance Warning: Decorators vs Effects
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main section should still be Decorators and have a description about what decorators are, it shouldn't start with a warning before the user knows what they are reading about.

Comment on lines +18 to +19
..add(
'Hue Decorator',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add a new section called decorators, since we're missing examples for the rest of the decorators.

/// a component and requires that the component implement [PaintProvider].
class HueEffect extends Effect with EffectTarget<PaintProvider> {
HueEffect(
this.angle,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need both a To and a By effect, similar to MoveToEffect and MoveByEffect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants