hd0013's picture
Upload folder using huggingface_hub
8fdc036 verified
raw
history blame contribute delete
No virus
5.55 kB
import {
Container,
Graphics,
Color,
type ColorSource,
type IRenderer,
RenderTexture,
Sprite
} from "pixi.js";
import type { LayerScene } from "../layers/utils";
import { type Command } from "../utils/commands";
import { make_graphics } from "../utils/pixi";
export interface DrawCommand extends Command {
/**
* sets the initial state to begin drawing
* @param options the options for drawing
* @returns
*/
start: (options: DrawOptions) => void;
/**
* continues drawing, smoothly interpolating between points where necessary
* @param options the options for drawing
* @returns
*/
continue: (options: Points) => void;
/**
* stops drawing
* @returns
*/
stop: () => void;
/**
* Whether or not the user is currently drawing.
*/
drawing: boolean;
}
/**
* Coordinates for a draw or erase path.
*/
interface Points {
/**
* The x coordinate of the path.
*/
x: number;
/**
* The y coordinate of the path.
*/
y: number;
}
/**
* Options for drawing a path.
*/
interface DrawOptions extends Points {
/**
* The size of the brush.
*/
size: number;
/**
* The color of the brush.
*/
color?: ColorSource;
/**
* The opacity of the brush.
*/
opacity: number;
/**
* Whether or not to set the initial texture.
*/
set_initial_texture?: boolean;
}
/**
* Draws a circle on the given graphics object.
* @param graphics the graphics object to draw on
* @param x the x coordinate of the circle
* @param y the y coordinate of the circle
* @param brush_color the color of the circle
* @param brush_size the radius of the circle
*/
function drawCircle(
graphics: Graphics,
x: number,
y: number,
brush_color: ColorSource = new Color("black"),
brush_size: number
): void {
const color = new Color(brush_color);
graphics.beginFill(color);
graphics.drawCircle(x, y, brush_size);
graphics.endFill();
}
/**
* Interpolates between two points.
* @param point1 the first point
* @param point2 the second point
* @returns an array of points between the two points
*/
function interpolate(
point1: { x: number; y: number },
point2: { x: number; y: number }
): Points[] {
let points: Points[] = [];
const dx = point2.x - point1.x;
const dy = point2.y - point1.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const steps = Math.ceil(distance / 2);
const stepX = dx / steps;
const stepY = dy / steps;
for (let j = 0; j < steps; j++) {
const x = point1.x + j * stepX;
const y = point1.y + j * stepY;
points.push({ x, y });
}
return points;
}
export function draw_path(
renderer: IRenderer,
stage: Container,
layer: LayerScene,
mode: "draw" | "erase"
): DrawCommand {
const paths: Points[] = [];
let initial_path: DrawOptions;
let graphics: Graphics;
let InitialTexture: RenderTexture;
let has_drawn = false;
let id = 0;
return {
drawing: false,
start: function ({
x,
y,
size,
color = new Color("black"),
opacity,
set_initial_texture = true
}: DrawOptions) {
if (set_initial_texture) {
InitialTexture = RenderTexture.create({
width: layer.draw_texture.width,
height: layer.draw_texture.height
});
renderer.render(layer.composite, {
renderTexture: InitialTexture
});
}
initial_path = { x, y, size, color, opacity };
paths.push({ x, y });
graphics = make_graphics(id++);
drawCircle(graphics, x, y, color, size);
renderer.render(graphics, {
renderTexture:
mode === "draw" ? layer.draw_texture : layer.erase_texture,
clear: false
});
this.drawing = true;
},
continue: function ({ x, y }: Points) {
const last_point = paths[paths.length - 1];
const new_points = interpolate(last_point, { x, y });
for (let i = 0; i < new_points.length; i++) {
const { x, y } = new_points[i];
drawCircle(graphics, x, y, initial_path.color, initial_path.size);
paths.push({ x, y });
}
renderer.render(graphics, {
renderTexture:
mode === "draw" ? layer.draw_texture : layer.erase_texture,
clear: false
});
graphics.clear();
},
stop: function () {
const current_sketch = RenderTexture.create({
width: layer.draw_texture.width,
height: layer.draw_texture.height
});
renderer.render(layer.composite, {
renderTexture: current_sketch
});
renderer.render(new Sprite(current_sketch), {
renderTexture: layer.draw_texture
});
const clear_graphics = new Graphics()
.beginFill(0x000000, 0) // Use a fill color with 0 alpha for transparency
.drawRect(0, 0, layer.erase_texture.width, layer.erase_texture.height)
.endFill();
renderer.render(clear_graphics, {
renderTexture: layer.erase_texture,
clear: true
});
has_drawn = true;
this.drawing = false;
},
execute: function () {
if (!has_drawn) {
for (let i = 1; i < paths.length; i++) {
const { x, y } = paths[i];
drawCircle(graphics, x, y, initial_path.color, initial_path.size);
}
renderer.render(graphics, {
renderTexture:
mode === "draw" ? layer.draw_texture : layer.erase_texture,
clear: false
});
this.stop!();
}
},
undo: function () {
const clear_graphics = new Graphics()
.beginFill(0x000000, 0)
.drawRect(0, 0, layer.erase_texture.width, layer.erase_texture.height)
.endFill();
renderer.render(new Sprite(InitialTexture), {
renderTexture: layer.draw_texture
});
renderer.render(clear_graphics, {
renderTexture: layer.erase_texture,
clear: true
});
this.stop!();
has_drawn = false;
}
};
}