Skip to content
Open
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
42 changes: 42 additions & 0 deletions src/cull.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { DisplayObjectWithCulling, Simple } from 'pixi-cull';
// import { Point } from '@pixi/math';
// import { Bounds } from '@pixi/display';

// refer: https://github.com/davidfig/pixi-cull/issues/2#issuecomment-570087695
export default class Cull extends Simple {
updateObject(object: DisplayObjectWithCulling) {
// original code
// const box = object.getLocalBounds();
// object.AABB = object.AABB || { x: 0, y: 0, width: 0, height: 0 };
// object.AABB.x = object.x + (box.x - object.pivot.x) * Math.abs(object.scale.x);
// object.AABB.y = object.y + (box.y - object.pivot.y) * Math.abs(object.scale.y);
// object.AABB.width = box.width * Math.abs(object.scale.x);
// object.AABB.height = box.height * Math.abs(object.scale.y);

const box = object.getBounds();
object.AABB = box;

// const rotPivot = new Point(object.x + object.pivot.x, object.y + object.pivot.y);
// const rotSin = Math.sin(object.rotation);
// const rotCos = Math.cos(object.rotation);

// const points = [
// new Point(object.x, object.y),
// new Point(object.x + box.width, object.y),
// new Point(object.x, object.y + box.height),
// new Point(object.x + box.width, object.y + box.height),
// ];
// const pointsTransformed = points.map((point) => {
// return new Point(
// (point.x - rotPivot.x) * rotCos - (point.y - rotPivot.y) * rotSin + rotPivot.x,
// (point.x - rotPivot.x) * rotSin + (point.y - rotPivot.y) * rotCos + rotPivot.y
// );
// });

// const bounds = new Bounds();
// pointsTransformed.map((point) => bounds.addPoint(point));
// const aabb = bounds.getRectangle();

// object.AABB = aabb;
}
}
47 changes: 32 additions & 15 deletions src/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { Container } from '@pixi/display';
import { Point, IPointData, Rectangle } from '@pixi/math';
import { IAddOptions } from '@pixi/loaders';
import { Viewport } from 'pixi-viewport';
import { Cull } from '@pixi-essentials/cull';
// import { Simple } from 'pixi-cull';
import Cull from './cull';
import { AbstractGraph } from 'graphology-types';
import { TypedEmitter } from 'tiny-typed-emitter';
import { GraphStyleDefinition, NodeStyleDefinition, resolveStyleDefinitions } from './utils/style';
Expand Down Expand Up @@ -101,7 +100,7 @@ export class PixiGraph<
private app: Application;
private textureCache: TextureCache;
private viewport: Viewport;
// private cull: Simple;
private cull: Cull;
private resizeObserver: ResizeObserver;
private edgeLayer: Container;
private frontEdgeLayer: Container;
Expand Down Expand Up @@ -158,9 +157,9 @@ export class PixiGraph<
autoDensity: true,
});
this.container.appendChild(this.app.view);
// this.cull = new Simple({
// dirtyTest: true,
// });
this.cull = new Cull({
dirtyTest: false,
});

