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

@@ -327,6 +327,7 @@ class RenderTreeController {
contentOffsetY: parentContentOffset.y,
);
component.setViewportCulled(_isCulledByParentListView(component, parent));
component.setInheritedAlpha(parent?.renderAlpha ?? 1);
if (component.parent == target) {
return;
}

View File

@@ -43,6 +43,7 @@ List<({Rect source, Rect destination})> runtimeNineSliceRects({
double sliceTop = 0,
double sliceRight = 0,
double sliceBottom = 0,
double destinationOverlap = 0,
}) {
if (source.width <= 0 ||
source.height <= 0 ||
@@ -93,7 +94,7 @@ List<({Rect source, Rect destination})> runtimeNineSliceRects({
sourceXs[x + 1],
sourceYs[y + 1],
);
final destPart = Rect.fromLTRB(
final rawDestPart = Rect.fromLTRB(
destXs[x],
destYs[y],
destXs[x + 1],
@@ -101,16 +102,41 @@ List<({Rect source, Rect destination})> runtimeNineSliceRects({
);
if (sourcePart.width <= 0 ||
sourcePart.height <= 0 ||
destPart.width <= 0 ||
destPart.height <= 0) {
rawDestPart.width <= 0 ||
rawDestPart.height <= 0) {
continue;
}
final destPart = _overlapNineSliceDestinationRect(
rawDestPart,
x: x,
y: y,
bounds: destination,
overlap: destinationOverlap,
);
parts.add((source: sourcePart, destination: destPart));
}
}
return parts;
}
Rect _overlapNineSliceDestinationRect(
Rect rect, {
required int x,
required int y,
required Rect bounds,
required double overlap,
}) {
if (overlap <= 0) {
return rect;
}
return Rect.fromLTRB(
x == 0 ? rect.left : math.max(bounds.left, rect.left - overlap),
y == 0 ? rect.top : math.max(bounds.top, rect.top - overlap),
x == 2 ? rect.right : math.min(bounds.right, rect.right + overlap),
y == 2 ? rect.bottom : math.min(bounds.bottom, rect.bottom + overlap),
);
}
class RuntimeComponent extends PositionComponent
with HasVisibility, TapCallbacks {
RuntimeComponent({
@@ -157,8 +183,11 @@ class RuntimeComponent extends PositionComponent
double _parentContentOffsetY = 0;
bool _viewportCulled = false;
bool _pressed = false;
double _inheritedAlpha = 1;
double get renderAlpha => _runtimeAlpha ?? _node.alpha;
double get localAlpha => _runtimeAlpha ?? _node.alpha;
double get renderAlpha => (_inheritedAlpha * localAlpha).clamp(0.0, 1.0);
void setRuntimeAlpha(double value) {
final next = value.clamp(0, 1).toDouble();
@@ -166,7 +195,23 @@ class RuntimeComponent extends PositionComponent
return;
}
_runtimeAlpha = next;
_refreshInheritedAlphaSubtree();
}
void setInheritedAlpha(double value) {
final next = value.clamp(0, 1).toDouble();
if (_inheritedAlpha == next) {
return;
}
_inheritedAlpha = next;
_refreshInheritedAlphaSubtree();
}
void _refreshInheritedAlphaSubtree() {
_syncTextStyle(_node);
for (final child in children.whereType<RuntimeComponent>()) {
child.setInheritedAlpha(renderAlpha);
}
}
void setParentScroll({
@@ -194,6 +239,7 @@ class RuntimeComponent extends PositionComponent
_syncImage(node);
_syncSpine(node);
_syncParticle(node);
_refreshInheritedAlphaSubtree();
}
bool containsVisualPoint(Vector2 point) {
@@ -584,6 +630,7 @@ class RuntimeComponent extends PositionComponent
final parts = runtimeNineSliceRects(
source: source,
destination: destination,
destinationOverlap: 0.5,
sliceLeft: _node.sliceLeft ?? 0,
sliceTop: _node.sliceTop ?? 0,
sliceRight: _node.sliceRight ?? 0,
@@ -1174,6 +1221,7 @@ class RuntimeComponent extends PositionComponent
_releaseLoadedSpine();
_releaseParticle();
_runtimeAlpha = null;
_inheritedAlpha = 1;
_pressed = false;
_textComponent = null;
super.onRemove();