Spaces:
Runtime error
Runtime error
Commit
·
e0c4dc2
1
Parent(s):
9f14b6c
ok, I think it works now
Browse files- src/app/engine/render.ts +22 -25
- src/app/games/vernian.ts +2 -2
- src/app/interface/top-menu/index.tsx +15 -3
- src/app/main.tsx +41 -9
- src/lib/fonts.ts +16 -1
- src/types.ts +4 -0
src/app/engine/render.ts
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
|
4 |
|
5 |
-
import { RenderedScene } from "@/types"
|
6 |
import { Engine, EngineType } from "./engines"
|
7 |
|
8 |
// note: there is no / at the end in the variable
|
@@ -15,10 +15,12 @@ export async function newRender({
|
|
15 |
prompt,
|
16 |
actionnables = [],
|
17 |
engine,
|
|
|
18 |
}: {
|
19 |
prompt: string
|
20 |
actionnables: string[]
|
21 |
engine: Engine
|
|
|
22 |
}) {
|
23 |
if (!prompt) {
|
24 |
console.error(`cannot call the rendering API without a prompt, aborting..`)
|
@@ -31,8 +33,6 @@ export async function newRender({
|
|
31 |
|
32 |
const nbFrames = engine.type.includes("video") ? 8 : 1
|
33 |
|
34 |
-
const cacheKey = `render/${JSON.stringify({ prompt, actionnables, nbFrames, type: engine.type })}`
|
35 |
-
|
36 |
// return await Gorgon.get(cacheKey, async () => {
|
37 |
|
38 |
let defaulResult: RenderedScene = {
|
@@ -49,18 +49,24 @@ export async function newRender({
|
|
49 |
|
50 |
const isForVideo = nbFrames > 1
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
const res = await fetch(`${apiUrl}/render`, {
|
65 |
method: "POST",
|
66 |
headers: {
|
@@ -68,16 +74,7 @@ export async function newRender({
|
|
68 |
"Content-Type": "application/json",
|
69 |
// Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
|
70 |
},
|
71 |
-
body: JSON.stringify(
|
72 |
-
prompt,
|
73 |
-
// nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
|
74 |
-
nbFrames, // when nbFrames is 1, we will only generate static images
|
75 |
-
nbSteps: isForVideo ? 30 : 35, // 20 = fast, 30 = better, 50 = best
|
76 |
-
actionnables,
|
77 |
-
segmentation: "firstframe", // one day we will remove this param, to make it automatic
|
78 |
-
width: isForVideo ? 576 : 1024,
|
79 |
-
height: isForVideo ? 320 : 768,
|
80 |
-
}),
|
81 |
cache: 'no-store',
|
82 |
// we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
|
83 |
// next: { revalidate: 1 }
|
|
|
2 |
|
3 |
|
4 |
|
5 |
+
import { RenderRequest, RenderedScene } from "@/types"
|
6 |
import { Engine, EngineType } from "./engines"
|
7 |
|
8 |
// note: there is no / at the end in the variable
|
|
|
15 |
prompt,
|
16 |
actionnables = [],
|
17 |
engine,
|
18 |
+
clearCache,
|
19 |
}: {
|
20 |
prompt: string
|
21 |
actionnables: string[]
|
22 |
engine: Engine
|
23 |
+
clearCache: boolean
|
24 |
}) {
|
25 |
if (!prompt) {
|
26 |
console.error(`cannot call the rendering API without a prompt, aborting..`)
|
|
|
33 |
|
34 |
const nbFrames = engine.type.includes("video") ? 8 : 1
|
35 |
|
|
|
|
|
36 |
// return await Gorgon.get(cacheKey, async () => {
|
37 |
|
38 |
let defaulResult: RenderedScene = {
|
|
|
49 |
|
50 |
const isForVideo = nbFrames > 1
|
51 |
|
52 |
+
const request = {
|
53 |
+
prompt,
|
54 |
+
// nbFrames: 8 and nbSteps: 15 --> ~10 sec generation
|
55 |
+
nbFrames, // when nbFrames is 1, we will only generate static images
|
56 |
+
nbSteps: isForVideo ? 30 : 35, // 20 = fast, 30 = better, 50 = best
|
57 |
+
actionnables,
|
58 |
+
segmentation: "firstframe", // one day we will remove this param, to make it automatic
|
59 |
+
width: isForVideo ? 576 : 1024,
|
60 |
+
height: isForVideo ? 320 : 768,
|
61 |
+
|
62 |
+
// note that we never disable the cache completely for VideoQuest
|
63 |
+
// that's because in the feedbacks people prefer speed to avoid frustration
|
64 |
+
cache: clearCache ? "renew" : "use",
|
65 |
+
|
66 |
+
} as Partial<RenderRequest>
|
67 |
+
|
68 |
+
console.table(request)
|
69 |
+
|
70 |
const res = await fetch(`${apiUrl}/render`, {
|
71 |
method: "POST",
|
72 |
headers: {
|
|
|
74 |
"Content-Type": "application/json",
|
75 |
// Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
|
76 |
},
|
77 |
+
body: JSON.stringify(request),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
cache: 'no-store',
|
79 |
// we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
|
80 |
// next: { revalidate: 1 }
|
src/app/games/vernian.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import {
|
2 |
import { Game } from "./types"
|
3 |
import { InventoryItem } from "../../types"
|
4 |
|
@@ -79,7 +79,7 @@ export const game: Game = {
|
|
79 |
"cartesian_video",
|
80 |
"spherical_image",
|
81 |
],
|
82 |
-
className:
|
83 |
initialSituation,
|
84 |
initialActionnables,
|
85 |
inventory,
|
|
|
1 |
+
import { moondance } from "@/lib/fonts"
|
2 |
import { Game } from "./types"
|
3 |
import { InventoryItem } from "../../types"
|
4 |
|
|
|
79 |
"cartesian_video",
|
80 |
"spherical_image",
|
81 |
],
|
82 |
+
className: moondance.className,
|
83 |
initialSituation,
|
84 |
initialActionnables,
|
85 |
inventory,
|
src/app/interface/top-menu/index.tsx
CHANGED
@@ -19,18 +19,23 @@ export function TopMenu({
|
|
19 |
engine,
|
20 |
defaultGame,
|
21 |
game,
|
|
|
|
|
22 |
onChangeEngine,
|
23 |
onChangeGame,
|
24 |
onToggleDebug,
|
25 |
-
|
26 |
}: {
|
27 |
engine: Engine,
|
28 |
defaultGame: string
|
29 |
game: Game
|
|
|
|
|
30 |
onChangeEngine: (newEngine: EngineType) => void
|
31 |
onChangeGame: (newGameType: GameType) => void
|
32 |
onToggleDebug: (isToggledOn: boolean) => void
|
33 |
-
|
|
|
34 |
}) {
|
35 |
return (
|
36 |
<div className={cn(
|
@@ -65,7 +70,14 @@ export function TopMenu({
|
|
65 |
<Label>Debug</Label>
|
66 |
</div>
|
67 |
<div className="flex flex-row items-center space-x-3 font-mono">
|
68 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
<Select
|
70 |
defaultValue={game.engines.includes(engine.type) ? engine.type : game.engines[0]}
|
71 |
onValueChange={(value) => { onChangeEngine(value as EngineType) }}>
|
|
|
19 |
engine,
|
20 |
defaultGame,
|
21 |
game,
|
22 |
+
debug,
|
23 |
+
clearCache,
|
24 |
onChangeEngine,
|
25 |
onChangeGame,
|
26 |
onToggleDebug,
|
27 |
+
onToggleClearCache,
|
28 |
}: {
|
29 |
engine: Engine,
|
30 |
defaultGame: string
|
31 |
game: Game
|
32 |
+
debug: boolean
|
33 |
+
clearCache: boolean
|
34 |
onChangeEngine: (newEngine: EngineType) => void
|
35 |
onChangeGame: (newGameType: GameType) => void
|
36 |
onToggleDebug: (isToggledOn: boolean) => void
|
37 |
+
onToggleClearCache: (shouldClearCache: boolean) => void
|
38 |
+
|
39 |
}) {
|
40 |
return (
|
41 |
<div className={cn(
|
|
|
70 |
<Label>Debug</Label>
|
71 |
</div>
|
72 |
<div className="flex flex-row items-center space-x-3 font-mono">
|
73 |
+
<Switch
|
74 |
+
checked={clearCache}
|
75 |
+
onCheckedChange={onToggleClearCache}
|
76 |
+
/>
|
77 |
+
<Label>No cache</Label>
|
78 |
+
</div>
|
79 |
+
<div className="flex flex-row items-center space-x-3 font-mono">
|
80 |
+
<Label className="flex text-sm">Engine:</Label>
|
81 |
<Select
|
82 |
defaultValue={game.engines.includes(engine.type) ? engine.type : game.engines[0]}
|
83 |
onValueChange={(value) => { onChangeEngine(value as EngineType) }}>
|
src/app/main.tsx
CHANGED
@@ -55,6 +55,9 @@ export default function Main() {
|
|
55 |
const requestedDebug = (searchParams.get('debug') === "true")
|
56 |
const [debug, setDebug] = useState<boolean>(requestedDebug)
|
57 |
|
|
|
|
|
|
|
58 |
const [situation, setSituation] = useState("")
|
59 |
|
60 |
const [dialogue, setDialogue] = useState("")
|
@@ -91,10 +94,10 @@ export default function Main() {
|
|
91 |
Array.isArray(nextActionnables) && nextActionnables.length
|
92 |
? nextActionnables
|
93 |
: game.initialActionnables
|
94 |
-
)
|
95 |
-
})
|
96 |
|
97 |
-
|
|
|
98 |
|
99 |
// detect if type game type changed while we were busy
|
100 |
// note that currently we reload the whol page when tha happens,
|
@@ -102,15 +105,25 @@ export default function Main() {
|
|
102 |
if (game?.type !== gameRef?.current) {
|
103 |
console.log("game type changed! aborting..")
|
104 |
return
|
|
|
|
|
|
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
}
|
107 |
-
// we cheat a bit by displaying the previous image as a placeholder
|
108 |
-
// this is better than displaying a blank image!
|
109 |
-
newRendered.assetUrl = rendered.assetUrl
|
110 |
-
newRendered.maskUrl = rendered.maskUrl
|
111 |
|
112 |
historyRef.current.unshift(newRendered)
|
113 |
setRendered(newRendered)
|
|
|
|
|
|
|
|
|
114 |
})
|
115 |
}
|
116 |
|
@@ -121,7 +134,7 @@ export default function Main() {
|
|
121 |
if (!historyRef.current[0]?.renderId || historyRef.current[0]?.status !== "pending") {
|
122 |
|
123 |
// console.log("let's try again in a moments")
|
124 |
-
loopRef.current = setTimeout(() => checkRenderedLoop(),
|
125 |
return
|
126 |
}
|
127 |
|
@@ -255,6 +268,23 @@ export default function Main() {
|
|
255 |
setDebug(isToggledOn)
|
256 |
}
|
257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
const handleSelectGame = (newGameType: GameType) => {
|
259 |
gameRef.current = newGameType
|
260 |
setGame(getGame(newGameType))
|
@@ -412,10 +442,12 @@ export default function Main() {
|
|
412 |
engine={engine}
|
413 |
game={game}
|
414 |
defaultGame={gameRef.current}
|
|
|
|
|
415 |
onToggleDebug={handleToggleDebug}
|
416 |
onChangeGame={handleSelectGame}
|
417 |
onChangeEngine={handleSelectEngine}
|
418 |
-
|
419 |
/>
|
420 |
|
421 |
<DndProvider backend={HTML5Backend}>
|
|
|
55 |
const requestedDebug = (searchParams.get('debug') === "true")
|
56 |
const [debug, setDebug] = useState<boolean>(requestedDebug)
|
57 |
|
58 |
+
const requestedClearCache = (searchParams.get('clearCache') ? (searchParams.get('clearCache') === "true") : false)
|
59 |
+
const [clearCache, setClearCache] = useState<boolean>(requestedClearCache)
|
60 |
+
|
61 |
const [situation, setSituation] = useState("")
|
62 |
|
63 |
const [dialogue, setDialogue] = useState("")
|
|
|
94 |
Array.isArray(nextActionnables) && nextActionnables.length
|
95 |
? nextActionnables
|
96 |
: game.initialActionnables
|
97 |
+
),
|
|
|
98 |
|
99 |
+
clearCache
|
100 |
+
})
|
101 |
|
102 |
// detect if type game type changed while we were busy
|
103 |
// note that currently we reload the whol page when tha happens,
|
|
|
105 |
if (game?.type !== gameRef?.current) {
|
106 |
console.log("game type changed! aborting..")
|
107 |
return
|
108 |
+
}
|
109 |
+
|
110 |
+
console.log("got the first version of our scene!", newRendered)
|
111 |
|
112 |
+
// in cache we didn't hit the cache and the request is still pending
|
113 |
+
// we cheat a bit by displaying the previous image as a placeholder
|
114 |
+
if (!newRendered.assetUrl && rendered.assetUrl && rendered.maskUrl) {
|
115 |
+
console.log("image is not in cache, using previous image as a placeholder..")
|
116 |
+
// this is better than displaying a blank image, no?
|
117 |
+
newRendered.assetUrl = rendered.assetUrl
|
118 |
+
newRendered.maskUrl = rendered.maskUrl
|
119 |
}
|
|
|
|
|
|
|
|
|
120 |
|
121 |
historyRef.current.unshift(newRendered)
|
122 |
setRendered(newRendered)
|
123 |
+
|
124 |
+
if (newRendered.status === "completed") {
|
125 |
+
setBusy(busyRef.current = false)
|
126 |
+
}
|
127 |
})
|
128 |
}
|
129 |
|
|
|
134 |
if (!historyRef.current[0]?.renderId || historyRef.current[0]?.status !== "pending") {
|
135 |
|
136 |
// console.log("let's try again in a moments")
|
137 |
+
loopRef.current = setTimeout(() => checkRenderedLoop(), 1000)
|
138 |
return
|
139 |
}
|
140 |
|
|
|
268 |
setDebug(isToggledOn)
|
269 |
}
|
270 |
|
271 |
+
const handleToggleClearCache = (shouldClearCache: boolean) => {
|
272 |
+
const current = new URLSearchParams(Array.from(searchParams.entries()))
|
273 |
+
current.set("clearCache", `${shouldClearCache}`)
|
274 |
+
const search = current.toString()
|
275 |
+
const query = search ? `?${search}` : ""
|
276 |
+
|
277 |
+
// for some reason, this doesn't work?!
|
278 |
+
router.replace(`${pathname}${query}`, { })
|
279 |
+
|
280 |
+
// workaround.. but it is strange that router.replace doesn't work..
|
281 |
+
let newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?' + search.toString()
|
282 |
+
window.history.pushState({path: newurl}, '', newurl)
|
283 |
+
|
284 |
+
setClearCache(shouldClearCache)
|
285 |
+
}
|
286 |
+
|
287 |
+
|
288 |
const handleSelectGame = (newGameType: GameType) => {
|
289 |
gameRef.current = newGameType
|
290 |
setGame(getGame(newGameType))
|
|
|
442 |
engine={engine}
|
443 |
game={game}
|
444 |
defaultGame={gameRef.current}
|
445 |
+
debug={debug}
|
446 |
+
clearCache={clearCache}
|
447 |
onToggleDebug={handleToggleDebug}
|
448 |
onChangeGame={handleSelectGame}
|
449 |
onChangeEngine={handleSelectEngine}
|
450 |
+
onToggleClearCache={handleToggleClearCache}
|
451 |
/>
|
452 |
|
453 |
<DndProvider backend={HTML5Backend}>
|
src/lib/fonts.ts
CHANGED
@@ -1,4 +1,12 @@
|
|
1 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import localFont from "next/font/local"
|
3 |
|
4 |
export const inter = Inter({
|
@@ -11,6 +19,13 @@ export const edu = Edu_SA_Beginner({
|
|
11 |
variable: "--font-edu",
|
12 |
})
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
export const orbitron = Orbitron({
|
15 |
subsets: ["latin"],
|
16 |
variable: "--font-orbitron",
|
|
|
1 |
+
import {
|
2 |
+
Inter,
|
3 |
+
Edu_SA_Beginner,
|
4 |
+
Orbitron,
|
5 |
+
Amatic_SC,
|
6 |
+
Macondo_Swash_Caps,
|
7 |
+
IM_Fell_English_SC,
|
8 |
+
Moon_Dance
|
9 |
+
} from "next/font/google"
|
10 |
import localFont from "next/font/local"
|
11 |
|
12 |
export const inter = Inter({
|
|
|
19 |
variable: "--font-edu",
|
20 |
})
|
21 |
|
22 |
+
export const moondance = Moon_Dance({
|
23 |
+
subsets: ["latin"],
|
24 |
+
weight: "400",
|
25 |
+
variable: "--font-moondance",
|
26 |
+
})
|
27 |
+
|
28 |
+
|
29 |
export const orbitron = Orbitron({
|
30 |
subsets: ["latin"],
|
31 |
variable: "--font-orbitron",
|
src/types.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
export type ProjectionMode = 'cartesian' | 'spherical'
|
2 |
|
|
|
|
|
3 |
export interface RenderRequest {
|
4 |
prompt: string
|
5 |
|
@@ -28,6 +30,8 @@ export interface RenderRequest {
|
|
28 |
height: number // fixed at 512 for now
|
29 |
|
30 |
projection: ProjectionMode
|
|
|
|
|
31 |
}
|
32 |
|
33 |
export interface ImageSegment {
|
|
|
1 |
export type ProjectionMode = 'cartesian' | 'spherical'
|
2 |
|
3 |
+
export type CacheMode = "use" | "renew" | "ignore"
|
4 |
+
|
5 |
export interface RenderRequest {
|
6 |
prompt: string
|
7 |
|
|
|
30 |
height: number // fixed at 512 for now
|
31 |
|
32 |
projection: ProjectionMode
|
33 |
+
|
34 |
+
cache: CacheMode
|
35 |
}
|
36 |
|
37 |
export interface ImageSegment {
|