Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
hanakla committed Apr 14, 2023
1 parent 83bc339 commit 32511ce
Show file tree
Hide file tree
Showing 84 changed files with 15,224 additions and 212 deletions.
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@
"devDependencies": {
"wsrun": "^5.2.4"
},
"packageManager": "[email protected]"
"packageManager": "[email protected]",
"dependencies": {
"@radix-ui/react-popover": "latest",
"@radix-ui/react-scroll-area": "^1.0.3",
"react-draggable-tree": "^0.7.0"
}
}
5 changes: 3 additions & 2 deletions pkgs/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"main": "dist/index.umd.js",
"module": "dist/index.mjs",
"types": "./dist/index.d.ts",
"types": "dist/index.d.ts",
"license": "MIT",
"exports": {
".": {
Expand All @@ -25,8 +25,9 @@
"@rollup/plugin-typescript": "^9.0.2",
"@types/gl-matrix": "^3.2.0",
"@types/three": "^0.146.0",
"typescript": "^4.9.3",
"typescript": "^5.0.3",
"vite": "^4.0.3",
"vite-plugin-dts": "^2.1.0",
"vite-tsconfig-paths": "^4.0.3",
"vitest": "^0.26.2"
},
Expand Down
Empty file.
12 changes: 12 additions & 0 deletions pkgs/core/src/Document/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export namespace PaplicoDocument {
export type Meta = {
schemaVersion: '2'
title: string
mainArtboard: {
width: number
height: number
}
}

export type SerializedSchema = {
Expand All @@ -34,12 +38,20 @@ export class PaplicoDocument {
public meta: PaplicoDocument.Meta = {
schemaVersion: '2',
title: '',
mainArtboard: {
width: 100,
height: 100,
},
}

public layerEntities: LayerEntity[] = []
public layerTree: LayerNode[] = []
public blobs: PaplicoBlob[] = []

public constructor({ width, height }: { width: number; height: number }) {
this.meta.mainArtboard = { width, height }
}

public resolveLayerEntity(layerId: string) {
return this.layerEntities.find((layer) => layer.uid === layerId)
}
Expand Down
7 changes: 7 additions & 0 deletions pkgs/core/src/Document/LayerEntity/InkSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type InkSetting<T extends Record<string, any> | null = {}> = {
inkId: string
inkVersion: string

/** Ink specific settings */
specific: T
}
11 changes: 11 additions & 0 deletions pkgs/core/src/Document/factory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import prand from 'pure-rand'

import { ulid } from '@/utils/ulid'
import { PaplicoDocument } from './Document'
import { FilterLayer, RasterLayer, VectorLayer } from './LayerEntity'
import { VectorObject } from './LayerEntity/VectorObject'
import { VectorPath } from './LayerEntity/VectorPath'
Expand All @@ -9,6 +10,16 @@ type Requires<T, K extends keyof T> = Omit<T, K> & {
[P in K]-?: T[P]
}

export const createDocument = ({
width,
height,
}: {
width: number
height: number
}) => {
return new PaplicoDocument({ width, height })
}

export const createRasterLayerEntity = ({
name = '',
width,
Expand Down
5 changes: 4 additions & 1 deletion pkgs/core/src/Engine/Brush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import { WebGLRenderer, Camera } from 'three'
// import { VectorObject } from '../DOM/VectorObject'
import { VectorStrokeSetting, VectorPath } from '@/Document'
import { RenderCycleLogger } from './RenderCycleLogger'
import { InkGenerator } from './Ink'

export type BrushContext<T extends Record<string, any>> = {
abort: AbortSignal
abortIfNeeded: () => never | void

/** Render result destination canvas */
context: CanvasRenderingContext2D
threeRenderer: WebGLRenderer
threeCamera: Camera
Expand All @@ -21,7 +24,7 @@ export type BrushContext<T extends Record<string, any>> = {
scale: { x: number; y: number }
translate: { x: number; y: number }
}
// ink: IInk
ink: InkGenerator
brushSetting: VectorStrokeSetting<T | null>
/** Expected destination canvas size */
destSize: { width: number; height: number }
Expand Down
6 changes: 3 additions & 3 deletions pkgs/core/src/Engine/Brushes/CircleBrush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class CircleBrush implements IBrush {

public getInitialSpecificConfig(): CircleBrush.SpecificSetting {
return {
lineCap: 'square',
lineCap: 'round',
}
}

Expand Down Expand Up @@ -72,8 +72,8 @@ export class CircleBrush implements IBrush {

// console.log(scattered)

path.mapPoints(
scattered,
mapPoints(
path.points,
(point, prev) => {
ctx.bezierCurveTo(
prev!.out?.x ?? prev!.x,
Expand Down
1 change: 1 addition & 0 deletions pkgs/core/src/Engine/Brushes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CircleBrush } from './CircleBrush'
35 changes: 35 additions & 0 deletions pkgs/core/src/Engine/Ink.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ColorRGBA } from '@/Document'
import { VectorPathPoint } from '@/Document/LayerEntity/VectorPath'
import { Camera, WebGLRenderer } from 'three'

export interface InkClass {
readonly id: string
readonly version: string

new (): IInk
}

export interface IInk {
class: InkClass

initialize(): Promise<void> | void
getInkGenerator(ctx: any): InkGenerator
}

export interface InkGenerator {
getColor(inkContext: {
pointIndex: number
points: VectorPathPoint[]
pointAtLength: number
totalLength: number
baseColor: ColorRGBA
}): ColorRGBA

applyTexture(
canvas: CanvasRenderingContext2D,
context: {
threeRenderer: WebGLRenderer
threeCamera: Camera
}
): void
}
39 changes: 39 additions & 0 deletions pkgs/core/src/Engine/InkRegistry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Emitter } from '@/utils/Emitter'
import { IInk, InkClass } from './Ink'

type Events = {
entriesChanged: void
}

export class InkRegistry extends Emitter<Events> {
protected brushes: Map<string, InkClass> = new Map()
protected instances: WeakMap<InkClass, IInk> = new WeakMap()

public async register(Brush: InkClass) {
try {
this.brushes.set(Brush.id, Brush)

const brush = new Brush()
await brush.initialize()

this.instances.set(Brush, brush)
} catch (e) {
this.brushes.delete(Brush.id)
this.instances.delete(Brush)
throw e
}

this.emit('entriesChanged')
}

public get brushEntries(): InkClass[] {
return [...this.brushes.values()]
}

public getInstance(id: string): IInk | null {
const Class = this.brushes.get(id)
if (!Class) return null

return this.instances.get(Class) ?? null
}
}
23 changes: 23 additions & 0 deletions pkgs/core/src/Engine/Inks/PlainInk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IInk, InkGenerator } from '../Ink'

export class PlainInk implements IInk {
public static id = '@paplico/core/ink/plain'
public static version = '0.0.1'

public get class() {
return PlainInk
}

public initialize() {}

getInkGenerator(ctx: any): InkGenerator {
return {
applyTexture(canvas, context) {
return
},
getColor({ pointIndex, points, baseColor }) {
return baseColor
},
}
}
}
33 changes: 33 additions & 0 deletions pkgs/core/src/Engine/Inks/RainbowInk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { createSeededRandom } from '@/Math'
import { IInk, InkGenerator } from '../Ink'

export class RainbowInk implements IInk {
public static id = '@paplico/core/ink/rainbow'
public static version = '0.0.1'

public get class() {
return RainbowInk
}

public initialize() {}

getInkGenerator(ctx: any): InkGenerator {
return {
applyTexture(canvas, context) {
return
},
getColor({ pointIndex, points, baseColor }) {
const random = createSeededRandom(pointIndex)

return baseColor

return {
r: random.nextFloat(),
g: random.nextFloat(),
b: random.nextFloat(),
a: baseColor.a,
}
},
}
}
}
38 changes: 24 additions & 14 deletions pkgs/core/src/Engine/MixerPipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,34 +66,42 @@ export class MixerPipeline {
continue
}

logger.log('Render layer', layer.uid, layer.name, layer.layerType)
logger.log(
'Render layer',
layer.source.uid,
layer.source.name,
layer.source.layerType
)

let image: ImageBitmap | HTMLCanvasElement | null | void

if (override?.[layer.uid]) {
image = override[layer.uid]
} else if (layer.layerType === 'raster') {
image = (await doc.getOrCreateLayerBitmapCache(layer.uid))!
} else if (layer.layerType === 'vector') {
if (override?.[layer.source.uid]) {
image = override[layer.source.uid]
} else if (layer.source.layerType === 'raster') {
image = (await doc.getOrCreateLayerBitmapCache(layer.source.uid))!
} else if (layer.source.layerType === 'vector') {
const requestSize = { width: viewport.width, height: viewport.height }

if (doc.hasLayerBitmapCache(layer.uid, requestSize)) {
logger.info('Use cached bitmap for vector layer', layer.uid)
if (doc.hasLayerBitmapCache(layer.source.uid, requestSize)) {
logger.info('Use cached bitmap for vector layer', layer.source.uid)
image = (await doc.getOrCreateLayerBitmapCache(
layer.uid,
layer.source.uid,
requestSize
))!
} else {
logger.info('Cache is invalidated, re-render vector layer', layer.uid)
logger.info(
'Cache is invalidated, re-render vector layer',
layer.source.uid
)

await render.renderVectorLayer(tmp, layer, {
await render.renderVectorLayer(tmp, layer.source, {
viewport,
abort,
logger,
})

image = await doc.updateOrCreateLayerBitmapCache(
layer.uid,
layer.source.uid,
tmpctx.getImageData(0, 0, viewport.width, viewport.height)
)
}
Expand All @@ -102,11 +110,13 @@ export class MixerPipeline {
continue
}

const mode = layerCompositeModeToCanvasCompositeMode(layer.compositeMode)
const mode = layerCompositeModeToCanvasCompositeMode(
layer.source.compositeMode
)

await saveAndRestoreCanvas(dest, async () => {
logger.log(
`Will draw layer ${layer.uid} as ${mode} to destination.`,
`Will draw layer ${layer.source.uid} as ${mode} to destination.`,
image
)
dest.globalCompositeOperation = mode
Expand Down
Loading

0 comments on commit 32511ce

Please sign in to comment.