feat: SceneManager creates pdf-page items with culling support

This commit is contained in:
Hiren Kangad
2026-03-14 11:21:08 +05:30
parent 332f12cafe
commit 07953ab18d
2 changed files with 42 additions and 2 deletions
+5 -2
View File
@@ -22,6 +22,7 @@ import { TextureManager } from './TextureManager';
import { ImageSprite } from './sprites/ImageSprite';
import { VideoSprite } from './sprites/VideoSprite';
import { AnimatedGifSprite } from './sprites/AnimatedGifSprite';
import { PdfPageSprite } from './sprites/PdfPageSprite';
import { SpringManager } from './spring';
import { convertFabricToV2 } 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 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 }[] = [];
// 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)) {
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) {
videoItems.push({ item, sprite: item.displayObject, dist, near: true });
}
@@ -257,7 +260,7 @@ const PixiCanvas = forwardRef<PixiCanvasHandle, PixiCanvasProps>(
const item = scene.items.get(id);
if (!item) { loadedImages.delete(id); continue; }
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();
}
loadedImages.delete(id);
+37
View File
@@ -15,6 +15,7 @@ import { DrawingSprite } from './sprites/DrawingSprite';
import { FrameSprite } from './sprites/FrameSprite';
import { StickySprite } from './sprites/StickySprite';
import { MarkdownSprite } from './sprites/MarkdownSprite';
import { PdfPageSprite } from './sprites/PdfPageSprite';
import { TextSprite } from './sprites/TextSprite';
import { SpringManager, Spring, PRESETS } from './spring';
import { reparentGroupChildren } from './grouping';
@@ -38,6 +39,7 @@ import type {
GroupObject,
StickyObject,
MarkdownObject,
PdfPageObject,
} from './scene-format';
// ---------------------------------------------------------------------------
@@ -374,6 +376,13 @@ export class SceneManager {
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:
displayObject = new Container();
break;
@@ -710,6 +719,34 @@ export class SceneManager {
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 --------------------------------
/**