Skip to content

Commit

Permalink
feat: Add advanced button component (#2742)
Browse files Browse the repository at this point in the history
New button with support for multiple states:
<img width="278" alt="image"
src="https://github.com/flame-engine/flame/assets/18004353/041c1105-8991-4976-b1a2-0553c149ec4e">
  • Loading branch information
denisgl7 committed Oct 10, 2023
1 parent cccae2e commit 97fff0e
Show file tree
Hide file tree
Showing 9 changed files with 1,098 additions and 0 deletions.
30 changes: 30 additions & 0 deletions doc/flame/inputs/other_inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,33 @@ else which isn't a pure sprite.

Flame has a separate plugin to support external game controllers (gamepads), check
[here](https://github.com/flame-engine/flame_gamepad) for more information.


## AdvancedButtonComponent

The `AdvancedButtonComponent` have separate states for each of the different pointer phases.
The skin can be customized for each state and each skin is represented by a `PositionComponent`.

These are the fields that can be used to customize the looks of the `AdvancedButtonComponent`:

- `defaultSkin`: Component that will be displayed by default on the button.
- `downSkin`: Component displayed when the button is clicked or tapped.
- `hoverSkin`: Component displayed when the button is hovered. (desktop and web).
- `defaultLabel`: Component shown on top of skins. Automatically aligned to center.
- `disabledSkin`: Component displayed when button is disabled.
- `disabledLabel`: Component shown on top of skins when button is disabled.


## ToggleButtonComponent

The [ToggleButtonComponent] is an [AdvancedButtonComponent] that can switch between selected
and not selected.

In addition to the already existing skins, the [ToggleButtonComponent] contains the following skins:

- `defaultSelectedSkin`: The component to display when the button is selected.
- `downAndSelectedSkin`: The component that is displayed when the selectable button is selected and
pressed.
- `hoverAndSelectedSkin`: Hover on selectable and selected button (desktop and web).
- `disabledAndSelectedSkin`: For when the button is selected and in the disabled state.
- `defaultSelectedLabel`: Component shown on top of the skins when button is selected.
125 changes: 125 additions & 0 deletions examples/lib/stories/input/advanced_button_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/painting.dart';

class AdvancedButtonExample extends FlameGame {
static const String description =
'''This example shows how you can use a button with different states''';

@override
Future<void> onLoad() async {
final defaultButton = DefaultButton();
defaultButton.position = Vector2(50, 50);
defaultButton.size = Vector2(250, 50);
add(defaultButton);

final disableButton = DisableButton();
disableButton.isDisabled = true;
disableButton.position = Vector2(400, 50);
disableButton.size = defaultButton.size;
add(disableButton);

final toggleButton = ToggleButton();
toggleButton.position = Vector2(50, 150);
toggleButton.size = defaultButton.size;
add(toggleButton);
}
}

class ToggleButton extends ToggleButtonComponent {
@override
Future<void> onLoad() async {
super.onLoad();

defaultLabel = TextComponent(
text: 'Toggle button',
textRenderer: TextPaint(
style: TextStyle(
fontSize: 24,
color: BasicPalette.white.color,
),
),
);

defaultSelectedLabel = TextComponent(
text: 'Toggle button',
textRenderer: TextPaint(
style: TextStyle(
fontSize: 24,
color: BasicPalette.red.color,
),
),
);

defaultSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 200, 0, 1));

hoverSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 180, 0, 1));

downSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 100, 0, 1));

defaultSelectedSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 0, 200, 1));

hoverAndSelectedSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 0, 180, 1));

downAndSelectedSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 0, 100, 1));
}
}

class DefaultButton extends AdvancedButtonComponent {
@override
Future<void> onLoad() async {
super.onLoad();

defaultLabel = TextComponent(text: 'Default button');

defaultSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 200, 0, 1));

hoverSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 180, 0, 1));

downSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 100, 0, 1));
}
}

class DisableButton extends AdvancedButtonComponent {
@override
Future<void> onLoad() async {
super.onLoad();

disabledLabel = TextComponent(text: 'Disabled button');

defaultSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(0, 255, 0, 1));

disabledSkin = RoundedRectComponent()
..setColor(const Color.fromRGBO(100, 100, 100, 1));
}
}

class RoundedRectComponent extends PositionComponent with HasPaint {
@override
void render(Canvas canvas) {
canvas.drawRRect(
RRect.fromLTRBAndCorners(
0,
0,
width,
height,
topLeft: Radius.circular(height),
topRight: Radius.circular(height),
bottomRight: Radius.circular(height),
bottomLeft: Radius.circular(height),
),
paint,
);
}
}
7 changes: 7 additions & 0 deletions examples/lib/stories/input/input.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:dashbook/dashbook.dart';
import 'package:examples/commons/commons.dart';
import 'package:examples/stories/input/advanced_button_example.dart';
import 'package:examples/stories/input/double_tap_callbacks_example.dart';
import 'package:examples/stories/input/draggables_example.dart';
import 'package:examples/stories/input/gesture_hitboxes_example.dart';
Expand Down Expand Up @@ -129,5 +130,11 @@ void addInputStories(Dashbook dashbook) {
(_) => GameWidget(game: JoystickAdvancedExample()),
codeLink: baseLink('input/joystick_advanced_example.dart'),
info: JoystickAdvancedExample.description,
)
..add(
'Advanced Button',
(_) => GameWidget(game: AdvancedButtonExample()),
codeLink: baseLink('input/advanced_button_example.dart'),
info: AdvancedButtonExample.description,
);
}
2 changes: 2 additions & 0 deletions packages/flame/lib/components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ export 'src/components/core/position_type.dart';
export 'src/components/custom_painter_component.dart';
export 'src/components/fps_component.dart';
export 'src/components/fps_text_component.dart';
export 'src/components/input/advanced_button_component.dart';
export 'src/components/input/joystick_component.dart';
export 'src/components/input/keyboard_listener_component.dart';
export 'src/components/input/toggle_button_component.dart';
export 'src/components/isometric_tile_map_component.dart';
export 'src/components/mixins/component_viewport_margin.dart';
export 'src/components/mixins/coordinate_transform.dart';
Expand Down
Loading

0 comments on commit 97fff0e

Please sign in to comment.