this.app.renderer.plugins.interaction.moveWhenInside = true;
this.app.view.addEventListener('wheel', (event) => {
Expand Down Expand Up @@ -238,6 +237,7 @@ export class PixiGraph<

// preload resources
if (this.resources) {
// @ts-ignore
this.app.loader.add(this.resources);
}
this.app.loader.load(() => {
Expand Down Expand Up @@ -529,10 +529,17 @@ export class PixiGraph<
const node = this.nodeKeyToNodeObject.get(nodeKey)!;
const nodePosition = { x: point.x, y: point.y };
node.updatePosition(nodePosition);
// @ts-ignore
this.cull.updateObject(node.nodeGfx);

// update style
this.updateNodeStyleByKey(nodeKey);
this.graph.edges(nodeKey).forEach(this.updateEdgeStyleByKey.bind(this));
this.graph.edges(nodeKey).forEach((edgeKey: string) => {
const edge = this.edgeKeyToEdgeObject.get(edgeKey)!;
// @ts-ignore
this.cull.updateObject(edge.edgeGfx);
});
}

private moveNodebyDelta(nodeKey: string, deltaX: number, deltaY: number) {
Expand All @@ -545,10 +552,17 @@ export class PixiGraph<
const node = this.nodeKeyToNodeObject.get(nodeKey)!;
const nodePosition = { x: x + deltaX, y: y + deltaY };
node.updatePosition(nodePosition);
// @ts-ignore
this.cull.updateObject(node.nodeGfx);

// update style
this.updateNodeStyleByKey(nodeKey);
this.graph.edges(nodeKey).forEach(this.updateEdgeStyleByKey.bind(this));
this.graph.edges(nodeKey).forEach((edgeKey: string) => {
const edge = this.edgeKeyToEdgeObject.get(edgeKey)!;
// @ts-ignore
this.cull.updateObject(edge.edgeGfx);
});
}

private enableNodeDragging() {
Expand Down Expand Up @@ -588,11 +602,8 @@ export class PixiGraph<
this.graph.forEachNode(this.createNode.bind(this));
this.graph.forEachEdge(this.createEdge.bind(this));

// todo
// when graph change(position change or add/delete new node)
// should mark related object dirty.
// @ts-ignore
// (this.viewport.children as Container[]).map((layer) => this.cull.addList(layer.children));
(this.viewport.children as Container[]).map((layer) => this.cull.addList(layer.children));
}

private createNode(nodeKey: string, nodeAttributes: NodeAttributes) {
Expand Down Expand Up @@ -685,6 +696,8 @@ export class PixiGraph<

const nodePosition = { x: nodeAttributes.x, y: nodeAttributes.y };
node.updatePosition(nodePosition);
// @ts-ignore
this.cull.updateObject(node.nodeGfx);

this.updateNodeStyle(nodeKey, nodeAttributes);
}
Expand Down Expand Up @@ -826,6 +839,8 @@ export class PixiGraph<
parallelEdgeCount,
parallelSeq
);
// @ts-ignore
this.cull.updateObject(edge.edgeGfx);

edge.updateStyle(
edgeStyle,
Expand All @@ -840,13 +855,13 @@ export class PixiGraph<
private updateGraphVisibility() {
// culling todo(rotation cull have bug)
// https://github.com/davidfig/pixi-cull/issues/2
// this.cull.cull(this.viewport.getVisibleBounds(), false);
this.cull.cull(this.viewport.getVisibleBounds(), true);
// should refer https://github.com/ShukantPal/pixi-essentials/tree/master/packages/cull

// original culling have performance issue.
const cull = new Cull();
cull.addAll((this.viewport.children as Container[]).map((layer) => layer.children).flat());
cull.cull(this.app.renderer.screen);
// const cull = new Cull();
// cull.addAll((this.viewport.children as Container[]).map((layer) => layer.children).flat());
// cull.cull(this.app.renderer.screen);

// console.log(
// Array.from((cull as any)._targetList as Set<DisplayObject>).filter(x => x.visible === true).length,
Expand All @@ -859,13 +874,15 @@ export class PixiGraph<
const zoomStep = zoomSteps.findIndex((zoomStep) => zoom <= zoomStep);
console.log(zoom, zoomStep);

// edge (line) will always show

// zoomStep = 0, zoom <= 0.1
// node background
// zoomStep = 1, 0.1 < zoom <= 0.2
// node border
// zoomStep = 2, 0.2 < zoom <= 0.4
// node icon
// edge (line/parallel edge/self loop edge)
// edge (parallel edge/self loop edge)
// zoomStep = 3, 0.4 < zoom < Infinity
// node label
// edge arrow
Expand Down
27 changes: 15 additions & 12 deletions src/renderers/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ export function updatePosition(
const [color, alpha] = colorToPixi(edgeStyle.color);
const length = Math.hypot(targetNodePosition.x - sourceNodePosition.x, targetNodePosition.y - sourceNodePosition.y);

const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as Sprite;
const edgeArrow = edgeGfx.getChildByName!(EDGE_ARROW) as Sprite;
const edgeCurve = edgeGfx.getChildByName!(EDGE_CURVE) as Graphics;
const edgeCurveArrow = edgeGfx.getChildByName!(EDGE_CURVE_ARROW) as Graphics;
const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as unknown as Sprite;
const edgeArrow = edgeGfx.getChildByName!(EDGE_ARROW) as unknown as Sprite;
const edgeCurve = edgeGfx.getChildByName!(EDGE_CURVE) as unknown as Graphics;
const edgeCurveArrow = edgeGfx.getChildByName!(EDGE_CURVE_ARROW) as unknown as Graphics;

edgeLine.visible = false;
edgeArrow.visible = false;
Expand Down Expand Up @@ -194,7 +194,7 @@ export function updateEdgeStyle(
}
if (parallelEdgeCount <= 1 || (parallelEdgeCount % 2 === 1 && parallelSeq === parallelEdgeCount)) {
// edgeGfx -> edgeLine
const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as Sprite;
const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as unknown as Sprite;
edgeLine.height = edgeStyle.width;
[edgeLine.tint, edgeLine.alpha] = colorToPixi(edgeStyle.color);
}
Expand All @@ -207,14 +207,14 @@ export function updateEdgeVisibility(
parallelEdgeCount: number,
parallelSeq: number
) {
const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as Sprite;
const edgeArrow = edgeGfx.getChildByName!(EDGE_ARROW) as Sprite;
const edgeCurve = edgeGfx.getChildByName!(EDGE_CURVE) as Graphics;
const edgeCurveArrow = edgeGfx.getChildByName!(EDGE_CURVE_ARROW) as Graphics;
const edgeLine = edgeGfx.getChildByName!(EDGE_LINE) as unknown as Sprite;
const edgeArrow = edgeGfx.getChildByName!(EDGE_ARROW) as unknown as Sprite;
const edgeCurve = edgeGfx.getChildByName!(EDGE_CURVE) as unknown as Graphics;
const edgeCurveArrow = edgeGfx.getChildByName!(EDGE_CURVE_ARROW) as unknown as Graphics;

if (isSelfLoop) {
// edgeGfx -> edgeCurve
edgeCurve.visible = zoomStep >= 2;
edgeCurve.visible = zoomStep >= 3;
// edgeGfx -> edgeCurveArrow
edgeCurveArrow.visible = zoomStep >= 3;

Expand All @@ -226,7 +226,10 @@ export function updateEdgeVisibility(

if (parallelEdgeCount <= 1 || (parallelEdgeCount % 2 === 1 && parallelSeq === parallelEdgeCount)) {
// edgeGfx -> edgeLine
edgeLine.visible = zoomStep >= 2;
// edgeLine.visible = zoomStep >= 1;
// todo(lin): we may need display line all the time.
edgeLine.visible = true;

// edgeGFX -> edgeArrow
edgeArrow.visible = zoomStep >= 3;

Expand All @@ -235,7 +238,7 @@ export function updateEdgeVisibility(
edgeCurveArrow.visible = false;
} else {
// edgeGfx -> edgeCurve
edgeCurve.visible = zoomStep >= 2;
edgeCurve.visible = zoomStep >= 3;
// edgeGfx -> edgeCurveArrow
edgeCurveArrow.visible = zoomStep >= 3;

Expand Down
4 changes: 2 additions & 2 deletions src/renderers/node-label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ export function updateNodeLabelStyle(nodeLabelGfx: Container, nodeStyle: NodeSty
});

// nodeLabelGfx -> nodeLabelText
const nodeLabelText = nodeLabelGfx.getChildByName!(NODE_LABEL_TEXT) as Sprite;
const nodeLabelText = nodeLabelGfx.getChildByName!(NODE_LABEL_TEXT) as unknown as Sprite;
nodeLabelText.texture = nodeLabelTextTexture;
nodeLabelText.y = nodeStyle.size + (nodeLabelTextTexture.height + nodeStyle.label.padding * 2) / 2;
[nodeLabelText.tint, nodeLabelText.alpha] = colorToPixi(nodeStyle.label.color);
}

export function updateNodeLabelVisibility(nodeLabelGfx: Container, zoomStep: number) {
// nodeLabelGfx -> nodeLabelText
const nodeLabelText = nodeLabelGfx.getChildByName!(NODE_LABEL_TEXT) as BitmapText;
const nodeLabelText = nodeLabelGfx.getChildByName!(NODE_LABEL_TEXT) as unknown as BitmapText;
nodeLabelText.visible = zoomStep >= 3;
}
10 changes: 5 additions & 5 deletions src/renderers/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,18 @@ export function updateNodeStyle(nodeGfx: Container, nodeStyle: NodeStyle, textur
(nodeGfx.hitArea as Circle).radius = nodeOuterSize;

// nodeGfx -> nodeCircle
const nodeCircle = nodeGfx.getChildByName!(NODE_CIRCLE) as Sprite;
const nodeCircle = nodeGfx.getChildByName!(NODE_CIRCLE) as unknown as Sprite;
nodeCircle.texture = nodeCircleTexture;
[nodeCircle.tint, nodeCircle.alpha] = colorToPixi(nodeStyle.color);

// nodeGfx -> nodeCircleBorder
const nodeCircleBorder = nodeGfx.getChildByName!(NODE_CIRCLE_BORDER) as Sprite;
const nodeCircleBorder = nodeGfx.getChildByName!(NODE_CIRCLE_BORDER) as unknown as Sprite;
nodeCircleBorder.texture = nodeCircleBorderTexture;
[nodeCircleBorder.tint, nodeCircleBorder.alpha] = colorToPixi(nodeStyle.border.color);

// nodeGfx -> nodeIcon
if (nodeStyle.icon.url && nodeStyle.icon.width && nodeStyle.icon.height) {
const nodeIcon = nodeGfx.getChildByName!(NODE_ICON) as Sprite;
const nodeIcon = nodeGfx.getChildByName!(NODE_ICON) as unknown as Sprite;
nodeIcon.texture = Texture.from(nodeStyle.icon.url);
nodeIcon.width = nodeStyle.icon.width;
nodeIcon.height = nodeStyle.icon.height;
Expand All @@ -82,11 +82,11 @@ export function updateNodeStyle(nodeGfx: Container, nodeStyle: NodeStyle, textur

export function updateNodeVisibility(nodeGfx: Container, zoomStep: number) {
// nodeGfx -> nodeCircleBorder
const nodeCircleBorder = nodeGfx.getChildByName!(NODE_CIRCLE_BORDER) as Sprite;
const nodeCircleBorder = nodeGfx.getChildByName!(NODE_CIRCLE_BORDER) as unknown as Sprite;
nodeCircleBorder.visible = zoomStep >= 1;

// nodeGfx -> nodeIcon
const nodeIcon = nodeGfx.getChildByName!(NODE_ICON) as Sprite;
const nodeIcon = nodeGfx.getChildByName!(NODE_ICON) as unknown as Sprite;
if (nodeIcon) {
nodeIcon.visible = zoomStep >= 2;
}
Expand Down