Skip to content

Commit

Permalink
🔧
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon committed Jan 7, 2025
1 parent c46b7c6 commit 33e9ded
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 51 deletions.
127 changes: 83 additions & 44 deletions packages/skia/src/sksg/Container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,88 +28,127 @@ const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
SkiaViewApi.setJsiProperty(nativeId, "picture", picture);
};

export class Container {
private _root: Node[] = [];
private _recording: Recording | null = null;
public unmounted = false;
export interface Container {
drawOnCanvas(canvas: SkCanvas): void;
get root(): Node[];
set root(root: Node[]);
redraw(): void;
registerAnimationValues(values: object): void;
unregisterAnimationValues(values: object): void;
}

private values = new Set<SharedValue<unknown>>();
private mapperId: number | null = null;
abstract class BaseContainer implements Container {
protected _root: Node[] = [];
protected _recording: Recording | null = null;

constructor(public Skia: Skia, private nativeId: number) {}
constructor(public Skia: Skia, protected nativeId: number) {}

get root() {
return this._root;
}

drawOnCanvas(canvas: SkCanvas) {
if (!this._recording) {
throw new Error("No recording to draw");
}
const ctx = createDrawingContext(
this.Skia,
this._recording.paintPool,
canvas
);
//console.log(this._recording);
replay(ctx, this._recording.commands);
}

abstract redraw(): void;
abstract registerAnimationValues(values: object): void;
abstract unregisterAnimationValues(values: object): void;
}

class StaticContainer extends BaseContainer {
set root(root: Node[]) {
this._root = root;
const recorder = new Recorder();
visit(recorder, root);
this._recording = createRecording(recorder.commands);
this.redraw();
}

redraw() {
const isOnscreen = this.nativeId !== -1;
if (isOnscreen) {
if (HAS_REANIMATED_3) {
if (this.mapperId !== null) {
Rea.stopMapper(this.mapperId);
}
const { nativeId, Skia, _recording } = this;
this.mapperId = Rea.startMapper(() => {
"worklet";
drawOnscreen(Skia, nativeId, _recording!);
}, Array.from(this.values));
} else {
this.redraw();
drawOnscreen(this.Skia, this.nativeId, this._recording!);
}
}

getNativeId() {
return this.nativeId;
}

unregisterAnimationValues(_values: object) {
// Nothing to do here
}

registerAnimationValues(_values: object) {
// Nothing to do here
}
}

class ReanimatedContainer extends BaseContainer {
private values = new Set<SharedValue<unknown>>();
private mapperId: number | null = null;

constructor(Skia: Skia, nativeId: number) {
super(Skia, nativeId);
}

set root(root: Node[]) {
const isOnscreen = this.nativeId !== -1;
if (isOnscreen) {
if (this.mapperId !== null) {
Rea.stopMapper(this.mapperId);
}
const { nativeId, Skia, _recording } = this;
this.mapperId = Rea.startMapper(() => {
"worklet";
drawOnscreen(Skia, nativeId, _recording!);
}, Array.from(this.values));
}
this._root = root;
const recorder = new Recorder();
visit(recorder, root);
this._recording = createRecording(recorder.commands);
}

clear() {
console.log("clear container");
}

redraw() {
const isOnscreen = this.nativeId !== -1;
if (isOnscreen && HAS_REANIMATED_3) {
if (isOnscreen) {
const { nativeId, Skia, _recording } = this;
Rea.runOnUI(() => {
drawOnscreen(Skia, nativeId, _recording!);
})();
} else if (isOnscreen) {
drawOnscreen(this.Skia, this.nativeId, this._recording!);
}
}

getNativeId() {
return this.nativeId;
}

unregisterValues(values: object) {
unregisterAnimationValues(values: object) {
Object.values(values)
.filter(isSharedValue)
.forEach((value) => {
this.values.delete(value);
});
}

registerValues(values: object) {
registerAnimationValues(values: object) {
Object.values(values)
.filter(isSharedValue)
.forEach((value) => {
this.values.add(value);
});
}

drawOnCanvas(canvas: SkCanvas) {
if (!this._recording) {
throw new Error("No recording to draw");
}
const ctx = createDrawingContext(
this.Skia,
this._recording.paintPool,
canvas
);
//console.log(this._recording);
replay(ctx, this._recording.commands);
}
}

export const createContainer = (Skia: Skia, nativeId: number) => {
return HAS_REANIMATED_3
? new ReanimatedContainer(Skia, nativeId)
: new StaticContainer(Skia, nativeId);
};
9 changes: 4 additions & 5 deletions packages/skia/src/sksg/HostConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const sksgHostConfig: SkiaHostConfig = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { children, ...props } = propsWithChildren as any;
debug("createInstance", type);
container.registerValues(props);
container.registerAnimationValues(props);
const instance = {
type,
props,
Expand Down Expand Up @@ -144,9 +144,8 @@ export const sksgHostConfig: SkiaHostConfig = {
// textInstance.instance = newText;
},

clearContainer: (container) => {
clearContainer: (_container) => {
debug("clearContainer");
container.clear();
},

prepareUpdate(
Expand All @@ -162,8 +161,8 @@ export const sksgHostConfig: SkiaHostConfig = {
if (propsAreEqual) {
return null;
}
container.unregisterValues(oldProps);
container.registerValues(newProps);
container.unregisterAnimationValues(oldProps);
container.registerAnimationValues(newProps);
return container;
},

Expand Down
5 changes: 3 additions & 2 deletions packages/skia/src/sksg/Reconciler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import type { SkCanvas, Skia } from "../skia/types";
import { NodeType } from "../dom/types";

import { debug, sksgHostConfig } from "./HostConfig";
import { Container } from "./Container";
import type { Container } from "./Container";
import { createContainer } from "./Container";

const skiaReconciler = ReactReconciler(sksgHostConfig);

Expand All @@ -21,7 +22,7 @@ export class SkiaSGRoot {
private container: Container;

constructor(public Skia: Skia, nativeId = -1) {
this.container = new Container(Skia, nativeId);
this.container = createContainer(Skia, nativeId);
this.root = skiaReconciler.createContainer(
this.container,
0,
Expand Down

0 comments on commit 33e9ded

Please sign in to comment.