mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
Painting Works.
This commit is contained in:
1 parent
0f8e7dae82
commit
fb87cdaee4
3 files changed
+138
-30
No files matched your search
@@ -113,13 +113,7 @@ export class Engine {
|
||||
|
||||
this.offScreenCanvas = new OffscreenCanvas(0, 0);
|
||||
|
||||
this.realTimeDrawEngine = new RealTimeDrawEngine({
|
||||
width: VideoResolutions.SQUARE_1024.width,
|
||||
height: VideoResolutions.SQUARE_1024.height,
|
||||
mediaLayerRef: this.mediaLayer,
|
||||
bgLayerRef: this.bgLayer,
|
||||
offScreenCanvas: this.offScreenCanvas,
|
||||
});
|
||||
|
||||
|
||||
// Collection of all Nodes
|
||||
this.nodesManager = new NodesManager();
|
||||
@@ -129,6 +123,14 @@ export class Engine {
|
||||
mediaLayerRef: this.mediaLayer,
|
||||
});
|
||||
|
||||
this.realTimeDrawEngine = new RealTimeDrawEngine({
|
||||
width: VideoResolutions.SQUARE_1024.width,
|
||||
height: VideoResolutions.SQUARE_1024.height,
|
||||
mediaLayerRef: this.mediaLayer,
|
||||
offScreenCanvas: this.offScreenCanvas,
|
||||
selectionManagerRef:this.selectionManager
|
||||
});
|
||||
|
||||
// Selector Square to select Nodes
|
||||
this.selectorSquare = new SelectorSquare({
|
||||
captureCanvasRef: this.realTimeDrawEngine.captureCanvas,
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import Konva from "konva";
|
||||
import { SelectionManager } from "../NodesManagers";
|
||||
import { Position, Size, NodeData, TransformationData } from "../types";
|
||||
import { NodeType } from "./constants";
|
||||
import { NodeUtilities } from "./NodeUtilities";
|
||||
import { NetworkedNode } from "./NetworkedNode";
|
||||
|
||||
interface PaintNodeConstructor {
|
||||
canvasElement:HTMLCanvasElement;
|
||||
lineBounds: {
|
||||
width: number;
|
||||
height: number;
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
mediaLayerRef: Konva.Layer;
|
||||
selectionManagerRef: SelectionManager;
|
||||
|
||||
loaded: () => Promise<void>;
|
||||
}
|
||||
|
||||
export class PaintNode extends NetworkedNode {
|
||||
retry(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
constructor({
|
||||
canvasElement,
|
||||
lineBounds,
|
||||
mediaLayerRef,
|
||||
selectionManagerRef,
|
||||
loaded,
|
||||
}: PaintNodeConstructor) {
|
||||
|
||||
const cl = canvasElement
|
||||
|
||||
// Convert circle to image
|
||||
const dataURL = cl.toDataURL();
|
||||
const imageObj = new Image();
|
||||
imageObj.src = dataURL;
|
||||
|
||||
const paintShape = new Konva.Image({
|
||||
x: lineBounds.x,
|
||||
y: lineBounds.y,
|
||||
width: lineBounds.width,
|
||||
height: lineBounds.height,
|
||||
image: imageObj,
|
||||
listening: false, // Disable event listening to allow captureCanvas to receive events
|
||||
draggable: true,
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
dash: [5, 5], // Creates dotted outline
|
||||
globalCompositeOperation: 'source-over',
|
||||
fill: 'transparent'
|
||||
});
|
||||
|
||||
imageObj.onload = () => {
|
||||
this.mediaLayerRef.draw();
|
||||
loaded();
|
||||
};
|
||||
|
||||
super({
|
||||
selectionManagerRef: selectionManagerRef,
|
||||
mediaLayerRef: mediaLayerRef,
|
||||
kNode: paintShape,
|
||||
});
|
||||
|
||||
this.mediaLayerRef.add(this.kNode);
|
||||
this.listenToBaseKNode();
|
||||
this.mediaLayerRef.draw();
|
||||
}
|
||||
|
||||
public getNodeData(canvasPosition: Position) {
|
||||
const data: NodeData = {
|
||||
type: NodeType.SHAPE,
|
||||
transform: {
|
||||
position: {
|
||||
x: this.kNode.position().x - canvasPosition.x,
|
||||
y: this.kNode.position().y - canvasPosition.y,
|
||||
},
|
||||
size: this.kNode.size(),
|
||||
rotation: this.kNode.rotation(),
|
||||
scale: {
|
||||
x: this.kNode.scaleX(),
|
||||
y: this.kNode.scaleY(),
|
||||
},
|
||||
zIndex: this.kNode.getZIndex(),
|
||||
},
|
||||
};
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,15 @@ import { MediaNode } from "../types";
|
||||
|
||||
import { RenderTask } from "./RenderTask";
|
||||
import { OffScreenSceneCanvas } from "./OffScreenSceneCanvas";
|
||||
import { Image } from "@tauri-apps/api/image";
|
||||
import { SelectionManager } from "../NodesManagers";
|
||||
import { PaintNode } from "../Nodes/PaintNode";
|
||||
|
||||
// https://www.aiseesoft.com/resource/phone-aspect-ratio-screen-resolution.html#:~:text=16%3A9%20Aspect%20Ratio
|
||||
|
||||
export class RealTimeDrawEngine {
|
||||
private videoNodes: VideoNode[];
|
||||
private imageNodes: (ImageNode | TextNode | ShapeNode)[];
|
||||
private imageNodes: (ImageNode | TextNode | ShapeNode | PaintNode)[];
|
||||
|
||||
private offScreenCanvas: OffscreenCanvas;
|
||||
private outputBitmap: ImageBitmap | undefined;
|
||||
@@ -48,7 +51,6 @@ export class RealTimeDrawEngine {
|
||||
public currentStrength: number;
|
||||
|
||||
|
||||
|
||||
// Paint Color
|
||||
// paint Brush Size
|
||||
// has to exit out of paint mode when shape or image are used.
|
||||
@@ -56,20 +58,26 @@ export class RealTimeDrawEngine {
|
||||
public paintBrushSize: number = 5;
|
||||
public isPaintMode: boolean = false;
|
||||
|
||||
private selectionManagerRef: SelectionManager;
|
||||
|
||||
constructor({
|
||||
width,
|
||||
height,
|
||||
mediaLayerRef,
|
||||
offScreenCanvas,
|
||||
selectionManagerRef,
|
||||
}: {
|
||||
width: number;
|
||||
height: number;
|
||||
mediaLayerRef: Konva.Layer;
|
||||
offScreenCanvas: OffscreenCanvas;
|
||||
selectionManagerRef: SelectionManager;
|
||||
}) {
|
||||
this.videoLoadingCanvas = undefined;
|
||||
this.videoNodes = [];
|
||||
this.imageNodes = [];
|
||||
|
||||
this.selectionManagerRef = selectionManagerRef;
|
||||
|
||||
// TODO: Make this dynamic and update this on change of canvas.
|
||||
|
||||
@@ -210,26 +218,11 @@ export class RealTimeDrawEngine {
|
||||
height: lineBounds.height,
|
||||
pixelRatio: 1,
|
||||
});
|
||||
|
||||
// Create a new Konva Image with the drawn content
|
||||
const drawingImage = new Konva.Image({
|
||||
x: lineBounds.x,
|
||||
y: lineBounds.y,
|
||||
width: lineBounds.width,
|
||||
height: lineBounds.height,
|
||||
image: lineCanvas,
|
||||
listening: false, // Disable event listening to allow captureCanvas to receive events
|
||||
draggable: true,
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
dash: [5, 5], // Creates dotted outline
|
||||
globalCompositeOperation: 'source-over',
|
||||
fill: 'transparent' // Add green background
|
||||
});
|
||||
|
||||
|
||||
this.createPaintNode(lineCanvas,lineBounds)
|
||||
|
||||
// Add the image to the drawingsLayer
|
||||
this.drawingsLayer.add(drawingImage);
|
||||
// this.drawingsLayer.add(drawingImage);
|
||||
|
||||
// Clean up
|
||||
lineToConvert.destroy();
|
||||
@@ -491,15 +484,36 @@ export class RealTimeDrawEngine {
|
||||
await this.render();
|
||||
};
|
||||
|
||||
public async createPaintNode(canvasElement: HTMLCanvasElement, lineBounds:{
|
||||
width: number;
|
||||
height: number;
|
||||
x: number;
|
||||
y: number;}){
|
||||
// Create an ImageNode from the Konva.Image
|
||||
var node = new PaintNode({
|
||||
canvasElement:canvasElement,
|
||||
lineBounds:lineBounds,
|
||||
canvasPosition: this.captureCanvas.position(),
|
||||
canvasSize: this.captureCanvas.size(),
|
||||
mediaLayerRef: this.mediaLayerRef,
|
||||
selectionManagerRef: this.selectionManagerRef,
|
||||
loaded: async () => {
|
||||
await this.render();
|
||||
}})
|
||||
await this.addNodes(node);
|
||||
}
|
||||
|
||||
public async addNodes(node: MediaNode) {
|
||||
|
||||
if (node instanceof ImageNode || node instanceof TextNode || node instanceof ShapeNode) {
|
||||
if (node instanceof ImageNode ||
|
||||
node instanceof TextNode ||
|
||||
node instanceof ShapeNode ||
|
||||
node instanceof PaintNode)
|
||||
{
|
||||
console.debug("Adding node:", node);
|
||||
this.imageNodes.push(node);
|
||||
console.log(this.imageNodes)
|
||||
node.kNode.on("dragend", this.handleNodeDragEnd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public removeNodes(node: MediaNode) {
|
||||
|
||||
Reference in new issue
Block a user