Spaces:
Runtime error
Runtime error
Julian Bilcke commited on
Commit ·
9802882
1
Parent(s): 9a8adca
working to add some llama2 step
Browse files- package-lock.json +9 -0
- package.json +1 -0
- src/app/agents/pirates.ts +6 -4
- src/app/agents/server.ts +10 -0
- src/app/main.tsx +50 -45
- src/components/business/image-renderer.tsx +142 -58
package-lock.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
| 8 |
"name": "video-quest",
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
|
|
|
| 11 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 12 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 13 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
@@ -183,6 +184,14 @@
|
|
| 183 |
"react-dom": ">=16.8.0"
|
| 184 |
}
|
| 185 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
"node_modules/@humanwhocodes/config-array": {
|
| 187 |
"version": "0.11.10",
|
| 188 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
|
|
|
| 8 |
"name": "video-quest",
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
+
"@huggingface/inference": "^2.6.1",
|
| 12 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 13 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 14 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
|
|
| 184 |
"react-dom": ">=16.8.0"
|
| 185 |
}
|
| 186 |
},
|
| 187 |
+
"node_modules/@huggingface/inference": {
|
| 188 |
+
"version": "2.6.1",
|
| 189 |
+
"resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-2.6.1.tgz",
|
| 190 |
+
"integrity": "sha512-qFYchgOCPeEkZJKiSr7Kz62QwukJtgkeQCT7Q0SSKUcvHpTQVNJp6i/JrJMR4dBdzQysJ1SZDC0pLBBnnskTag==",
|
| 191 |
+
"engines": {
|
| 192 |
+
"node": ">=18"
|
| 193 |
+
}
|
| 194 |
+
},
|
| 195 |
"node_modules/@humanwhocodes/config-array": {
|
| 196 |
"version": "0.11.10",
|
| 197 |
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
package.json
CHANGED
|
@@ -9,6 +9,7 @@
|
|
| 9 |
"lint": "next lint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
|
|
|
| 12 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 13 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 14 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
|
|
| 9 |
"lint": "next lint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
+
"@huggingface/inference": "^2.6.1",
|
| 13 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 14 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 15 |
"@radix-ui/react-checkbox": "^1.0.4",
|
src/app/agents/pirates.ts
CHANGED
|
@@ -34,10 +34,13 @@ const actionnables = [
|
|
| 34 |
// "ship's wheel",
|
| 35 |
// "hat",
|
| 36 |
// "barrel",
|
| 37 |
-
|
| 38 |
// "rope",
|
| 39 |
// "bucket",
|
|
|
|
| 40 |
"parrot",
|
|
|
|
|
|
|
| 41 |
// "wooden leg"
|
| 42 |
]
|
| 43 |
|
|
@@ -54,9 +57,8 @@ export const agent: Agent = {
|
|
| 54 |
const prompt = [
|
| 55 |
`screenshot from an adventure videogame`,
|
| 56 |
`inside the hold of a pirate ship`,
|
| 57 |
-
`
|
| 58 |
-
`a parrot`,
|
| 59 |
-
`and a wooden leg`,
|
| 60 |
`at sunset`,
|
| 61 |
`unreal engine`,
|
| 62 |
].join(", ")
|
|
|
|
| 34 |
// "ship's wheel",
|
| 35 |
// "hat",
|
| 36 |
// "barrel",
|
| 37 |
+
"cannon",
|
| 38 |
// "rope",
|
| 39 |
// "bucket",
|
| 40 |
+
"skull",
|
| 41 |
"parrot",
|
| 42 |
+
"lock",
|
| 43 |
+
"ship",
|
| 44 |
// "wooden leg"
|
| 45 |
]
|
| 46 |
|
|
|
|
| 57 |
const prompt = [
|
| 58 |
`screenshot from an adventure videogame`,
|
| 59 |
`inside the hold of a pirate ship`,
|
| 60 |
+
`a pirate chest in the center with a large lock`,
|
| 61 |
+
`a parrot on top of it`,
|
|
|
|
| 62 |
`at sunset`,
|
| 63 |
`unreal engine`,
|
| 64 |
].join(", ")
|
src/app/agents/server.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use server"
|
| 2 |
+
|
| 3 |
+
import { HfInference } from "@huggingface/inference"
|
| 4 |
+
|
| 5 |
+
const hfi = new HfInference(process.env.HF_API_TOKEN)
|
| 6 |
+
const hf = hfi.endpoint(`${process.env.HF_INFERENCE_ENDPOINT_URL || ""}`)
|
| 7 |
+
|
| 8 |
+
export async function decideNextSteps(userAction: string) {
|
| 9 |
+
return ""
|
| 10 |
+
}
|
src/app/main.tsx
CHANGED
|
@@ -13,9 +13,9 @@ import {
|
|
| 13 |
} from "@/components/ui/select"
|
| 14 |
|
| 15 |
import { render } from "./render"
|
| 16 |
-
import {
|
| 17 |
import { agents, defaultAgent, getAgent } from "./agents"
|
| 18 |
-
import {
|
| 19 |
|
| 20 |
export default function Main() {
|
| 21 |
const [isPending, startTransition] = useTransition()
|
|
@@ -28,54 +28,59 @@ export default function Main() {
|
|
| 28 |
})
|
| 29 |
const ref = useRef<AgentType>(defaultAgent)
|
| 30 |
|
| 31 |
-
useEffect(() => {
|
| 32 |
-
|
| 33 |
-
const updateView = async () => {
|
| 34 |
-
// console.log(`update view..`)
|
| 35 |
-
|
| 36 |
-
await startTransition(async () => {
|
| 37 |
-
|
| 38 |
-
// console.log(`getting agent..`)
|
| 39 |
-
const type = ref?.current
|
| 40 |
-
const agent = getAgent(type)
|
| 41 |
-
|
| 42 |
-
// console.log(`asking agent to determine things..`)
|
| 43 |
-
const scene = agent.simulate()
|
| 44 |
-
|
| 45 |
-
// console.log(`rendering scene..`)
|
| 46 |
-
const newRendered = await render(
|
| 47 |
-
scene.prompt,
|
| 48 |
-
scene.actionnables.slice(0, 5) // too many can slow us down it seems
|
| 49 |
-
)
|
| 50 |
-
|
| 51 |
-
if (type !== ref?.current) {
|
| 52 |
-
console.log("agent type changed! reloading scene")
|
| 53 |
-
setTimeout(() => { updateView() }, 0)
|
| 54 |
-
return
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
if (newRendered.assetUrl) {
|
| 59 |
-
setRendered(newRendered)
|
| 60 |
-
// console.log(`got a new url: ${newUrl}`)
|
| 61 |
-
setScene(scene)
|
| 62 |
-
setTimeout(() => { updateView()}, 1000)
|
| 63 |
-
} else {
|
| 64 |
-
// console.log(`going to wait a bit more: ${newUrl}`)
|
| 65 |
-
setTimeout(() => { updateView()}, newRendered.error ? 6000 : 3000)
|
| 66 |
-
}
|
| 67 |
-
})
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
updateView()
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
}, [])
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
return (
|
| 75 |
<div className="flex flex-col w-full pt-4">
|
| 76 |
<div className="flex flex-col space-y-3 px-2">
|
| 77 |
<div className="flex flex-row items-center space-x-3">
|
| 78 |
-
<label className="flex">Select a
|
| 79 |
<Select
|
| 80 |
defaultValue={defaultAgent}
|
| 81 |
onValueChange={(value) => {
|
|
@@ -97,7 +102,7 @@ export default function Main() {
|
|
| 97 |
</SelectContent>
|
| 98 |
</Select>
|
| 99 |
</div>
|
| 100 |
-
<p>Note:
|
| 101 |
|
| 102 |
{(scene) ? <div>
|
| 103 |
<p>Action: {scene.action}</p>
|
|
@@ -111,7 +116,7 @@ export default function Main() {
|
|
| 111 |
</div>)}
|
| 112 |
</div>
|
| 113 |
</div>
|
| 114 |
-
<ImageRenderer {
|
| 115 |
</div>
|
| 116 |
)
|
| 117 |
}
|
|
|
|
| 13 |
} from "@/components/ui/select"
|
| 14 |
|
| 15 |
import { render } from "./render"
|
| 16 |
+
import { AgentType, Scene } from "./agents/types"
|
| 17 |
import { agents, defaultAgent, getAgent } from "./agents"
|
| 18 |
+
import { RenderedScene } from "./types"
|
| 19 |
|
| 20 |
export default function Main() {
|
| 21 |
const [isPending, startTransition] = useTransition()
|
|
|
|
| 28 |
})
|
| 29 |
const ref = useRef<AgentType>(defaultAgent)
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
+
const loadNextScene = async () => {
|
| 33 |
+
// console.log(`update view..`)
|
| 34 |
+
|
| 35 |
+
await startTransition(async () => {
|
| 36 |
+
|
| 37 |
+
// console.log(`getting agent..`)
|
| 38 |
+
const type = ref?.current
|
| 39 |
+
const agent = getAgent(type)
|
| 40 |
+
|
| 41 |
+
// console.log(`asking agent to determine things..`)
|
| 42 |
+
const scene = agent.simulate()
|
| 43 |
+
|
| 44 |
+
// console.log(`rendering scene..`)
|
| 45 |
+
const newRendered = await render(
|
| 46 |
+
scene.prompt,
|
| 47 |
+
scene.actionnables.slice(0, 5) // too many can slow us down it seems
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
if (type !== ref?.current) {
|
| 51 |
+
console.log("agent type changed! reloading scene")
|
| 52 |
+
setTimeout(() => { loadNextScene() }, 0)
|
| 53 |
+
return
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
if (newRendered.assetUrl) {
|
| 57 |
+
setRendered(newRendered)
|
| 58 |
+
// console.log(`got a new url: ${newUrl}`)
|
| 59 |
+
setScene(scene)
|
| 60 |
+
}
|
| 61 |
+
})
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
useEffect(() => {
|
| 65 |
+
loadNextScene()
|
| 66 |
}, [])
|
| 67 |
|
| 68 |
+
const handleUserAction = (action: string) => {
|
| 69 |
+
console.log("user action:", action)
|
| 70 |
+
|
| 71 |
+
// TODO: ask Llama2 what to do about it
|
| 72 |
+
// we need a frame and some actionnables,
|
| 73 |
+
// perhaps even some music or sound effects
|
| 74 |
+
|
| 75 |
+
console.log("we don't know what to do, so we just load the next frame!")
|
| 76 |
+
loadNextScene()
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
return (
|
| 80 |
<div className="flex flex-col w-full pt-4">
|
| 81 |
<div className="flex flex-col space-y-3 px-2">
|
| 82 |
<div className="flex flex-row items-center space-x-3">
|
| 83 |
+
<label className="flex">Select a story:</label>
|
| 84 |
<Select
|
| 85 |
defaultValue={defaultAgent}
|
| 86 |
onValueChange={(value) => {
|
|
|
|
| 102 |
</SelectContent>
|
| 103 |
</Select>
|
| 104 |
</div>
|
| 105 |
+
<p>Note: it takes about 1 minute to generate a new game panel</p>
|
| 106 |
|
| 107 |
{(scene) ? <div>
|
| 108 |
<p>Action: {scene.action}</p>
|
|
|
|
| 116 |
</div>)}
|
| 117 |
</div>
|
| 118 |
</div>
|
| 119 |
+
<ImageRenderer rendered={rendered} onUserAction={handleUserAction} />
|
| 120 |
</div>
|
| 121 |
)
|
| 122 |
}
|
src/components/business/image-renderer.tsx
CHANGED
|
@@ -1,73 +1,115 @@
|
|
| 1 |
-
import { useRef } from "react"
|
| 2 |
|
| 3 |
import { ImageSegment, RenderedScene } from "@/app/types"
|
| 4 |
|
| 5 |
export const ImageRenderer = ({
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
const imgRef = useRef<HTMLImageElement | null>(null)
|
| 11 |
-
const
|
| 12 |
-
const
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
const getPixelColor = (x: number, y: number) => {
|
| 15 |
-
|
| 16 |
-
if (!context) {
|
| 17 |
throw new Error("Unable to get context from canvas")
|
| 18 |
}
|
| 19 |
|
| 20 |
-
const imgData =
|
| 21 |
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
| 23 |
}
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
image.onload = function () {
|
| 35 |
-
if (context) {
|
| 36 |
-
context.drawImage(image, 0, 0)
|
| 37 |
-
|
| 38 |
-
const clickedColor = getPixelColor(x, y) as any
|
| 39 |
-
|
| 40 |
-
let closestSegment: ImageSegment | null = null
|
| 41 |
-
|
| 42 |
-
let minDistance = Infinity
|
| 43 |
-
|
| 44 |
-
segments.forEach(segment => {
|
| 45 |
-
const segmentColor = segment.color.slice(0,3) // get the RGB part only
|
| 46 |
-
|
| 47 |
-
const distance = Math.sqrt(
|
| 48 |
-
Math.pow(clickedColor[0] - segmentColor[0], 2) +
|
| 49 |
-
Math.pow(clickedColor[1] - segmentColor[1], 2) +
|
| 50 |
-
Math.pow(clickedColor[2] - segmentColor[2], 2)
|
| 51 |
-
)
|
| 52 |
-
|
| 53 |
-
if(distance < minDistance) {
|
| 54 |
-
minDistance = distance;
|
| 55 |
-
closestSegment = segment;
|
| 56 |
-
}
|
| 57 |
-
})
|
| 58 |
|
| 59 |
-
|
| 60 |
-
console.log(closestSegment) // Here is the closest matching segment
|
| 61 |
-
}
|
| 62 |
-
}
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
} else {
|
| 67 |
-
console.log("No mask available, aborting..")
|
| 68 |
}
|
| 69 |
-
}
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
if (!assetUrl) {
|
| 73 |
return <div className="flex w-full h-screen items-center justify-center text-center">
|
|
@@ -75,14 +117,56 @@ export const ImageRenderer = ({
|
|
| 75 |
</div>
|
| 76 |
}
|
| 77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
return (
|
| 79 |
<div className="w-full py-8 px-2">
|
| 80 |
-
<
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
</div>
|
| 87 |
)
|
| 88 |
}
|
|
|
|
| 1 |
+
import { useEffect, useRef, useState } from "react"
|
| 2 |
|
| 3 |
import { ImageSegment, RenderedScene } from "@/app/types"
|
| 4 |
|
| 5 |
export const ImageRenderer = ({
|
| 6 |
+
rendered: {
|
| 7 |
+
assetUrl = "",
|
| 8 |
+
maskBase64 = "",
|
| 9 |
+
segments = []
|
| 10 |
+
},
|
| 11 |
+
onUserAction,
|
| 12 |
+
}: {
|
| 13 |
+
rendered: RenderedScene
|
| 14 |
+
onUserAction: (action: string) => void
|
| 15 |
+
}) => {
|
| 16 |
const imgRef = useRef<HTMLImageElement | null>(null)
|
| 17 |
+
const canvasRef = useRef<HTMLCanvasElement | null>(null)
|
| 18 |
+
const contextRef = useRef<CanvasRenderingContext2D | null>(null)
|
| 19 |
+
const [actionnable, setActionnable] = useState<string>("")
|
| 20 |
+
|
| 21 |
+
useEffect(() => {
|
| 22 |
+
if (maskBase64) {
|
| 23 |
+
console.log("maskBase64:", maskBase64)
|
| 24 |
+
const img = new Image();
|
| 25 |
+
img.onload = function () {
|
| 26 |
+
canvasRef.current = document.createElement('canvas');
|
| 27 |
+
canvasRef.current.width = img.width;
|
| 28 |
+
canvasRef.current.height = img.height;
|
| 29 |
+
contextRef.current = canvasRef.current.getContext('2d');
|
| 30 |
+
contextRef.current!.drawImage(img, 0, 0, img.width, img.height);
|
| 31 |
+
}
|
| 32 |
+
img.src = "data:image/png;base64," + maskBase64;
|
| 33 |
+
} else {
|
| 34 |
+
console.log("error, no maskBase64 detected!")
|
| 35 |
+
}
|
| 36 |
+
}, [maskBase64]);
|
| 37 |
+
|
| 38 |
+
|
| 39 |
const getPixelColor = (x: number, y: number) => {
|
| 40 |
+
if (!contextRef.current) {
|
|
|
|
| 41 |
throw new Error("Unable to get context from canvas")
|
| 42 |
}
|
| 43 |
|
| 44 |
+
const imgData = contextRef.current.getImageData(x, y, 1, 1).data
|
| 45 |
|
| 46 |
+
|
| 47 |
+
const clickedColor = Array.from(imgData.slice(0, 3), value => value / 255);
|
| 48 |
+
|
| 49 |
+
return clickedColor
|
| 50 |
}
|
| 51 |
|
| 52 |
+
|
| 53 |
+
const getSegmentAt = (x: number, y: number): ImageSegment => {
|
| 54 |
+
if (!contextRef.current) throw new Error("Unable to get context from canvas");
|
| 55 |
+
if (!maskBase64) throw new Error("Mask is undefined");
|
| 56 |
+
|
| 57 |
+
let closestSegment: ImageSegment = {
|
| 58 |
+
id: 0,
|
| 59 |
+
box: [],
|
| 60 |
+
color: [],
|
| 61 |
+
label: "",
|
| 62 |
+
score: 0,
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
const clickedColor = getPixelColor(x,y) as any
|
| 66 |
+
|
| 67 |
+
if (`${clickedColor}` === "1,1,1") {
|
| 68 |
+
return closestSegment
|
| 69 |
+
}
|
| 70 |
|
| 71 |
+
let minDistance = Infinity;
|
| 72 |
+
|
| 73 |
+
segments.forEach(segment => {
|
| 74 |
+
const segmentColor = segment.color.slice(0,3); // get the RGB part only
|
| 75 |
+
|
| 76 |
+
const distance = Math.sqrt(
|
| 77 |
+
Math.pow(clickedColor[0] - segmentColor[0], 2) +
|
| 78 |
+
Math.pow(clickedColor[1] - segmentColor[1], 2) +
|
| 79 |
+
Math.pow(clickedColor[2] - segmentColor[2], 2)
|
| 80 |
+
);
|
| 81 |
+
|
| 82 |
+
if(distance < minDistance) {
|
| 83 |
+
minDistance = distance;
|
| 84 |
+
closestSegment = segment;
|
| 85 |
+
}
|
| 86 |
+
});
|
| 87 |
+
|
| 88 |
+
return closestSegment;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
const handleMouseEvent = (event: React.MouseEvent, isClickEvent: boolean = false) => {
|
| 92 |
+
if (!contextRef.current) return; // Return early if mask image has not been loaded yet
|
| 93 |
|
| 94 |
+
const boundingRect = imgRef.current!.getBoundingClientRect();
|
| 95 |
+
const x = event.clientX - boundingRect.left;
|
| 96 |
+
const y = event.clientY - boundingRect.top;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
const newSegment = getSegmentAt(x, y)
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
+
if (actionnable !== newSegment.label) {
|
| 101 |
+
setActionnable(newSegment.label)
|
|
|
|
|
|
|
| 102 |
}
|
|
|
|
| 103 |
|
| 104 |
+
if (!newSegment.label) { return }
|
| 105 |
+
|
| 106 |
+
console.log("actionnable: ", actionnable)
|
| 107 |
+
|
| 108 |
+
if (isClickEvent) {
|
| 109 |
+
console.log("User clicked on " + actionnable);
|
| 110 |
+
// onUserAction(actionnable);
|
| 111 |
+
}
|
| 112 |
+
};
|
| 113 |
|
| 114 |
if (!assetUrl) {
|
| 115 |
return <div className="flex w-full h-screen items-center justify-center text-center">
|
|
|
|
| 117 |
</div>
|
| 118 |
}
|
| 119 |
|
| 120 |
+
/*
|
| 121 |
+
<img
|
| 122 |
+
src={assetUrl}
|
| 123 |
+
ref={imgRef}
|
| 124 |
+
width="1024px"
|
| 125 |
+
height="512px"
|
| 126 |
+
className={
|
| 127 |
+
[
|
| 128 |
+
"absolute top-0 left-0",
|
| 129 |
+
actionnable ? "cursor-pointer" : ""
|
| 130 |
+
].join(" ")
|
| 131 |
+
}
|
| 132 |
+
onMouseDown={(event) => handleMouseEvent(event, true)}
|
| 133 |
+
onMouseMove={handleMouseEvent}
|
| 134 |
+
/>
|
| 135 |
+
|
| 136 |
+
<img
|
| 137 |
+
src={"data:image/png;base64," + maskBase64}
|
| 138 |
+
ref={imgRef}
|
| 139 |
+
width="1024px"
|
| 140 |
+
height="512px"
|
| 141 |
+
className={
|
| 142 |
+
[
|
| 143 |
+
"absolute top-0 left-0 opacity-30",
|
| 144 |
+
actionnable ? "cursor-pointer" : ""
|
| 145 |
+
].join(" ")
|
| 146 |
+
}
|
| 147 |
+
onMouseDown={(event) => handleMouseEvent(event, true)}
|
| 148 |
+
onMouseMove={handleMouseEvent}
|
| 149 |
+
/>
|
| 150 |
+
*/
|
| 151 |
+
|
| 152 |
return (
|
| 153 |
<div className="w-full py-8 px-2">
|
| 154 |
+
<div className="relative w-full">
|
| 155 |
+
<img
|
| 156 |
+
src={"data:image/png;base64," + maskBase64}
|
| 157 |
+
ref={imgRef}
|
| 158 |
+
width="1024px"
|
| 159 |
+
height="512px"
|
| 160 |
+
className={
|
| 161 |
+
[
|
| 162 |
+
"absolute top-0 left-0 opacity-30",
|
| 163 |
+
actionnable ? "cursor-pointer" : ""
|
| 164 |
+
].join(" ")
|
| 165 |
+
}
|
| 166 |
+
onMouseDown={(event) => handleMouseEvent(event, true)}
|
| 167 |
+
onMouseMove={handleMouseEvent}
|
| 168 |
+
/>
|
| 169 |
+
</div>
|
| 170 |
</div>
|
| 171 |
)
|
| 172 |
}
|