diff --git a/components/studio/drawing/drawing-canvas.tsx b/components/studio/drawing/drawing-canvas.tsx index f025c2d..0a30e61 100644 --- a/components/studio/drawing/drawing-canvas.tsx +++ b/components/studio/drawing/drawing-canvas.tsx @@ -56,9 +56,17 @@ export default function DrawingCanvas() { const points = path.points.map((p) => [p.x + dx, p.y + dy, p.pressure ?? 0.5]) const stroke = getStroke(points, { size: path.strokeWidth, - thinning: 0.6, - smoothing: 0.6, - streamline: 0.4, + thinning: 0.5, + smoothing: 0.5, + streamline: 0.5, + start: { + cap: true, + taper: 0, + }, + end: { + cap: true, + taper: 0, + }, }) if (stroke.length > 1) { @@ -67,7 +75,8 @@ export default function DrawingCanvas() { for (let i = 1; i < stroke.length; i += 1) { ctx.lineTo(stroke[i][0], stroke[i][1]) } - ctx.stroke() + ctx.closePath() + ctx.fill() } ctx.restore() }) @@ -107,9 +116,16 @@ export default function DrawingCanvas() { const updated = drawings.map((path, index) => { if (index === drawings.length - 1) { - return { - ...path, - points: [...path.points, point] + const lastPoint = path.points[path.points.length - 1] + const isDuplicate = lastPoint && + Math.abs(lastPoint.x - point.x) < 0.5 && + Math.abs(lastPoint.y - point.y) < 0.5 + + if (!isDuplicate) { + return { + ...path, + points: [...path.points, point] + } } } return path @@ -134,10 +150,19 @@ export default function DrawingCanvas() { { + e.currentTarget.setPointerCapture(e.pointerId) + handlePointerDown(e) + }} onPointerMove={handlePointerMove} - onPointerUp={handlePointerUp} - onPointerLeave={handlePointerUp} + onPointerUp={(e) => { + e.currentTarget.setPointerCapture(e.pointerId) + handlePointerUp() + }} + onPointerLeave={(e) => { + e.currentTarget.setPointerCapture(e.pointerId) + handlePointerUp() + }} style={{ touchAction: 'none', cursor, pointerEvents }} /> ) diff --git a/components/studio/image/add-image-button.tsx b/components/studio/image/add-image-button.tsx index 797eddf..d59e778 100644 --- a/components/studio/image/add-image-button.tsx +++ b/components/studio/image/add-image-button.tsx @@ -26,11 +26,13 @@ export default function AddImageButton({ }: AddImageButtonProps) { if (file) { const imageUrl = URL.createObjectURL(file) + const newImageId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 + setImages([ ...images, { image: imageUrl, - id: images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1, + id: newImageId, style: images.length < 1 ? defaultStyle @@ -62,7 +64,7 @@ export default function AddImageButton({ }: AddImageButtonProps) { setResolution(newResolution.toString()) } } - setSelectedImage(images.length) + setSelectedImage(newImageId) } } diff --git a/components/studio/main-image.tsx b/components/studio/main-image.tsx index a0050a2..93c7579 100644 --- a/components/studio/main-image.tsx +++ b/components/studio/main-image.tsx @@ -105,11 +105,12 @@ const ImageUpload = () => { const file = item.getAsFile(); if (!file) continue; const imageUrl = URL.createObjectURL(file); + const pastedImageId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 setImages([ ...images, { image: imageUrl, - id: images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1, + id: pastedImageId, style: images.length < 1 ? defaultStyle : { @@ -301,12 +302,13 @@ function LoadAImage() { setInitialImageUploaded(true) + const loadedImageId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 setImagesCheck([...imagesCheck, imageUrl]) setImages([ ...images, - { image: imageUrl, id: images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1, style: defaultStyle }, + { image: imageUrl, id: loadedImageId, style: defaultStyle }, ]) - setSelectedImage(images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1) + setSelectedImage(loadedImageId) if (localStorage.getItem('image-init-pro-tip') === null) { toast.info("Pro Trip!", { description: "If you right click on the image, you can replace it, delete it, or even crop it!", position: "top-left" }); @@ -359,13 +361,13 @@ function LoadAImage() { try { const imageUrl = URL.createObjectURL(file) setInitialImageUploaded(true) - + const newImageId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 setImagesCheck([...imagesCheck, imageUrl]) setImages([ ...images, - { image: imageUrl, id: images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1, style: defaultStyle }, + { image: imageUrl, id: newImageId, style: defaultStyle }, ]) - setSelectedImage(images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1) + setSelectedImage(newImageId) if (localStorage.getItem('image-init-pro-tip') === null) { toast.info("Pro Trip!", { description: "If you right click on the image, you can replace it, delete it, or even crop it!", position: "top-left" }); @@ -435,13 +437,13 @@ function LoadAImage() { // setBackground(gradient); // document?.documentElement.style.setProperty('--gradient-bg', gradient); - const nextId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 + const demoImageId = images.length > 0 ? Math.max(...images.map(img => img.id)) + 1 : 1 setInitialImageUploaded(true) setImages([ ...images, { image: imageSrc, - id: nextId, + id: demoImageId, style: { ...defaultStyle, imageRoundness: 0.7, @@ -449,7 +451,7 @@ function LoadAImage() { }, }, ]); - setSelectedImage(nextId) + setSelectedImage(demoImageId) setImagesCheck([...imagesCheck, imageSrc]); if (localStorage.getItem('image-init-pro-tip') === null) { diff --git a/components/studio/sidebar-buttons.tsx b/components/studio/sidebar-buttons.tsx index cdbfa97..c3585d7 100644 --- a/components/studio/sidebar-buttons.tsx +++ b/components/studio/sidebar-buttons.tsx @@ -2,6 +2,7 @@ import { Button } from '@/components/ui/button' import { useActiveIndexStore } from '@/store/use-active-index' +import { useDrawingTools } from '@/store/use-drawing' export default function SidebarButton({ icon, @@ -14,10 +15,17 @@ export default function SidebarButton({ }) { const activeIndex = useActiveIndexStore((state) => state.activeIndex) const setActiveIndex = useActiveIndexStore((state) => state.setActiveIndex) + const { setCurrentTool, currentTool } = useDrawingTools() + + const handleClick = () => { + setActiveIndex(index) + if (index === 4) setCurrentTool('pen'); + else if (activeIndex === 4 && currentTool !== 'select') setCurrentTool('select'); + } return (
  • setActiveIndex(index)} + onClick={handleClick} className={`click-ignored relative flex flex-col items-center gap-2`} >