Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boundary detection fixes #377

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 60 additions & 34 deletions src/core/CoreNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
type RectWithValid,
createBound,
boundInsideBound,
boundLargeThanBound,
} from './lib/utils.js';
import { Matrix3d } from './lib/Matrix3d.js';
import { RenderCoords } from './lib/RenderCoords.js';
Expand Down Expand Up @@ -698,6 +699,7 @@ export class CoreNode extends EventEmitter {
readonly props: CoreNodeProps;

public updateType = UpdateType.All;
public childUpdateType = UpdateType.None;

public globalTransform?: Matrix3d;
public scaleRotateTransform?: Matrix3d;
Expand Down Expand Up @@ -847,7 +849,7 @@ export class CoreNode extends EventEmitter {
// If we're updating this node at all, we need to inform the parent
// (and all ancestors) that their children need updating as well
const parent = this.props.parent;
if (parent && !(parent.updateType & UpdateType.Children)) {
if (parent !== null && !(parent.updateType & UpdateType.Children)) {
parent.setUpdateType(UpdateType.Children);
}
// If node is part of RTT texture
Expand Down Expand Up @@ -957,7 +959,6 @@ export class CoreNode extends EventEmitter {
}

const parent = this.props.parent;
let childUpdateType = UpdateType.None;

if (this.updateType & UpdateType.ParentRenderTexture) {
let p = this.parent;
Expand Down Expand Up @@ -1004,7 +1005,7 @@ export class CoreNode extends EventEmitter {
this.setUpdateType(UpdateType.Clipping);
}

childUpdateType |= UpdateType.Global;
this.childUpdateType |= UpdateType.Global;
}

if (this.updateType & UpdateType.RenderBounds) {
Expand All @@ -1023,16 +1024,15 @@ export class CoreNode extends EventEmitter {
}

if (this.renderState === CoreNodeRenderState.OutOfBounds) {
this.updateType = 0;
return;
}

if (this.updateType & UpdateType.Clipping) {
this.calculateClippingRect(parentClippingRect);
this.setUpdateType(UpdateType.Children);

childUpdateType |= UpdateType.Clipping;
childUpdateType |= UpdateType.RenderBounds;
this.childUpdateType |= UpdateType.Clipping;
this.childUpdateType |= UpdateType.RenderBounds;
}

if (this.updateType & UpdateType.WorldAlpha) {
Expand All @@ -1046,7 +1046,7 @@ export class CoreNode extends EventEmitter {
UpdateType.PremultipliedColors |
UpdateType.IsRenderable,
);
childUpdateType |= UpdateType.WorldAlpha;
this.childUpdateType |= UpdateType.WorldAlpha;
}

if (this.updateType & UpdateType.PremultipliedColors) {
Expand Down Expand Up @@ -1097,15 +1097,20 @@ export class CoreNode extends EventEmitter {
this.children.length > 0 &&
this.rtt === false
) {
this.children.forEach((child) => {
// Trigger the depenedent update types on the child
child.setUpdateType(childUpdateType);
// If child has no updates, skip
for (let i = 0; i < this.children.length; i++) {
const child = this.children[i];
if (child === undefined) {
continue;
}

child.setUpdateType(this.childUpdateType);

if (child.updateType === 0) {
return;
continue;
}

child.update(delta, this.clippingRect);
});
}
}

// Sorting children MUST happen after children have been updated so
Expand All @@ -1117,6 +1122,7 @@ export class CoreNode extends EventEmitter {

// reset update type
this.updateType = 0;
this.childUpdateType = 0;
}

//check if CoreNode is renderable based on props
Expand Down Expand Up @@ -1190,6 +1196,19 @@ export class CoreNode extends EventEmitter {
return CoreNodeRenderState.InBounds;
}

// check if we're larger then our parent, we're definitely in the viewport
if (boundLargeThanBound(this.renderBound, this.strictBound)) {
return CoreNodeRenderState.InViewport;
}

// check if we dont have dimensions, take our parent's render state
if (
this.parent !== null &&
(this.props.width === 0 || this.props.height === 0)
) {
return this.parent.renderState;
}

return CoreNodeRenderState.OutOfBounds;
}

Expand All @@ -1204,6 +1223,27 @@ export class CoreNode extends EventEmitter {
);
}

updateBoundingRect() {
const { renderCoords, globalTransform: transform } = this;
assertTruthy(transform);
assertTruthy(renderCoords);

const { tb, tc } = transform;
const { x1, y1, x3, y3 } = renderCoords;
if (tb === 0 || tc === 0) {
this.renderBound = createBound(x1, y1, x3, y3, this.renderBound);
} else {
const { x2, x4, y2, y4 } = renderCoords;
this.renderBound = createBound(
Math.min(x1, x2, x3, x4),
Math.min(y1, y2, y3, y4),
Math.max(x1, x2, x3, x4),
Math.max(y1, y2, y3, y4),
this.renderBound,
);
}
}

createRenderBounds(): void {
assertTruthy(this.stage);

Expand Down Expand Up @@ -1330,26 +1370,6 @@ export class CoreNode extends EventEmitter {
}
}

updateBoundingRect() {
const { renderCoords, globalTransform: transform } = this;
assertTruthy(transform);
assertTruthy(renderCoords);

const { tb, tc } = transform;
const { x1, y1, x3, y3 } = renderCoords;
if (tb === 0 || tc === 0) {
this.renderBound = createBound(x1, y1, x3, y3, this.renderBound);
} else {
const { x2, x4, y2, y4 } = renderCoords;
this.renderBound = createBound(
Math.min(x1, x2, x3, x4),
Math.min(y1, y2, y3, y4),
Math.max(x1, x2, x3, x4),
Math.max(y1, y2, y3, y4),
this.renderBound,
);
}
}
/**
* This function calculates the clipping rectangle for a node.
*
Expand Down Expand Up @@ -1707,7 +1727,12 @@ export class CoreNode extends EventEmitter {

set alpha(value: number) {
this.props.alpha = value;
this.setUpdateType(UpdateType.PremultipliedColors | UpdateType.WorldAlpha);
this.setUpdateType(
UpdateType.PremultipliedColors |
UpdateType.WorldAlpha |
UpdateType.Children,
);
this.childUpdateType |= UpdateType.Global;
}

get autosize(): boolean {
Expand All @@ -1727,6 +1752,7 @@ export class CoreNode extends EventEmitter {
this.setUpdateType(
UpdateType.Clipping | UpdateType.RenderBounds | UpdateType.Children,
);
this.childUpdateType |= UpdateType.Global | UpdateType.Clipping;
}

get color(): number {
Expand Down
9 changes: 9 additions & 0 deletions src/core/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ export function boundInsideBound(bound1: Bound, bound2: Bound) {
);
}

export function boundLargeThanBound(bound1: Bound, bound2: Bound) {
return (
bound1.x1 < bound2.x1 &&
bound1.x2 > bound2.x2 &&
bound1.y1 < bound2.y1 &&
bound1.y2 > bound2.y2
);
}

export function isBoundPositive(bound: Bound): boolean {
return bound.x1 < bound.x2 && bound.y1 < bound.y2;
}
Expand Down
Loading