Fix nine-slice seams and inherited alpha

This commit is contained in:
gem
2026-06-09 13:52:07 +08:00
parent 638ea22562
commit 4ce5fe1ae7
4 changed files with 156 additions and 4 deletions

View File

@@ -116,6 +116,90 @@ void main() {
expect(component.renderAlpha, 1);
});
test('inherits parent alpha for prefab-like subtrees', () async {
final parent = RuntimeComponent(
node: const RuntimeNode(
id: 'parent',
type: RuntimeNodeType.panel,
alpha: 0.8,
),
resources: GameResourceManager(),
onNodeTap: (_, __) {},
);
final child = RuntimeComponent(
node: const RuntimeNode(
id: 'child',
type: RuntimeNodeType.text,
text: 'Child',
alpha: 0.5,
color: Color(0xffffffff),
),
resources: GameResourceManager(),
onNodeTap: (_, __) {},
);
parent.add(child);
parent.updateTree(0);
child.setInheritedAlpha(parent.renderAlpha);
expect(child.renderAlpha, closeTo(0.4, 0.001));
final text = child.children.whereType<TextComponent>().single;
expect(
((text.textRenderer as TextPaint).style.color!).a,
closeTo(0.4, 0.003),
);
parent.setRuntimeAlpha(0.25);
expect(child.renderAlpha, closeTo(0.125, 0.001));
final updatedText = child.children.whereType<TextComponent>().single;
expect(identical(updatedText, text), isTrue);
expect(
((updatedText.textRenderer as TextPaint).style.color!).a,
closeTo(0.125, 0.003),
);
});
test('propagates parent node alpha updates to child subtree', () {
final parent = RuntimeComponent(
node: const RuntimeNode(
id: 'parent',
type: RuntimeNodeType.panel,
alpha: 0.8,
),
resources: GameResourceManager(),
onNodeTap: (_, __) {},
);
final child = RuntimeComponent(
node: const RuntimeNode(
id: 'child',
type: RuntimeNodeType.text,
text: 'Child',
alpha: 0.5,
color: Color(0xffffffff),
),
resources: GameResourceManager(),
onNodeTap: (_, __) {},
);
parent.add(child);
parent.updateTree(0);
child.setInheritedAlpha(parent.renderAlpha);
parent.updateNode(
const RuntimeNode(
id: 'parent',
type: RuntimeNodeType.panel,
alpha: 0.6,
),
);
final text = child.children.whereType<TextComponent>().single;
expect(child.renderAlpha, closeTo(0.3, 0.001));
expect(
((text.textRenderer as TextPaint).style.color!).a,
closeTo(0.3, 0.003),
);
});
test('multiplies color alpha with node and runtime alpha', () {
expect(
composeRuntimeColorAlpha(const Color(0xffffffff), 1).a,
@@ -183,6 +267,23 @@ void main() {
expect(parts.last.destination, const Rect.fromLTRB(83, 112, 90, 120));
});
test('overlaps nine-slice destination seams without changing bounds', () {
final parts = runtimeNineSliceRects(
source: const Rect.fromLTWH(0, 0, 30, 30),
destination: const Rect.fromLTWH(0, 0, 90, 90),
sliceLeft: 10,
sliceTop: 10,
sliceRight: 10,
sliceBottom: 10,
destinationOverlap: 0.5,
);
expect(parts.first.destination, const Rect.fromLTRB(0, 0, 10.5, 10.5));
expect(parts[4].destination, const Rect.fromLTRB(9.5, 9.5, 80.5, 80.5));
expect(parts.last.destination, const Rect.fromLTRB(79.5, 79.5, 90, 90));
expect(parts[4].source, const Rect.fromLTRB(10, 10, 20, 20));
});
test('updates text alpha style without rebuilding text component', () {
final component = RuntimeComponent(
node: const RuntimeNode(