Skip to content

Commit 22d4ac6

Browse files
dwa
1 parent da09cbe commit 22d4ac6

11 files changed

Lines changed: 325 additions & 101 deletions

lib/components/animation/animation_view.dart

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ class _AnimationViewState extends State<AnimationView> {
9292
if (doc == null) {
9393
_ticker?.cancel();
9494
_ticker = null;
95-
return const dom.div(classes: 'hui-animation-player is-empty', <Widget>[]);
95+
return const dom.div(
96+
classes: 'hui-animation-player is-empty',
97+
<Widget>[],
98+
);
9699
}
97100
_syncTicker(doc);
98101
final String id = _store.menuId;
@@ -103,7 +106,10 @@ class _AnimationViewState extends State<AnimationView> {
103106
dom.div(classes: 'hui-animation-frame-stage', <Widget>[
104107
dom.div(classes: 'hui-animation-frame-large', <Widget>[
105108
GlossTextLine(
106-
render: renderGlossLine(frame, emoji: _store.workspaceEmoji),
109+
render: renderGlossAnimationFramePreview(
110+
frame,
111+
emoji: _store.workspaceEmoji,
112+
),
107113
),
108114
]),
109115
dom.div(classes: 'hui-animation-frame-meta', <Widget>[
@@ -171,39 +177,40 @@ class _AnimationViewState extends State<AnimationView> {
171177
),
172178
]);
173179

174-
Widget _strip(GlossAnimationDoc doc, String id, int index) =>
175-
dom.div(classes: 'hui-animation-strip', <Widget>[
176-
for (int i = 0; i < doc.frames.length; i++)
177-
dom.button(
178-
classes: 'hui-animation-strip-frame${i == index ? ' is-active' : ''}',
179-
attributes: <String, String>{
180-
'type': 'button',
181-
'aria-label': 'Show frame ${i + 1}',
182-
},
183-
events: <String, EventCallback>{
184-
'click': (Object? _) => setState(() => _player.scrubTo(i, doc)),
185-
},
186-
<Widget>[
187-
dom.span(classes: 'hui-animation-strip-index', <Widget>[
188-
Text('${i + 1}'),
189-
]),
190-
GlossTextLine(
191-
render: renderGlossLine(
192-
doc.frames[i],
193-
emoji: _store.workspaceEmoji,
194-
),
180+
Widget _strip(GlossAnimationDoc doc, String id, int index) => dom.div(
181+
classes: 'hui-animation-strip',
182+
<Widget>[
183+
for (int i = 0; i < doc.frames.length; i++)
184+
dom.button(
185+
classes: 'hui-animation-strip-frame${i == index ? ' is-active' : ''}',
186+
attributes: <String, String>{
187+
'type': 'button',
188+
'aria-label': 'Show frame ${i + 1}',
189+
},
190+
events: <String, EventCallback>{
191+
'click': (Object? _) => setState(() => _player.scrubTo(i, doc)),
192+
},
193+
<Widget>[
194+
dom.span(classes: 'hui-animation-strip-index', <Widget>[
195+
Text('${i + 1}'),
196+
]),
197+
GlossTextLine(
198+
render: renderGlossAnimationFramePreview(
199+
doc.frames[i],
200+
emoji: _store.workspaceEmoji,
195201
),
196-
],
197-
),
198-
]);
202+
),
203+
],
204+
),
205+
],
206+
);
199207

200208
/// The range input's value, off `event.target.value`.
201209
static String? _rangeValue(Object? event) {
202210
final JSObject? object = event as JSObject?;
203211
final JSAny? target = object?.getProperty<JSAny?>('target'.toJS);
204212
if (target == null || !target.isA<JSObject>()) return null;
205-
final JSAny? value =
206-
(target as JSObject).getProperty<JSAny?>('value'.toJS);
213+
final JSAny? value = (target as JSObject).getProperty<JSAny?>('value'.toJS);
207214
return value.isA<JSString>() ? (value! as JSString).toDart : null;
208215
}
209216
}

lib/config/gloss_templates.dart

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,68 @@ const String kGlossAnimationRainbowJson = r'''
6161
"schemaVersion": 1,
6262
"revision": 1,
6363
"mode": "ascend",
64-
"frameIntervalMs": 500,
64+
"frameIntervalMs": 50,
6565
"frames": [
66-
"&c",
67-
"&6",
68-
"&a",
69-
"&b"
66+
"[FF0000]",
67+
"[FF1A00]",
68+
"[FF3300]",
69+
"[FF4D00]",
70+
"[FF6600]",
71+
"[FF8000]",
72+
"[FF9900]",
73+
"[FFB300]",
74+
"[FFCC00]",
75+
"[FFE600]",
76+
"[FFFF00]",
77+
"[E5FF00]",
78+
"[CCFF00]",
79+
"[B2FF00]",
80+
"[99FF00]",
81+
"[7FFF00]",
82+
"[66FF00]",
83+
"[4CFF00]",
84+
"[33FF00]",
85+
"[19FF00]",
86+
"[00FF00]",
87+
"[00FF1A]",
88+
"[00FF33]",
89+
"[00FF4D]",
90+
"[00FF66]",
91+
"[00FF80]",
92+
"[00FF99]",
93+
"[00FFB3]",
94+
"[00FFCC]",
95+
"[00FFE6]",
96+
"[00FFFF]",
97+
"[00E5FF]",
98+
"[00CCFF]",
99+
"[00B2FF]",
100+
"[0099FF]",
101+
"[007FFF]",
102+
"[0066FF]",
103+
"[004CFF]",
104+
"[0033FF]",
105+
"[0019FF]",
106+
"[0000FF]",
107+
"[1A00FF]",
108+
"[3300FF]",
109+
"[4D00FF]",
110+
"[6600FF]",
111+
"[8000FF]",
112+
"[9900FF]",
113+
"[B300FF]",
114+
"[CC00FF]",
115+
"[E600FF]",
116+
"[FF00FF]",
117+
"[FF00E5]",
118+
"[FF00CC]",
119+
"[FF00B2]",
120+
"[FF0099]",
121+
"[FF007F]",
122+
"[FF0066]",
123+
"[FF004C]",
124+
"[FF0033]",
125+
"[FF0019]"
70126
]
71127
}
72128
''';
@@ -128,7 +184,7 @@ const String kGlossScoreboardShowcaseJson = r'''
128184
"&7Tick &f{{ fixed(metric('react.tick-ms', 1000 / server.tps), 1) }}ms",
129185
"&7Balance &6${{ fixed(papiNumber('vault_eco_balance', 0), 2) }}",
130186
"",
131-
"|animation.rainbow|&lLIVE EVENT",
187+
"&d{{ select(['·', '•', '●', '•'], floor(time.seconds * 8)) }} &f&lLIVE EVENT",
132188
"&d:heart: &fWelcome!",
133189
"&bplay.example.net"
134190
],
@@ -310,7 +366,7 @@ const String kGlossTablistShowcaseJson = r'''
310366
"groupListNames": true,
311367
"nameFormats": {
312368
"default": "&7$player",
313-
"_op": "{{ select(['&c', '&6', '&d'], floor(time.seconds * 4)) }}&l[OP] &f$player",
369+
"_op": "{{ hex(mix(#FF3355, #FF55FF, (sin(time.seconds * 4) + 1) / 2)) }}&l[OP] &f$player",
314370
"vip": "&6[$group] &f$player"
315371
}
316372
}

lib/doctype/animation_document_type.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ final class AnimationDocumentType extends GlossDocumentTypeAdapter {
8585
id: 'animation-rainbow',
8686
name: 'Rainbow',
8787
description:
88-
'The shipped default: four colour-only frames on a 500 ms '
89-
'ascend. Prefix text with |animation.rainbow| to colour it '
90-
'without inserting another word.',
91-
highlights: const <String>['Shipped default', '4 frames'],
88+
'The shipped default: a 60-step RGB hue gradient advancing '
89+
'once per tick. Prefix text with |animation.rainbow| to '
90+
'colour it without inserting another word.',
91+
highlights: const <String>['Shipped default', 'Smooth RGB'],
9292
create: (EditorStore store) => store.newGlossDocument(
9393
this,
9494
name: 'rainbow',

lib/doctype/tablist_document_type.dart

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -78,42 +78,42 @@ final class TablistDocumentType extends GlossDocumentTypeAdapter {
7878
'opens as a new document, so your current one is untouched.';
7979

8080
@override
81-
List<DocumentTemplateSection> get templateSections =>
82-
<DocumentTemplateSection>[
83-
DocumentTemplateSection(
84-
templates: <DocumentTemplate>[
85-
DocumentTemplate(
86-
id: 'tablist-default',
87-
name: 'Default tablist',
88-
description:
89-
'The shipped default: Gloss header, VolmitSoftware footer, '
90-
'plain default names and gold operators. Exactly what '
91-
'plugins/Gloss/tablist.json starts with.',
92-
highlights: const <String>['Shipped default', '2 formats'],
93-
create: (EditorStore store) => store.newGlossDocument(
94-
this,
95-
name: 'tablist',
96-
from: buildDefaultGlossTablist(),
97-
),
98-
),
99-
DocumentTemplate(
100-
id: 'tablist-showcase',
101-
name: 'Grouped showcase',
102-
description:
103-
'A live RGB header with PAPI, ping and metrics, an animated '
104-
'footer, and group formats including authored colour cycles.',
105-
highlights: const <String>[
106-
'3 formats',
107-
'PAPI + metrics',
108-
'Authored animation',
109-
],
110-
create: (EditorStore store) => store.newGlossDocument(
111-
this,
112-
name: 'tablist',
113-
from: buildShowcaseGlossTablist(),
114-
),
115-
),
81+
List<DocumentTemplateSection>
82+
get templateSections => <DocumentTemplateSection>[
83+
DocumentTemplateSection(
84+
templates: <DocumentTemplate>[
85+
DocumentTemplate(
86+
id: 'tablist-default',
87+
name: 'Default tablist',
88+
description:
89+
'The shipped default: Gloss header, VolmitSoftware footer, '
90+
'plain default names and gold operators. Exactly what '
91+
'plugins/Gloss/tablist.json starts with.',
92+
highlights: const <String>['Shipped default', '2 formats'],
93+
create: (EditorStore store) => store.newGlossDocument(
94+
this,
95+
name: 'tablist',
96+
from: buildDefaultGlossTablist(),
97+
),
98+
),
99+
DocumentTemplate(
100+
id: 'tablist-showcase',
101+
name: 'Grouped showcase',
102+
description:
103+
'A live RGB header with PAPI, ping and metrics, an animated '
104+
'footer, and group formats including smooth authored RGB animation.',
105+
highlights: const <String>[
106+
'3 formats',
107+
'PAPI + metrics',
108+
'Authored animation',
116109
],
110+
create: (EditorStore store) => store.newGlossDocument(
111+
this,
112+
name: 'tablist',
113+
from: buildShowcaseGlossTablist(),
114+
),
117115
),
118-
];
116+
],
117+
),
118+
];
119119
}

lib/logic/gloss_text.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,22 @@ GlossLineRender renderGlossLine(
262262
expressionSamples: expressionSamples,
263263
);
264264

265+
GlossLineRender renderGlossAnimationFramePreview(
266+
String raw, {
267+
GlossEmojiResolver emoji = const GlossNoEmoji(),
268+
}) {
269+
final GlossLineRender rendered = renderGlossLine(raw, emoji: emoji);
270+
final bool hasVisibleContent = rendered.pieces.any(
271+
(GlossTextPiece piece) => switch (piece) {
272+
GlossTextRun(:final McSpan span) => span.text.isNotEmpty,
273+
GlossPlaceholderChip() || GlossMetricChip() => true,
274+
},
275+
);
276+
return hasVisibleContent
277+
? rendered
278+
: renderGlossLine('$raw&lRAINBOW', emoji: emoji);
279+
}
280+
265281
GlossLineRender renderGlossScoreboardTitle(
266282
String raw, {
267283
GlossAnimationResolver animations = const GlossNoAnimations(),

0 commit comments

Comments
 (0)