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:
Victor O
2024-03-29 12:51:02 -07:00
committed by GitHub
parent 364460c774
commit 3dba6cb284
11 changed files with 377 additions and 0 deletions
@@ -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%;
}
+60
View File
@@ -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>
`
}
+24
View File
@@ -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;
}
}
}
+26
View File
@@ -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>
`
}
+17
View File
@@ -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>
`
}