Adding jump and replay functionality
This commit is contained in:
parent
c45fce2c2f
commit
e6cdab9293
|
@ -1,5 +1,6 @@
|
|||
import { PlayingState } from "../types";
|
||||
import { InferenceInput, InferenceResult, PlayingState } from "../types";
|
||||
import { IoMdClose } from "react-icons/io";
|
||||
import Pause from "./Pause";
|
||||
|
||||
interface PromptEntryProps {
|
||||
prompt: string;
|
||||
|
@ -7,6 +8,9 @@ interface PromptEntryProps {
|
|||
className: string;
|
||||
playingState: PlayingState;
|
||||
resetCallback: () => void;
|
||||
inferenceResults: InferenceResult[];
|
||||
nowPlayingResult: InferenceResult;
|
||||
setPaused: (value: boolean) => void;
|
||||
}
|
||||
|
||||
export default function PromptEntry({
|
||||
|
@ -15,68 +19,117 @@ export default function PromptEntry({
|
|||
className,
|
||||
playingState,
|
||||
resetCallback,
|
||||
inferenceResults,
|
||||
nowPlayingResult,
|
||||
setPaused
|
||||
}: PromptEntryProps) {
|
||||
|
||||
const getPromptCopy = (prompt: string) => {
|
||||
switch (playingState) {
|
||||
case PlayingState.UNINITIALIZED:
|
||||
case PlayingState.SAME_PROMPT:
|
||||
switch (index) {
|
||||
case 0:
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="⏪ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
);
|
||||
case 1:
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="⏪ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
);
|
||||
case 2:
|
||||
// active prompt
|
||||
if (prompt == " " || prompt == "") {
|
||||
return <span className="text-slate-600">{"<enter prompt>"}</span>;
|
||||
} else {
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🔁 Restart current prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
case 3:
|
||||
if (prompt == " " || prompt == "") {
|
||||
return "...";
|
||||
return <p className={className}>...</p>
|
||||
} else {
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🚀 Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
case 4:
|
||||
if (prompt == " " || prompt == "") {
|
||||
return "UP NEXT: Anything you want";
|
||||
return <p className={className}>UP NEXT: Anything you want</p>;
|
||||
} else {
|
||||
return "UP NEXT: " + prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🚀 Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>UP NEXT: {prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
default: {
|
||||
console.log("UNHANDLED default");
|
||||
return prompt;
|
||||
return <p className={className}>{prompt}</p>;
|
||||
}
|
||||
}
|
||||
case PlayingState.TRANSITION:
|
||||
switch (index) {
|
||||
case 0:
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="⏪ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
);
|
||||
case 1:
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="⏪ Jump to previous prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
);
|
||||
case 2:
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🔁 Restart outgoing prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
)
|
||||
case 3:
|
||||
if (prompt == " " || prompt == "") {
|
||||
return "< enter prompt >";
|
||||
return <p className={className}> -enter prompt- </p>;
|
||||
} else {
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🚀 Jump to incoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>{prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
case 4:
|
||||
if (prompt == " " || prompt == "") {
|
||||
return "...";
|
||||
return <p className={className}>...</p>;
|
||||
} else {
|
||||
return prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🚀 Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>UP NEXT: {prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
case 5:
|
||||
if (prompt == " " || prompt == "") {
|
||||
return "UP NEXT: Anything you want";
|
||||
return <p className={className}>UP NEXT: Anything you want</p>;
|
||||
} else {
|
||||
return "UP NEXT: " + prompt;
|
||||
return (
|
||||
<div className="tooltip text-left" data-tip="🚀 Jump to upcoming prompt?" onClick={() => { jumpToPrompt(prompt, inferenceResults, setPaused, nowPlayingResult) }} >
|
||||
<p className={className}>UP NEXT: {prompt}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
default: {
|
||||
console.log("UNHANDLED default");
|
||||
return prompt;
|
||||
return <p className={className}>{prompt}</p>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +137,8 @@ export default function PromptEntry({
|
|||
|
||||
return (
|
||||
<div className="flex">
|
||||
<p className={className}>{getPromptCopy(prompt)}</p>
|
||||
{getPromptCopy(prompt)}
|
||||
|
||||
{/* TODO(hayk): Re-enable this when it's working. */}
|
||||
{/* {index == 2 ? (
|
||||
<IoMdClose
|
||||
|
@ -94,6 +148,124 @@ export default function PromptEntry({
|
|||
}}
|
||||
/>
|
||||
) : null} */}
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
||||
export function jumpToPrompt(prompt: String, inferenceResults: InferenceResult[], setPaused: (value: boolean) => void, nowPlayingResult?: InferenceResult) {
|
||||
|
||||
// Pause player since this function will open new tab that user will interact with
|
||||
setPaused(true)
|
||||
|
||||
let firstTimePromptAppears = -1;
|
||||
for (let i = 0; i < inferenceResults.length; i++) {
|
||||
if (inferenceResults[i].input.start.prompt === prompt) {
|
||||
firstTimePromptAppears = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (firstTimePromptAppears == -1) {
|
||||
let url = generateLinkToUpcomingPrompt(prompt, nowPlayingResult)
|
||||
window.open(url, "_blank").focus();
|
||||
}
|
||||
else {
|
||||
let url = generateLinkToPreviousInput(inferenceResults[firstTimePromptAppears].input)
|
||||
window.open(url, "_blank").focus();
|
||||
}
|
||||
}
|
||||
|
||||
export function generateLinkToUpcomingPrompt(prompt, nowPlayingResult?: InferenceResult) {
|
||||
|
||||
var promptString = "&prompt=" + prompt;
|
||||
promptString = promptString.replace(/ /g, "+");
|
||||
|
||||
if (nowPlayingResult != null) {
|
||||
var denoisingString = "&denoising=" + nowPlayingResult.input.start.denoising;
|
||||
var seedImageIdString = "&seedImageId=" + nowPlayingResult.input.seed_image_id;
|
||||
} else {
|
||||
denoisingString = "";
|
||||
seedImageIdString = "";
|
||||
}
|
||||
|
||||
var baseUrl = window.location.origin + "/?";
|
||||
var url = baseUrl + promptString + denoisingString + seedImageIdString;
|
||||
return url;
|
||||
}
|
||||
|
||||
// Todo: DRY this and share functions
|
||||
export function generateLinkToPreviousInput(selectedInput: InferenceInput) {
|
||||
var prompt;
|
||||
var seed;
|
||||
var denoising;
|
||||
var maskImageId;
|
||||
var seedImageId;
|
||||
var guidance;
|
||||
var numInferenceSteps;
|
||||
var alphaVelocity;
|
||||
|
||||
prompt = selectedInput.start.prompt;
|
||||
seed = selectedInput.start.seed;
|
||||
denoising = selectedInput.start.denoising;
|
||||
maskImageId = selectedInput.mask_image_id;
|
||||
seedImageId = selectedInput.seed_image_id;
|
||||
|
||||
var baseUrl = window.location.origin + "/?";
|
||||
|
||||
if (prompt != null) {
|
||||
var promptString = "&prompt=" + prompt;
|
||||
} else {
|
||||
promptString = "";
|
||||
}
|
||||
if (seed != null) {
|
||||
var seedString = "&seed=" + seed;
|
||||
} else {
|
||||
seedString = "";
|
||||
}
|
||||
if (denoising != null) {
|
||||
var denoisingString = "&denoising=" + denoising;
|
||||
} else {
|
||||
denoisingString = "";
|
||||
}
|
||||
if (maskImageId != null) {
|
||||
var maskImageIdString = "&maskImageId=" + maskImageId;
|
||||
} else {
|
||||
maskImageIdString = "";
|
||||
}
|
||||
if (seedImageId != null) {
|
||||
var seedImageIdString = "&seedImageId=" + seedImageId;
|
||||
} else {
|
||||
seedImageIdString = "";
|
||||
}
|
||||
if (guidance != null) {
|
||||
var guidanceString = "&guidance=" + guidance;
|
||||
} else {
|
||||
guidanceString = "";
|
||||
}
|
||||
if (numInferenceSteps != null) {
|
||||
var numInferenceStepsString = "&numInferenceSteps=" + numInferenceSteps;
|
||||
} else {
|
||||
numInferenceStepsString = "";
|
||||
}
|
||||
if (alphaVelocity != null) {
|
||||
var alphaVelocityString = "&alphaVelocity=" + alphaVelocity;
|
||||
} else {
|
||||
alphaVelocityString = "";
|
||||
}
|
||||
|
||||
// Format strings to have + in place of spaces for ease of sharing, note this is only necessary for prompts currently
|
||||
promptString = promptString.replace(/ /g, "+");
|
||||
|
||||
// create url string with the variables above combined
|
||||
var shareUrl =
|
||||
baseUrl +
|
||||
promptString +
|
||||
seedString +
|
||||
denoisingString +
|
||||
maskImageIdString +
|
||||
seedImageIdString +
|
||||
guidanceString +
|
||||
numInferenceStepsString +
|
||||
alphaVelocityString;
|
||||
|
||||
return shareUrl;
|
||||
}
|
|
@ -10,6 +10,7 @@ interface PromptPanelProps {
|
|||
appState: AppState;
|
||||
changePrompt: (prompt: string, index: number) => void;
|
||||
resetCallback: () => void;
|
||||
setPaused: (paused: boolean) => void;
|
||||
}
|
||||
|
||||
export default function PromptPanel({
|
||||
|
@ -19,6 +20,7 @@ export default function PromptPanel({
|
|||
appState,
|
||||
changePrompt,
|
||||
resetCallback,
|
||||
setPaused,
|
||||
}: PromptPanelProps) {
|
||||
const inputPrompt = useRef(null);
|
||||
|
||||
|
@ -150,12 +152,15 @@ export default function PromptPanel({
|
|||
<div className="h-[78vh] landscape:sm:max-[750px]:h-[62vh] md:h-[80vh] flex flex-col justify-around pt-[10vh] pr-5">
|
||||
{getDisplayPrompts().map((prompt, index) => (
|
||||
<PromptEntry
|
||||
prompt={prompt.prompt + " "}
|
||||
prompt={prompt.prompt}
|
||||
className={getPromptEntryClassName(index)}
|
||||
index={index}
|
||||
key={index}
|
||||
playingState={playingState}
|
||||
resetCallback={resetCallback}
|
||||
inferenceResults={inferenceResults}
|
||||
nowPlayingResult={nowPlayingResult}
|
||||
setPaused={setPaused}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -194,6 +199,10 @@ export default function PromptPanel({
|
|||
);
|
||||
}
|
||||
|
||||
export function refreshPage() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
const promptEntryClassNameDict = {
|
||||
0: "font-extralight text-xs text-gray-500 text-opacity-20",
|
||||
1: "font-extralight text-xs text-gray-400 text-opacity-20",
|
||||
|
|
|
@ -13,7 +13,7 @@ import Pause from "../components/Pause";
|
|||
import PromptPanel from "../components/PromptPanel";
|
||||
import ThreeCanvas from "../components/ThreeCanvas";
|
||||
|
||||
import { samplePrompts } from "../prompts";
|
||||
import { samplePrompts, initialSeeds, initialSeedImageMap } from "../prompts";
|
||||
|
||||
import {
|
||||
AppState,
|
||||
|
@ -22,10 +22,6 @@ import {
|
|||
PromptInput,
|
||||
} from "../types";
|
||||
|
||||
function getRandomInt(max: number) {
|
||||
return Math.floor(Math.random() * max);
|
||||
}
|
||||
|
||||
function getRandomFromArray(arr: any[], n: number) {
|
||||
var result = new Array(n),
|
||||
len = arr.length,
|
||||
|
@ -51,11 +47,11 @@ export default function Home() {
|
|||
const [alpha, setAlpha] = useState(0.0);
|
||||
const [alphaRollover, setAlphaRollover] = useState(false);
|
||||
const [alphaVelocity, setAlphaVelocity] = useState(0.25);
|
||||
const [seed, setSeed] = useState(getRandomInt(1000000));
|
||||
|
||||
// Settings
|
||||
const [denoising, setDenoising] = useState(0.75);
|
||||
const [seedImageId, setSeedImageId] = useState("og_beat");
|
||||
const [seedImageId, setSeedImageId] = useState(initialSeeds[Math.floor(Math.random() * initialSeeds.length)]);
|
||||
const [seed, setSeed] = useState(initialSeedImageMap[seedImageId][Math.floor(Math.random() * initialSeedImageMap[seedImageId].length)]);
|
||||
|
||||
// Prompts shown on screen and maintained by the prompt panel
|
||||
const [promptInputs, setPromptInputs] = useState<PromptInput[]>([]);
|
||||
|
@ -330,10 +326,14 @@ export default function Home() {
|
|||
newPromptInputs[index].prompt = prompt;
|
||||
setPromptInputs(newPromptInputs);
|
||||
}}
|
||||
setPaused={setPaused}
|
||||
resetCallback={resetCallback}
|
||||
/>
|
||||
|
||||
<Pause paused={paused} setPaused={setPaused} />
|
||||
<Pause
|
||||
paused={paused}
|
||||
setPaused={setPaused}
|
||||
/>
|
||||
|
||||
<Share
|
||||
inferenceResults={inferenceResults}
|
||||
|
|
65
prompts.ts
65
prompts.ts
|
@ -3,24 +3,59 @@ export const samplePrompts = [
|
|||
"lo-fi beat for the holidays",
|
||||
"techno DJ and a country singer",
|
||||
"classical italian tenor operatic pop",
|
||||
"arabic (vocals:1.5)",
|
||||
"typing",
|
||||
"chainsaw funk",
|
||||
"dance pop edm electropop indietronica metropopolis pop uk pop",
|
||||
"edm electropop indietronica metropopolis",
|
||||
"kygo tropical dance marvin gaye",
|
||||
"west coast rap vocals 808",
|
||||
"detroit hip hop 808",
|
||||
"church bells",
|
||||
"funk bassline with a jazzy saxophone solo",
|
||||
"piano funk",
|
||||
"a jazz pianist playing a concerto",
|
||||
"funk bassline with a jazzy saxophone",
|
||||
"a pianist playing a concerto",
|
||||
"rock and roll electric guitar solo",
|
||||
"acoustic folk fiddle jam",
|
||||
"jamaican rap",
|
||||
"church organ with a harpsichord",
|
||||
"late romantic era in the style of Richard Wagner",
|
||||
"acoustic folk violin jam",
|
||||
"k-pop boy group",
|
||||
"typing",
|
||||
"post-teen pop talent show winner",
|
||||
"sean paul dancehall",
|
||||
"mambo but from kenya",
|
||||
"classical flute",
|
||||
"swing jazz trumpet",
|
||||
"tropical deep sea",
|
||||
"laughing",
|
||||
"lo-fi beat with a violin",
|
||||
"bubblegum eurodance",
|
||||
];
|
||||
|
||||
export const rollTheDicePrompts = [
|
||||
"arabic (vocals:1.5)",
|
||||
"classic rock mellow gold progressive",
|
||||
"west coast rap vocals",
|
||||
"classical flute",
|
||||
"church organ with a harpsichord",
|
||||
"uk permanent wave pop",
|
||||
"chainsaw funk",
|
||||
"laughing",
|
||||
"tropical deep sea",
|
||||
"piano funk",
|
||||
"jamaican ska rap",
|
||||
"tropical electro house moombahton",
|
||||
"breathing",
|
||||
"water drops",
|
||||
"british soul dance",
|
||||
"pop r&b urban contemporary",
|
||||
"baroque pop new wave",
|
||||
"reggae fusion",
|
||||
"tropical german dance house",
|
||||
// TODO: consider adding samplePrompts to this list when using it
|
||||
];
|
||||
|
||||
export const initialSeedImageMap = {
|
||||
"og_beat": [3, 738973, 51209, 745234],
|
||||
"agile": [808, 231, 3324, 323984],
|
||||
"marim": [123, 676, 6754, 8730],
|
||||
// "motorway": [8730, 323984, 745234],
|
||||
// "vibes": [4205, 94, 78530]
|
||||
}
|
||||
|
||||
export const initialSeeds = [
|
||||
"og_beat",
|
||||
"agile",
|
||||
"marim",
|
||||
// "motorway",
|
||||
// "vibes"
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue