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

Add support for managing extensions #529

Merged
merged 5 commits into from
Sep 1, 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
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,15 @@ Setting `attachToDevtools` to `true` will automatically attach the application t

###### `defaultTextStyle`

`defaultTextStyle` is a convenience property. Whatever is passed will automatically be assigned to Pixi.js's[`TextStyle.defaultTextStyle`](https://pixijs.download/release/docs/text.TextStyle.html#defaultTextStyle).
`defaultTextStyle` is a convenience property. Whatever is passed will automatically be assigned to Pixi.js's [`TextStyle.defaultTextStyle`](https://pixijs.download/release/docs/text.TextStyle.html#defaultTextStyle).

> [!NOTE]
> This property **is not retroactive**. It will only apply to text components created after `defaultTextStyle` is set. Any text components created before setting `defaultTextStyle` will retain the base styles they had before `defaultTextStyle` was changed.

###### `extensions`

`extensions` is an array of extensions to be loaded. Adding and removing items from this array will automatically load/unload the extensions. The first time this is handled happens before the application is initialised. See Pixi.js's [`extensions`](https://pixijs.download/release/docs/extensions.html) documentation for more info on extensions.

###### `resizeTo`

The `<Application>` component supports the `resizeTo` property, with some additional functionality: it can accept any HTML element **or** it can take a React `ref` directly.
Expand Down
49 changes: 42 additions & 7 deletions src/components/Application.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { TextStyle } from 'pixi.js';
import {
extensions as PixiExtensions,
TextStyle,
} from 'pixi.js';
import {
createElement,
forwardRef,
type ForwardRefRenderFunction,
type MutableRefObject,
useCallback,
useRef,
} from 'react';
import { createRoot } from '../core/createRoot';
import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect';
import { type ApplicationProps } from '../typedefs/ApplicationProps';
import { type Root } from '../typedefs/Root';

import type { Application as PixiApplication } from 'pixi.js';
import type {
ForwardRefRenderFunction,
MutableRefObject,
} from 'react';
import type { ApplicationProps } from '../typedefs/ApplicationProps';
import type { Root } from '../typedefs/Root';

const originalDefaultTextStyle = { ...TextStyle.defaultTextStyle };

Expand All @@ -29,13 +30,15 @@ export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, Appl
children,
className,
defaultTextStyle,
extensions,
onInit,
resizeTo,
...applicationProps
} = props;

const applicationRef: MutableRefObject<PixiApplication | null> = useRef(null);
const canvasRef: MutableRefObject<HTMLCanvasElement | null> = useRef(null);
const extensionsRef: MutableRefObject<Set<any>> = useRef(new Set());
const rootRef: MutableRefObject<Root | null> = useRef(null);

const updateResizeTo = useCallback(() =>
Expand Down Expand Up @@ -95,6 +98,38 @@ export const ApplicationFunction: ForwardRefRenderFunction<PixiApplication, Appl
}
}, [onInit]);

useIsomorphicLayoutEffect(() =>
{
if (extensions)
{
const extensionsToHandle = [...extensions];
const extensionsState = extensionsRef.current;

// Check for extensions that have been removed from the array
for (const extension of extensionsState.values())
{
const extensionIndex = extensionsToHandle.indexOf(extension);

// If the extension is no longer in the array, we'll remove it from Pixi.js
if (extensionIndex === -1)
{
PixiExtensions.remove(extension);
extensionsState.delete(extension);
}

// Since the extension already existed in the state, we can remove it to prevent any further handling
extensionsToHandle.splice(extensionIndex, 1);
}

// Load any remaining extensions.
for (const extension in extensionsToHandle)
{
PixiExtensions.add(extension);
extensionsState.add(extension);
}
}
}, [extensions]);

useIsomorphicLayoutEffect(() =>
{
const canvasElement = canvasRef.current;
Expand Down
4 changes: 4 additions & 0 deletions src/typedefs/ApplicationProps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
Application,
ApplicationOptions,
ExtensionFormatLoose,
TextStyle,
TextStyleOptions,
} from 'pixi.js';
Expand All @@ -24,6 +25,9 @@ export interface BaseApplicationProps
/** @description The default style to be applied to text nodes. */
defaultTextStyle?: TextStyle | TextStyleOptions,

/** @description An array of Pixi extensions to be loaded before initialisation. */
extensions?: (ExtensionFormatLoose | any)[],

/** @description A unique key which allows React to manage this component across changes in parent state. */
key?: Key,

Expand Down