feat: SceneManager creates pdf-page items with culling support
This commit is contained in:
@@ -22,6 +22,7 @@ import { TextureManager } from './TextureManager';
|
|||||||
import { ImageSprite } from './sprites/ImageSprite';
|
import { ImageSprite } from './sprites/ImageSprite';
|
||||||
import { VideoSprite } from './sprites/VideoSprite';
|
import { VideoSprite } from './sprites/VideoSprite';
|
||||||
import { AnimatedGifSprite } from './sprites/AnimatedGifSprite';
|
import { AnimatedGifSprite } from './sprites/AnimatedGifSprite';
|
||||||
|
import { PdfPageSprite } from './sprites/PdfPageSprite';
|
||||||
import { SpringManager } from './spring';
|
import { SpringManager } from './spring';
|
||||||
import { convertFabricToV2 } from './scene-format';
|
import { convertFabricToV2 } from './scene-format';
|
||||||
import type { SceneData } from './scene-format';
|
import type { SceneData } from './scene-format';
|
||||||
@@ -197,7 +198,7 @@ const PixiCanvas = forwardRef<PixiCanvasHandle, PixiCanvasProps>(
|
|||||||
const vcx = bounds.x + bounds.width / 2;
|
const vcx = bounds.x + bounds.width / 2;
|
||||||
const vcy = bounds.y + bounds.height / 2;
|
const vcy = bounds.y + bounds.height / 2;
|
||||||
|
|
||||||
const imageItems: { item: SceneItem; sprite: ImageSprite | AnimatedGifSprite; dist: number; near: boolean }[] = [];
|
const imageItems: { item: SceneItem; sprite: ImageSprite | AnimatedGifSprite | PdfPageSprite; dist: number; near: boolean }[] = [];
|
||||||
const videoItems: { item: SceneItem; sprite: VideoSprite; dist: number; near: boolean }[] = [];
|
const videoItems: { item: SceneItem; sprite: VideoSprite; dist: number; near: boolean }[] = [];
|
||||||
|
|
||||||
// Spatial query: only check items within the extended viewport region
|
// Spatial query: only check items within the extended viewport region
|
||||||
@@ -215,6 +216,8 @@ const PixiCanvas = forwardRef<PixiCanvasHandle, PixiCanvasProps>(
|
|||||||
|
|
||||||
if (item.type === 'image' && (item.displayObject instanceof ImageSprite || item.displayObject instanceof AnimatedGifSprite)) {
|
if (item.type === 'image' && (item.displayObject instanceof ImageSprite || item.displayObject instanceof AnimatedGifSprite)) {
|
||||||
imageItems.push({ item, sprite: item.displayObject, dist, near: true });
|
imageItems.push({ item, sprite: item.displayObject, dist, near: true });
|
||||||
|
} else if (item.type === 'pdf-page' && item.displayObject instanceof PdfPageSprite) {
|
||||||
|
imageItems.push({ item, sprite: item.displayObject, dist, near: true });
|
||||||
} else if (item.type === 'video' && item.displayObject instanceof VideoSprite) {
|
} else if (item.type === 'video' && item.displayObject instanceof VideoSprite) {
|
||||||
videoItems.push({ item, sprite: item.displayObject, dist, near: true });
|
videoItems.push({ item, sprite: item.displayObject, dist, near: true });
|
||||||
}
|
}
|
||||||
@@ -257,7 +260,7 @@ const PixiCanvas = forwardRef<PixiCanvasHandle, PixiCanvasProps>(
|
|||||||
const item = scene.items.get(id);
|
const item = scene.items.get(id);
|
||||||
if (!item) { loadedImages.delete(id); continue; }
|
if (!item) { loadedImages.delete(id); continue; }
|
||||||
const sprite = item.displayObject;
|
const sprite = item.displayObject;
|
||||||
if ((sprite instanceof ImageSprite || sprite instanceof AnimatedGifSprite) && sprite.loaded) {
|
if ((sprite instanceof ImageSprite || sprite instanceof AnimatedGifSprite || sprite instanceof PdfPageSprite) && sprite.loaded) {
|
||||||
sprite.unloadTexture();
|
sprite.unloadTexture();
|
||||||
}
|
}
|
||||||
loadedImages.delete(id);
|
loadedImages.delete(id);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { DrawingSprite } from './sprites/DrawingSprite';
|
|||||||
import { FrameSprite } from './sprites/FrameSprite';
|
import { FrameSprite } from './sprites/FrameSprite';
|
||||||
import { StickySprite } from './sprites/StickySprite';
|
import { StickySprite } from './sprites/StickySprite';
|
||||||
import { MarkdownSprite } from './sprites/MarkdownSprite';
|
import { MarkdownSprite } from './sprites/MarkdownSprite';
|
||||||
|
import { PdfPageSprite } from './sprites/PdfPageSprite';
|
||||||
import { TextSprite } from './sprites/TextSprite';
|
import { TextSprite } from './sprites/TextSprite';
|
||||||
import { SpringManager, Spring, PRESETS } from './spring';
|
import { SpringManager, Spring, PRESETS } from './spring';
|
||||||
import { reparentGroupChildren } from './grouping';
|
import { reparentGroupChildren } from './grouping';
|
||||||
@@ -38,6 +39,7 @@ import type {
|
|||||||
GroupObject,
|
GroupObject,
|
||||||
StickyObject,
|
StickyObject,
|
||||||
MarkdownObject,
|
MarkdownObject,
|
||||||
|
PdfPageObject,
|
||||||
} from './scene-format';
|
} from './scene-format';
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -374,6 +376,13 @@ export class SceneManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'pdf-page': {
|
||||||
|
const d = data as PdfPageObject;
|
||||||
|
const sprite = new PdfPageSprite(d.thumb, d.asset, d.w, d.h, d.pageNumber, d.pageCount, this.textures);
|
||||||
|
displayObject = sprite;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
displayObject = new Container();
|
displayObject = new Container();
|
||||||
break;
|
break;
|
||||||
@@ -710,6 +719,34 @@ export class SceneManager {
|
|||||||
return this.items.get(data.id)!;
|
return this.items.get(data.id)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Create a PdfPageObject from a PDF upload and add it to the scene. */
|
||||||
|
addPdfPageFromUpload(
|
||||||
|
thumbKey: string | null, assetKey: string | null,
|
||||||
|
w: number, h: number, x: number, y: number,
|
||||||
|
pdfImageId: string, pdfName: string,
|
||||||
|
pageNumber: number, pageCount: number,
|
||||||
|
): SceneItem {
|
||||||
|
const data: PdfPageObject = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
type: 'pdf-page',
|
||||||
|
x, y, w, h,
|
||||||
|
sx: 1, sy: 1, angle: 0,
|
||||||
|
z: this.nextZ(),
|
||||||
|
opacity: 1,
|
||||||
|
locked: false,
|
||||||
|
visible: true,
|
||||||
|
name: `${pdfName} p.${pageNumber}`,
|
||||||
|
asset: assetKey,
|
||||||
|
thumb: thumbKey,
|
||||||
|
pdfImageId, pdfName, pageNumber, pageCount,
|
||||||
|
nativeW: w, nativeH: h,
|
||||||
|
};
|
||||||
|
this._createItem(data);
|
||||||
|
this._applyZOrder();
|
||||||
|
this._onChange?.();
|
||||||
|
return this.items.get(data.id)!;
|
||||||
|
}
|
||||||
|
|
||||||
// -- Group / Ungroup with Spring Animation --------------------------------
|
// -- Group / Ungroup with Spring Animation --------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user