mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-09 00:09:55 +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