mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-27 08:48:14 +00:00
added new components (#113)
various components for studio video style transfer --------- Co-authored-by: Victor <victor@storyteller.ai> Co-authored-by: Lee-Orr <lee-orr@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
import MakeRequest from "./MakeRequest";
|
||||||
|
|
||||||
|
export interface EnqueueEngineCompositingRequest {
|
||||||
|
uuid_idempotency_token: string,
|
||||||
|
media_file_token: string,
|
||||||
|
camera?: string,
|
||||||
|
camera_speed?: number,
|
||||||
|
skybox?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EnqueueEngineCompositingResponse {
|
||||||
|
success: boolean,
|
||||||
|
inference_job_token?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EnqueueEngineCompositing = MakeRequest<string, EnqueueEngineCompositingRequest, EnqueueEngineCompositingResponse,{}>({
|
||||||
|
method: "POST",
|
||||||
|
routingFunction: () => `/v1/conversion/enqueue_render_engine_scene`,
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
type UrlRoutingFunction<UrlRouteArgs> = (urlRouteArgs: UrlRouteArgs) => string;
|
||||||
|
|
||||||
|
interface RequestHeaders {
|
||||||
|
[name: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RouteSetup<UrlRouteArgs> {
|
||||||
|
method: string;
|
||||||
|
multipart?: boolean;
|
||||||
|
routingFunction: UrlRoutingFunction<UrlRouteArgs>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const METHOD_OMITS_BODY: { [key: string]: boolean } = {
|
||||||
|
DELETE: false,
|
||||||
|
GET: true,
|
||||||
|
OPTIONS: true,
|
||||||
|
PATCH: false,
|
||||||
|
POST: false,
|
||||||
|
PUT: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const MakeRequest = <UrlRouteArgs, Request, Response, UrlParams>(routeSetup: RouteSetup<UrlRouteArgs>) : (urlRouteArgs: UrlRouteArgs, request: Request, queries?: UrlParams) => Promise<Response> => {
|
||||||
|
return async function(urlRouteArgs: UrlRouteArgs, request: Request, queries?: any) : Promise<Response> {
|
||||||
|
const newQueries = queries ? Object.keys(queries).map((key, i) => {
|
||||||
|
return `${ i ? "&" : "" }${ key }=${ Array.isArray(queries[key]) ? queries[key].join(`&${ key }=`) : queries[key] }`
|
||||||
|
}).join("") : null;
|
||||||
|
|
||||||
|
const endpoint = `${ routeSetup.routingFunction(urlRouteArgs) }${ newQueries ? "?" + newQueries : "" }`;
|
||||||
|
const method = routeSetup.method;
|
||||||
|
const methodOmitsBody = METHOD_OMITS_BODY[method] || false;
|
||||||
|
|
||||||
|
console.log("🛼",request)
|
||||||
|
|
||||||
|
return fetch(`https://api.fakeyou.com${ endpoint }`, {
|
||||||
|
method,
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
...methodOmitsBody? {} : { "Content-Type": "application/json" }
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
...methodOmitsBody ? {} : { body: JSON.stringify(request) },
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
if (!res.success && res && (res.voice_token || res.dataset_token)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (res && "success" in res) {
|
||||||
|
return res;
|
||||||
|
} else Promise.reject();
|
||||||
|
})
|
||||||
|
.catch(e => ({ success : false }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MakeRequest;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
.studio-bubble-select {
|
||||||
|
// background: red;
|
||||||
|
display: flex;
|
||||||
|
list-style: none;
|
||||||
|
margin-block-start: 0px;
|
||||||
|
margin-block-end: 0px;
|
||||||
|
padding-inline-start: 0px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border: 2px solid darken(purple, 3%);
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
background-color: darken(purple, 3%);
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(#fff, 0.75);
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.selected-bubble {
|
||||||
|
color: #fff;
|
||||||
|
border-color: red;
|
||||||
|
background-color: lighten(purple, 6%);
|
||||||
|
|
||||||
|
&.fill {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import styles from "./bubble-select.element.scss?inline";
|
||||||
|
|
||||||
|
// const abc = "word";
|
||||||
|
|
||||||
|
@customElement("sts-bubble-select")
|
||||||
|
export class BubbleSelect extends LitElement {
|
||||||
|
static override styles = unsafeCSS(styles);
|
||||||
|
@property() name = "";
|
||||||
|
@property() onChange = (e: any) => {};
|
||||||
|
@property() options = [];
|
||||||
|
@property() value = "";
|
||||||
|
|
||||||
|
protected override render = () => html`
|
||||||
|
<ul class="studio-bubble-select">
|
||||||
|
${ this.options.map(({ label, value: itemValue },i) =>
|
||||||
|
html`<li
|
||||||
|
class=${ itemValue === this.value ? "selected-bubble" : "" }
|
||||||
|
@click=${ ({ target }: any) => {
|
||||||
|
this.onChange({ target: { name: this.name, value: itemValue } });
|
||||||
|
} }
|
||||||
|
>${ label }</li>`
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
.inspector-input-set {
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import { LitElement, html, nothing, unsafeCSS } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
import styles from "./style-tab.scss?inline";
|
||||||
|
import { EnqueueEngineCompositing } from "../api/EnqueueEngineCompositing";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
import { drag, on, provide } from "@storyteller/framework";
|
||||||
|
|
||||||
|
@customElement("sts-style-tab")
|
||||||
|
export class StyleTab extends LitElement {
|
||||||
|
static override styles = unsafeCSS(styles);
|
||||||
|
@state() vstStyle = "anime_2d_flat";
|
||||||
|
@state() posPrompt = "";
|
||||||
|
@state() negPrompt = "";
|
||||||
|
@property() sceneToken = "";
|
||||||
|
|
||||||
|
styleOptions = [
|
||||||
|
{
|
||||||
|
label: "2D Anime",
|
||||||
|
imageUrl: "/images/landing/onboarding/styles/style-2d-anime.webp",
|
||||||
|
value: "anime_2d_flat",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "3D Cartoon",
|
||||||
|
imageUrl: "/images/landing/onboarding/styles/style-3d-cartoon.webp",
|
||||||
|
value: "cartoon_3d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Ink B&W",
|
||||||
|
imageUrl: "/images/landing/onboarding/styles/style-ink-bw.webp",
|
||||||
|
value: "ink_bw_style",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Origami",
|
||||||
|
imageUrl: "/images/landing/onboarding/styles/style-origami.webp",
|
||||||
|
value: "paper_origami",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
inputChange = ({ target }: { target: { name: string, value: any } }) => {
|
||||||
|
// console.log("💁🏼♀️", this[target.name]);
|
||||||
|
// this[target.name] = target.value; // fix later
|
||||||
|
}
|
||||||
|
|
||||||
|
@on("scene-state")
|
||||||
|
oAThing(): void { console.log("🍕")};
|
||||||
|
|
||||||
|
compositorEnqueue = (sceneToken: string) => () => {
|
||||||
|
console.log("🏎️",this.sceneToken,sceneToken);
|
||||||
|
EnqueueEngineCompositing("",{
|
||||||
|
uuid_idempotency_token: uuid(),
|
||||||
|
media_file_token: sceneToken,
|
||||||
|
camera: "zoom",
|
||||||
|
camera_speed: 0.2,
|
||||||
|
skybox: "meadow_4k",
|
||||||
|
}).then((res: any) => {
|
||||||
|
if (res && res.success) {
|
||||||
|
console.log("💎",res.inference_job_token);
|
||||||
|
|
||||||
|
window.parent.postMessage(
|
||||||
|
`studio-scene-composited:compositeJobToken:${ res.inference_job_token }`,
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
// compositeJobTokenSet(res.inference_job_token)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
thingy = ({ target }: any ) => {
|
||||||
|
console.log("🏎️", this.sceneToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override render = () => html`<section class="inspector-input-set">
|
||||||
|
${ this.vstStyle }
|
||||||
|
<button @click=${ this.thingy }>State</button>
|
||||||
|
<sts-bubble-select
|
||||||
|
.onChange=${ ({ target }: any) => { this.vstStyle = target.value; } }
|
||||||
|
.options=${this.styleOptions}
|
||||||
|
.value=${this.vstStyle}
|
||||||
|
></sts-bubble-select>
|
||||||
|
<label htmlFor="inspector-posPrompt">Positive Prompt</label>
|
||||||
|
<textarea
|
||||||
|
id="inspector-posPrompt"
|
||||||
|
name="posPrompt"
|
||||||
|
@input=${ this.inputChange }
|
||||||
|
.value=${ this.posPrompt }
|
||||||
|
></textarea>
|
||||||
|
<label htmlFor="inspector-posPrompt">Negative Prompt</label>
|
||||||
|
<textarea
|
||||||
|
id="inspector-negPrompt"
|
||||||
|
name="negPrompt"
|
||||||
|
@input=${ this.inputChange }
|
||||||
|
.value=${ this.negPrompt }
|
||||||
|
></textarea>
|
||||||
|
<sts-button
|
||||||
|
@click=${this.compositorEnqueue(this.sceneToken)}
|
||||||
|
>
|
||||||
|
Generate your movie
|
||||||
|
</sts-button>
|
||||||
|
</section>`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
.studio-inspector {
|
||||||
|
color: #fff;
|
||||||
|
background: blue;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
import "@storyteller/studio-ui/tree";
|
||||||
|
import "./tabs.element";
|
||||||
|
import "./bubble-select.element";
|
||||||
|
import "./inspector-tabs/style-tab";
|
||||||
|
import styles from "./inspector.element.scss?inline";
|
||||||
|
import "@storyteller/studio-ui/button";
|
||||||
|
|
||||||
|
// const abc = "word";
|
||||||
|
|
||||||
|
enum InspectorMode {
|
||||||
|
Properties,
|
||||||
|
Style
|
||||||
|
}
|
||||||
|
|
||||||
|
@customElement("sts-inspector")
|
||||||
|
export class Inspector extends LitElement {
|
||||||
|
static override styles = unsafeCSS(styles);
|
||||||
|
@state() selectedTab = InspectorMode.Style;
|
||||||
|
@property() sceneToken = "";
|
||||||
|
@property() styleMediaToken = "";
|
||||||
|
|
||||||
|
tabs = [{
|
||||||
|
label: "Properties",
|
||||||
|
value: InspectorMode.Properties
|
||||||
|
},{
|
||||||
|
label: "Style",
|
||||||
|
value: InspectorMode.Style
|
||||||
|
}];
|
||||||
|
|
||||||
|
thingy = ({ target }: any) => {
|
||||||
|
console.log("🏎️", this.styleMediaToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
propertiesTab = html`<div>Properties</div>`;
|
||||||
|
|
||||||
|
tabContent = () => {
|
||||||
|
switch (this.selectedTab) {
|
||||||
|
case InspectorMode.Properties: return this.propertiesTab;
|
||||||
|
case InspectorMode.Style: return html`<sts-style-tab .sceneToken=${this.sceneToken}></sts-style-tab>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override render = () => html`
|
||||||
|
<div class="studio-inspector">
|
||||||
|
<button @click=${ this.thingy }>State</button>
|
||||||
|
<sts-tabs
|
||||||
|
.onChange=${ ({ target }: any) => {
|
||||||
|
this.selectedTab = target.value;
|
||||||
|
} }
|
||||||
|
.tabs=${this.tabs}
|
||||||
|
.value=${this.selectedTab}
|
||||||
|
></sts-tabs>
|
||||||
|
<div>
|
||||||
|
${ this.tabContent() }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
.studio-tabs {
|
||||||
|
// background: red;
|
||||||
|
display: flex;
|
||||||
|
list-style: none;
|
||||||
|
margin-block-start: 0px;
|
||||||
|
margin-block-end: 0px;
|
||||||
|
padding-inline-start: 0px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
border: none;
|
||||||
|
padding: 1rem 1.4rem;
|
||||||
|
border-bottom: 4px solid transparent;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.selected-tab {
|
||||||
|
border-bottom: 4px solid #e66462;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
|
import styles from "./tabs.element.scss?inline";
|
||||||
|
|
||||||
|
@customElement("sts-tabs")
|
||||||
|
export class Tabs extends LitElement {
|
||||||
|
static override styles = unsafeCSS(styles);
|
||||||
|
@property() name = "";
|
||||||
|
@property() onChange = (e: any) => {};
|
||||||
|
@property() tabs = [];
|
||||||
|
@property() value = "";
|
||||||
|
|
||||||
|
protected override render = () => html`
|
||||||
|
<ul class="studio-tabs">
|
||||||
|
${ this.tabs.map(({ label, value: itemValue },i) =>
|
||||||
|
html`<li
|
||||||
|
class=${ itemValue === this.value ? "selected-tab" : "" }
|
||||||
|
@click=${ ({ target }: any) => {
|
||||||
|
this.onChange({ target: { name: this.name, value: itemValue } });
|
||||||
|
} }
|
||||||
|
>${ label }</li>`
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { LitElement, type PropertyValues, html, nothing, unsafeCSS } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
|
// import styles from "./button.element.scss?inline";
|
||||||
|
|
||||||
|
// const abc = "word";
|
||||||
|
|
||||||
|
@customElement("sts-tabs")
|
||||||
|
export class Tabs extends LitElement {
|
||||||
|
@property() tabs = ["hello world"];
|
||||||
|
|
||||||
|
protected override render = () => html`
|
||||||
|
<div>
|
||||||
|
${ this.tabs.map((item,i) => item) }
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user