Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3e21ac98e | ||
|
|
9aaa894a2b | ||
|
|
685e225d85 | ||
|
|
dfd130c595 | ||
|
|
d81449fc12 | ||
|
|
a538f7d379 | ||
|
|
c1f0138fc7 | ||
|
|
bdb9a99c90 | ||
|
|
f8396e9a1b | ||
|
|
08b16d4efb | ||
|
|
c1ba8164fc | ||
|
|
587cac06af | ||
|
|
0659bfb2e7 |
@@ -1,6 +1,6 @@
|
|||||||
import platform
|
import platform
|
||||||
import blender_node
|
import blender_node
|
||||||
from mesh_utils import assign_texture, open_in_blender as open_blender, export_gltf
|
from mesh_utils import upload_avatar_file, open_in_blender as open_blender, export_gltf
|
||||||
import folder_paths
|
import folder_paths
|
||||||
|
|
||||||
global_blender_path = ''
|
global_blender_path = ''
|
||||||
@@ -47,14 +47,16 @@ class AvatarMainOutput(blender_node.ObjectOps):
|
|||||||
}),
|
}),
|
||||||
"model_type": (["AVA","GLB", "GLTF_EMBEDDED"],),
|
"model_type": (["AVA","GLB", "GLTF_EMBEDDED"],),
|
||||||
"write_mode": (["Overwrite", "Increment"],),
|
"write_mode": (["Overwrite", "Increment"],),
|
||||||
|
"upload_to_cloud": ("BOOLEAN", {
|
||||||
|
"default": False
|
||||||
|
}),
|
||||||
"SHAPE_FLOW": ("SHAPE_FLOW",),
|
"SHAPE_FLOW": ("SHAPE_FLOW",),
|
||||||
}
|
}
|
||||||
|
|
||||||
OUTPUT_NODE = True
|
OUTPUT_NODE = True
|
||||||
RETURN_TYPES = ()
|
RETURN_TYPES = ()
|
||||||
|
|
||||||
def blender_process(self, bpy, BPY_OBJ=None, BPY_OBJS=None, open_in_blender=False, auto_save=False, blender_path_override='', filename='', model_type='', write_mode='', SHAPE_FLOW=''):
|
def blender_process(self, bpy, BPY_OBJ=None, BPY_OBJS=None, open_in_blender=False, auto_save=False, blender_path_override='', filename='', model_type='', write_mode='', upload_to_cloud=False, SHAPE_FLOW=''):
|
||||||
if open_in_blender:
|
if open_in_blender:
|
||||||
p = blender_path_override if blender_path_override else global_blender_path
|
p = blender_path_override if blender_path_override else global_blender_path
|
||||||
output_file = self.output_dir + '/tmp.blend'
|
output_file = self.output_dir + '/tmp.blend'
|
||||||
@@ -72,4 +74,23 @@ class AvatarMainOutput(blender_node.ObjectOps):
|
|||||||
import global_bpy
|
import global_bpy
|
||||||
global_bpy.set_should_reset_scene(True)
|
global_bpy.set_should_reset_scene(True)
|
||||||
|
|
||||||
return {"ui": {"gltfFilename": {filepath.replace(f"{self.output_dir}/", "")}, "SHAPE_FLOW": {SHAPE_FLOW}, "auto_save": {'true' if auto_save else 'false'},}}
|
outputs = {
|
||||||
|
"gltfFilename": [filepath.replace(f"{self.output_dir}/", "")],
|
||||||
|
"files": [{
|
||||||
|
"filename": filepath.replace(f"{self.output_dir}/", ""),
|
||||||
|
"content_type": "model/gltf+json",
|
||||||
|
},],
|
||||||
|
"SHAPE_FLOW": {SHAPE_FLOW},
|
||||||
|
"auto_save": {'true' if auto_save else 'false'},
|
||||||
|
}
|
||||||
|
if upload_to_cloud:
|
||||||
|
avatarId = upload_avatar_file(outputs)
|
||||||
|
return {
|
||||||
|
"ui": {
|
||||||
|
**outputs,
|
||||||
|
"avatarId": [avatarId],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"ui": outputs
|
||||||
|
}
|
||||||
|
|||||||
@@ -260,7 +260,8 @@ def create_primitive_shape_class(cls, path, name=None, name_prefix=''):
|
|||||||
|
|
||||||
|
|
||||||
def assign_and_return(BPY_OBJ, name, value):
|
def assign_and_return(BPY_OBJ, name, value):
|
||||||
BPY_OBJ[name] = value
|
setattr(BPY_OBJ, name, value)
|
||||||
|
# BPY_OBJ[name] = value
|
||||||
# print(BPY_OBJ,name, BPY_OBJ[name])
|
# print(BPY_OBJ,name, BPY_OBJ[name])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import atexit
|
import atexit
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
import folder_paths
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
def genreate_mesh_from_texture(bpy, image):
|
def genreate_mesh_from_texture(bpy, image):
|
||||||
import torch
|
import torch
|
||||||
@@ -246,3 +249,38 @@ def export_gltf(output_dir, bpy_objects, filename, model_type, write_mode, metad
|
|||||||
filepath = new_filepath
|
filepath = new_filepath
|
||||||
|
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
def get_avatar_file(output):
|
||||||
|
avatar_filename = output["gltfFilename"][0]
|
||||||
|
with open(
|
||||||
|
f"{folder_paths.get_output_directory()}/{avatar_filename}", "rb"
|
||||||
|
) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def upload_avatar_file(output):
|
||||||
|
file = get_avatar_file(output)
|
||||||
|
response = requests.get("https://labs.avatech.ai/api/share")
|
||||||
|
labData = response.json()
|
||||||
|
modelId = labData["modelId"]
|
||||||
|
|
||||||
|
# upload model
|
||||||
|
headers = {
|
||||||
|
"x-amz-acl": "public-read",
|
||||||
|
"Content-Type": "model/gltf-binary",
|
||||||
|
"Content-Length": str(len(file)),
|
||||||
|
}
|
||||||
|
requests.put(labData["url"], headers=headers, data=file)
|
||||||
|
|
||||||
|
# send notification
|
||||||
|
webhook_url = os.getenv("DISCORD_WEBHOOK_URL")
|
||||||
|
data = {
|
||||||
|
"username": "Avabot",
|
||||||
|
"avatar_url": "https://avatech-avatar-dev1.nyc3.cdn.digitaloceanspaces.com/avatechai.png",
|
||||||
|
"content": "[API Call] New register!",
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
response = requests.post(webhook_url, headers=headers, data=json.dumps(data))
|
||||||
|
|
||||||
|
return modelId
|
||||||
|
|||||||
+2
-45
@@ -173,10 +173,6 @@ async function prepareImageFromUrlRedirect(stage) {
|
|||||||
|
|
||||||
export function AvatarPreview() {
|
export function AvatarPreview() {
|
||||||
console.log("getting workflow json now");
|
console.log("getting workflow json now");
|
||||||
loadJSONWorkflow("default").then(() => {
|
|
||||||
console.log("done loading");
|
|
||||||
jsonWorkflowLoading.val = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
const loading = van.state(false);
|
const loading = van.state(false);
|
||||||
const shareLoading = van.state("share"); // share, loading, shared
|
const shareLoading = van.state("share"); // share, loading, shared
|
||||||
@@ -465,7 +461,7 @@ export function AvatarPreview() {
|
|||||||
name: "avatech-viewer-iframe",
|
name: "avatech-viewer-iframe",
|
||||||
allow: "cross-origin-isolated",
|
allow: "cross-origin-isolated",
|
||||||
class: () =>
|
class: () =>
|
||||||
"w-full h-full min-w-[400px] min-h-[400px] z-[100] pointer-events-auto flex border-none overflow-hidden" +
|
"w-full h-full min-w-[350px] min-h-[350px] z-[100] pointer-events-auto flex border-none overflow-hidden bg-transparent" +
|
||||||
(showPreview.val ? "" : "hidden"),
|
(showPreview.val ? "" : "hidden"),
|
||||||
// src: "https://labs.avatech.ai/viewer/default",
|
// src: "https://labs.avatech.ai/viewer/default",
|
||||||
// src: "http://localhost:3000/viewer/default",
|
// src: "http://localhost:3000/viewer/default",
|
||||||
@@ -711,50 +707,11 @@ export function AvatarPreview() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
(showPreview.val ? "" : "hidden ") +
|
(showPreview.val ? "" : "hidden ") +
|
||||||
"w-full h-full absolute left-0 top-0 z-[99] pointer-events-auto flex border-none bg-white"
|
"absolute w-[360px] h-[360px] rounded-xl overflow-hidden right-0 top-0 z-[99] pointer-events-auto flex border-none bg-transparent"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
div(
|
|
||||||
{ class: "overflow-y-auto overflow-x-hidden w-full h-full" },
|
|
||||||
div(
|
|
||||||
{
|
|
||||||
class: "absolute top-4 left-4 flex flex-row gap-2",
|
|
||||||
},
|
|
||||||
renderCloseButton(),
|
|
||||||
renderRestartButton(),
|
|
||||||
renderChangeWorkflowButton()
|
|
||||||
),
|
|
||||||
renderTwitter(),
|
|
||||||
() => {
|
|
||||||
if (isMobileDevice()) {
|
|
||||||
return div(
|
|
||||||
{
|
|
||||||
class: () =>
|
|
||||||
"flex flex-col w-full h-fit bg-white justify-center items-center py-16 px-4 gap-2" +
|
|
||||||
(showPreview.val ? "" : "hidden"),
|
|
||||||
},
|
|
||||||
renderIFrame(),
|
renderIFrame(),
|
||||||
renderSteps(),
|
|
||||||
renderShareLink()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return div(
|
|
||||||
{
|
|
||||||
class: () =>
|
|
||||||
"flex w-full h-full bg-white justify-around items-center p-24" +
|
|
||||||
(showPreview.val ? "" : "hidden"),
|
|
||||||
},
|
|
||||||
renderSteps(),
|
|
||||||
div(
|
|
||||||
{ class: () => "flex flex-col" },
|
|
||||||
renderIFrame(),
|
|
||||||
renderShareLink()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ export const showEditor = van.state(false);
|
|||||||
// localStorage.getItem("showPreview") == 'true'
|
// localStorage.getItem("showPreview") == 'true'
|
||||||
export const showPreview = van.state(true);
|
export const showPreview = van.state(true);
|
||||||
export const previewUrl = van.state(
|
export const previewUrl = van.state(
|
||||||
"https://editor.avatech.ai/viewer?avatarId=default&debug=false&width=400&height=400&hideTrigger=true&voiceSelection=true&hideUI=true"
|
"https://editor.avatech.ai/viewer?avatarId=default&debug=true&width=350&height=350&hideTrigger=true&voiceSelection=true&hideUI=true"
|
||||||
);
|
);
|
||||||
export const previewImg = van.state("");
|
export const previewImg = van.state("");
|
||||||
export const previewImgLoading = van.state(false);
|
export const previewImgLoading = van.state(false);
|
||||||
|
|||||||
+123
-57
@@ -1,7 +1,7 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Gabarito&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Gabarito&display=swap');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
|
! tailwindcss v3.4.0 | MIT License | https://tailwindcss.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -34,9 +34,11 @@
|
|||||||
4. Use the user's configured `sans` font-family by default.
|
4. Use the user's configured `sans` font-family by default.
|
||||||
5. Use the user's configured `sans` font-feature-settings by default.
|
5. Use the user's configured `sans` font-feature-settings by default.
|
||||||
6. Use the user's configured `sans` font-variation-settings by default.
|
6. Use the user's configured `sans` font-variation-settings by default.
|
||||||
|
7. Disable tap highlights on iOS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
html {
|
html,
|
||||||
|
:host {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
/* 1 */
|
/* 1 */
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
@@ -46,12 +48,14 @@ html {
|
|||||||
-o-tab-size: 4;
|
-o-tab-size: 4;
|
||||||
tab-size: 4;
|
tab-size: 4;
|
||||||
/* 3 */
|
/* 3 */
|
||||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
/* 4 */
|
/* 4 */
|
||||||
font-feature-settings: normal;
|
font-feature-settings: normal;
|
||||||
/* 5 */
|
/* 5 */
|
||||||
font-variation-settings: normal;
|
font-variation-settings: normal;
|
||||||
/* 6 */
|
/* 6 */
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
/* 7 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -123,8 +127,10 @@ strong {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
1. Use the user's configured `mono` font family by default.
|
1. Use the user's configured `mono` font-family by default.
|
||||||
2. Correct the odd `em` font sizing in all browsers.
|
2. Use the user's configured `mono` font-feature-settings by default.
|
||||||
|
3. Use the user's configured `mono` font-variation-settings by default.
|
||||||
|
4. Correct the odd `em` font sizing in all browsers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
code,
|
code,
|
||||||
@@ -133,8 +139,12 @@ samp,
|
|||||||
pre {
|
pre {
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
/* 1 */
|
/* 1 */
|
||||||
font-size: 1em;
|
font-feature-settings: normal;
|
||||||
/* 2 */
|
/* 2 */
|
||||||
|
font-variation-settings: normal;
|
||||||
|
/* 3 */
|
||||||
|
font-size: 1em;
|
||||||
|
/* 4 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -501,7 +511,7 @@ html{
|
|||||||
:root{
|
:root{
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
--in: 0.7206 0.191 231.6;
|
--in: 0.7206 0.191 231.6;
|
||||||
--su: 0.7441 0.213 164.75;
|
--su: 64.8% 0.150 160;
|
||||||
--wa: 0.8471 0.199 83.87;
|
--wa: 0.8471 0.199 83.87;
|
||||||
--er: 0.7176 0.221 22.18;
|
--er: 0.7176 0.221 22.18;
|
||||||
--pc: 0.89824 0.06192 275.75;
|
--pc: 0.89824 0.06192 275.75;
|
||||||
@@ -742,7 +752,7 @@ html{
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: var(--rounded-btn, 0.5rem);
|
border-radius: var(--rounded-btn, 0.5rem);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1));
|
border-color: oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity));
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -762,7 +772,9 @@ html{
|
|||||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
outline-color: var(--fallback-bc,oklch(var(--bc)/1));
|
outline-color: var(--fallback-bc,oklch(var(--bc)/1));
|
||||||
background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1));
|
background-color: oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity));
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
--tw-border-opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-disabled,
|
.btn-disabled,
|
||||||
@@ -870,8 +882,7 @@ html{
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
--tw-content: '';
|
--tw-content: '';
|
||||||
content: var(--tw-content);
|
content: var(--tw-content);
|
||||||
--tw-bg-opacity: 1;
|
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
||||||
background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown{
|
.dropdown{
|
||||||
@@ -959,18 +970,23 @@ html{
|
|||||||
.btn:hover{
|
.btn:hover{
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));
|
border-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-border-opacity)));
|
||||||
border-color: color-mix(
|
|
||||||
in oklab,
|
|
||||||
oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%,
|
|
||||||
black
|
|
||||||
);
|
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));
|
background-color: var(--fallback-b3,oklch(var(--b3)/var(--tw-bg-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (color: color-mix(in oklab, black, black)){
|
||||||
|
.btn:hover{
|
||||||
background-color: color-mix(
|
background-color: color-mix(
|
||||||
in oklab,
|
in oklab,
|
||||||
oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%,
|
oklch(var(--btn-color, var(--b2)) / var(--tw-bg-opacity, 1)) 90%,
|
||||||
black
|
black
|
||||||
);
|
);
|
||||||
|
border-color: color-mix(
|
||||||
|
in oklab,
|
||||||
|
oklch(var(--btn-color, var(--b2)) / var(--tw-border-opacity, 1)) 90%,
|
||||||
|
black
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports not (color: oklch(0 0 0)){
|
@supports not (color: oklch(0 0 0)){
|
||||||
@@ -1005,10 +1021,12 @@ html{
|
|||||||
--tw-text-opacity: 0.2;
|
--tw-text-opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@supports (color: color-mix(in oklab, black, black)){
|
||||||
.btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover{
|
.btn:is(input[type="checkbox"]:checked):hover, .btn:is(input[type="radio"]:checked):hover{
|
||||||
background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
|
background-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
|
||||||
border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
|
border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown.dropdown-hover:hover .dropdown-content{
|
.dropdown.dropdown-hover:hover .dropdown-content{
|
||||||
--tw-scale-x: 1;
|
--tw-scale-x: 1;
|
||||||
@@ -1018,8 +1036,6 @@ html{
|
|||||||
|
|
||||||
:where(.menu li:not(.menu-title):not(.disabled) > *:not(ul):not(details):not(.menu-title)):not(.active):hover, :where(.menu li:not(.menu-title):not(.disabled) > details > summary:not(.menu-title)):not(.active):hover{
|
:where(.menu li:not(.menu-title):not(.disabled) > *:not(ul):not(details):not(.menu-title)):not(.active):hover, :where(.menu li:not(.menu-title):not(.disabled) > details > summary:not(.menu-title)):not(.active):hover{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
|
|
||||||
outline: 2px solid transparent;
|
outline: 2px solid transparent;
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
@@ -1050,6 +1066,9 @@ html{
|
|||||||
|
|
||||||
.input{
|
.input{
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
@@ -1152,9 +1171,7 @@ html{
|
|||||||
.menu :where(li ul){
|
.menu :where(li ul){
|
||||||
position: relative;
|
position: relative;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
-webkit-margin-start: 1rem;
|
|
||||||
margin-inline-start: 1rem;
|
margin-inline-start: 1rem;
|
||||||
-webkit-padding-start: 0.5rem;
|
|
||||||
padding-inline-start: 0.5rem;
|
padding-inline-start: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1485,7 +1502,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
:where(.collapse > input[type="radio"]){
|
:where(.collapse > input[type="radio"]){
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
-webkit-padding-end: 3rem;
|
|
||||||
padding-inline-end: 3rem;
|
padding-inline-end: 3rem;
|
||||||
min-height: 3.75rem;
|
min-height: 3.75rem;
|
||||||
transition: background-color 0.2s ease-out;
|
transition: background-color 0.2s ease-out;
|
||||||
@@ -1577,10 +1593,13 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
--tw-placeholder-opacity: 0.2;
|
--tw-placeholder-opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input::-webkit-date-and-time-value{
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.join > :where(*:not(:first-child)){
|
.join > :where(*:not(:first-child)){
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
-webkit-margin-start: -1px;
|
|
||||||
margin-inline-start: -1px;
|
margin-inline-start: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1624,7 +1643,9 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
}
|
}
|
||||||
|
|
||||||
:where(.menu li:empty){
|
:where(.menu li:empty){
|
||||||
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
|
||||||
|
opacity: 0.1;
|
||||||
margin: 0.5rem 1rem;
|
margin: 0.5rem 1rem;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
}
|
}
|
||||||
@@ -1635,7 +1656,9 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
inset-inline-start: 0px;
|
inset-inline-start: 0px;
|
||||||
top: 0.75rem;
|
top: 0.75rem;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
|
||||||
|
opacity: 0.1;
|
||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1760,7 +1783,7 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
|
|
||||||
.modal:not(dialog:not(.modal-open)),
|
.modal:not(dialog:not(.modal-open)),
|
||||||
.modal::backdrop{
|
.modal::backdrop{
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
background-color: #0006;
|
||||||
animation: modal-pop 0.2s ease-out;
|
animation: modal-pop 0.2s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2083,7 +2106,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
.join.join-horizontal > :where(*:not(:first-child)){
|
.join.join-horizontal > :where(*:not(:first-child)){
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
-webkit-margin-start: -1px;
|
|
||||||
margin-inline-start: -1px;
|
margin-inline-start: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2174,10 +2196,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-28{
|
|
||||||
left: 7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-4{
|
.left-4{
|
||||||
left: 1rem;
|
left: 1rem;
|
||||||
}
|
}
|
||||||
@@ -2268,10 +2286,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-4{
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mt-8{
|
.mt-8{
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
@@ -2304,19 +2318,43 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
height: 394px;
|
height: 394px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-full{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.h-fit{
|
.h-fit{
|
||||||
height: -moz-fit-content;
|
height: -moz-fit-content;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-full{
|
.h-\[400px\]{
|
||||||
height: 100%;
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-\[420px\]{
|
||||||
|
height: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-\[410px\]{
|
||||||
|
height: 410px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-\[360px\]{
|
||||||
|
height: 360px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.min-h-\[400px\]{
|
.min-h-\[400px\]{
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.min-h-\[380px\]{
|
||||||
|
min-height: 380px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-h-\[350px\]{
|
||||||
|
min-height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
.w-20{
|
.w-20{
|
||||||
width: 5rem;
|
width: 5rem;
|
||||||
}
|
}
|
||||||
@@ -2350,10 +2388,42 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-\[\]{
|
||||||
|
width: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[400px\]{
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[420px\]{
|
||||||
|
width: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[410px\]{
|
||||||
|
width: 410px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-\[360px\]{
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
.min-w-\[400px\]{
|
.min-w-\[400px\]{
|
||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.min-w-\[380\]{
|
||||||
|
min-width: 380;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-w-\[380px\]{
|
||||||
|
min-width: 380px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-w-\[350px\]{
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
.max-w-\[100\%\]{
|
.max-w-\[100\%\]{
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@@ -2404,10 +2474,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.justify-around{
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-2{
|
.gap-2{
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
@@ -2424,14 +2490,6 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflow-y-auto{
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overflow-x-hidden{
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rounded{
|
.rounded{
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
@@ -2456,6 +2514,14 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rounded-2xl{
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-xl{
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded-b-md{
|
.rounded-b-md{
|
||||||
border-bottom-right-radius: 0.375rem;
|
border-bottom-right-radius: 0.375rem;
|
||||||
border-bottom-left-radius: 0.375rem;
|
border-bottom-left-radius: 0.375rem;
|
||||||
@@ -2669,14 +2735,14 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-24{
|
|
||||||
padding: 6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-4{
|
.p-4{
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-24{
|
||||||
|
padding: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
.\!px-0{
|
.\!px-0{
|
||||||
padding-left: 0px !important;
|
padding-left: 0px !important;
|
||||||
padding-right: 0px !important;
|
padding-right: 0px !important;
|
||||||
@@ -2692,16 +2758,16 @@ details.collapse summary::-webkit-details-marker{
|
|||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.py-16{
|
|
||||||
padding-top: 4rem;
|
|
||||||
padding-bottom: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.py-2{
|
.py-2{
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
padding-bottom: 0.5rem;
|
padding-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.py-16{
|
||||||
|
padding-top: 4rem;
|
||||||
|
padding-bottom: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-start{
|
.text-start{
|
||||||
text-align: start;
|
text-align: start;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ numpy
|
|||||||
opencv-python
|
opencv-python
|
||||||
opencv-contrib-python
|
opencv-contrib-python
|
||||||
einops
|
einops
|
||||||
bpy
|
bpy==3.6.0
|
||||||
segment-anything
|
segment-anything
|
||||||
tqdm
|
tqdm
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from aiohttp import web
|
|||||||
from segment_anything import sam_model_registry, SamPredictor
|
from segment_anything import sam_model_registry, SamPredictor
|
||||||
from PIL import Image, ImageOps
|
from PIL import Image, ImageOps
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
from blender.mesh_utils import upload_avatar_file
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
import folder_paths
|
import folder_paths
|
||||||
@@ -125,7 +126,7 @@ async def post_sam_model(request):
|
|||||||
}
|
}
|
||||||
json.dump(data, f)
|
json.dump(data, f)
|
||||||
else:
|
else:
|
||||||
sam = sam_model_registry[model_type](checkpoint=ckpt).to("cuda")
|
sam = sam_model_registry[model_type](checkpoint=ckpt)
|
||||||
predictor = SamPredictor(sam)
|
predictor = SamPredictor(sam)
|
||||||
|
|
||||||
image_np = (image * 255).astype(np.uint8)
|
image_np = (image * 255).astype(np.uint8)
|
||||||
@@ -205,45 +206,6 @@ def post_prompt(json_data):
|
|||||||
return web.json_response({"error": "no prompt", "node_errors": []}, status=400)
|
return web.json_response({"error": "no prompt", "node_errors": []}, status=400)
|
||||||
|
|
||||||
|
|
||||||
def get_avatar_file(outputs):
|
|
||||||
for node_id, output in outputs.items():
|
|
||||||
if "gltfFilename" in output:
|
|
||||||
avatar_filename = output["gltfFilename"][0]
|
|
||||||
with open(
|
|
||||||
f"{folder_paths.get_output_directory()}/{avatar_filename}", "rb"
|
|
||||||
) as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
|
|
||||||
def upload_avatar_file(outputs):
|
|
||||||
file = get_avatar_file(outputs)
|
|
||||||
response = requests.get("https://labs.avatech.ai/api/share")
|
|
||||||
labData = response.json()
|
|
||||||
modelId = labData["modelId"]
|
|
||||||
|
|
||||||
# upload model
|
|
||||||
headers = {
|
|
||||||
"x-amz-acl": "public-read",
|
|
||||||
"Content-Type": "model/gltf-binary",
|
|
||||||
"Content-Length": str(len(file)),
|
|
||||||
}
|
|
||||||
requests.put(labData["url"], headers=headers, data=file)
|
|
||||||
|
|
||||||
# send notification
|
|
||||||
webhook_url = os.getenv("DISCORD_WEBHOOK_URL")
|
|
||||||
data = {
|
|
||||||
"username": "Avabot",
|
|
||||||
"avatar_url": "https://avatech-avatar-dev1.nyc3.cdn.digitaloceanspaces.com/avatechai.png",
|
|
||||||
"content": "[API Call] New register!",
|
|
||||||
}
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
}
|
|
||||||
response = requests.post(webhook_url, headers=headers, data=json.dumps(data))
|
|
||||||
|
|
||||||
return modelId
|
|
||||||
|
|
||||||
|
|
||||||
def randomSeed(num_digits=15):
|
def randomSeed(num_digits=15):
|
||||||
range_start = 10 ** (num_digits - 1)
|
range_start = 10 ** (num_digits - 1)
|
||||||
range_end = (10**num_digits) - 1
|
range_end = (10**num_digits) - 1
|
||||||
@@ -260,8 +222,6 @@ def load_workflow(workflow_name):
|
|||||||
return "\n".join(f.readlines())
|
return "\n".join(f.readlines())
|
||||||
|
|
||||||
|
|
||||||
default_workflow = load_workflow("avatar_generation_mask_api_v11(FaceToon)")
|
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.post("/avatar_generation")
|
@server.PromptServer.instance.routes.post("/avatar_generation")
|
||||||
async def post_prompt_block(request):
|
async def post_prompt_block(request):
|
||||||
@@ -273,8 +233,6 @@ async def post_prompt_block(request):
|
|||||||
workflow = uploaded_workflow
|
workflow = uploaded_workflow
|
||||||
elif workflow_name is not None:
|
elif workflow_name is not None:
|
||||||
workflow = load_workflow(workflow_name)
|
workflow = load_workflow(workflow_name)
|
||||||
else:
|
|
||||||
workflow = default_workflow
|
|
||||||
|
|
||||||
ref_image = post.get("ref_image")
|
ref_image = post.get("ref_image")
|
||||||
base_image = post.get("base_image")
|
base_image = post.get("base_image")
|
||||||
@@ -292,7 +250,7 @@ async def post_prompt_block(request):
|
|||||||
if key.startswith("mask_"):
|
if key.startswith("mask_"):
|
||||||
mask_name = image_name + "_" + key.replace("mask_", "") + image_ext
|
mask_name = image_name + "_" + key.replace("mask_", "") + image_ext
|
||||||
mask_path = save_image(value, save_name=mask_name)
|
mask_path = save_image(value, save_name=mask_name)
|
||||||
workflow = workflow.replace(key, mask_path)
|
workflow = workflow.replace(f'"{key}"', f'"{mask_path}"')
|
||||||
|
|
||||||
workflow = workflow.replace("embedding_id_avatech", image_path)
|
workflow = workflow.replace("embedding_id_avatech", image_path)
|
||||||
workflow = workflow.replace("SEED", str(randomSeed()))
|
workflow = workflow.replace("SEED", str(randomSeed()))
|
||||||
@@ -319,8 +277,10 @@ async def post_prompt_block(request):
|
|||||||
if history:
|
if history:
|
||||||
# file = get_avatar_file(history[prompt_id]["outputs"])
|
# file = get_avatar_file(history[prompt_id]["outputs"])
|
||||||
# return web.Response(body=file)
|
# return web.Response(body=file)
|
||||||
|
outputs = history[prompt_id]["outputs"]
|
||||||
modelId = upload_avatar_file(history[prompt_id]["outputs"])
|
for node_id, output in outputs.items():
|
||||||
|
if "gltfFilename" in output:
|
||||||
|
modelId = upload_avatar_file(output)
|
||||||
print("model id", modelId)
|
print("model id", modelId)
|
||||||
return web.json_response({"id": modelId}, status=200)
|
return web.json_response({"id": modelId}, status=200)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|||||||
Reference in New Issue
Block a user