mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 09:48:44 +00:00
Merge branch 'test' of github.com:storytold/GottaGoFast into test
This commit is contained in:
commit
eec0363b1f
7 files changed
+15
-424
No files matched your search
@@ -1,155 +0,0 @@
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
import { LipSync } from './lipsync.js';
|
||||
|
||||
class AnimatedItem {
|
||||
constructor(uuid) {
|
||||
this.name = uuid;
|
||||
this.anims = [];
|
||||
this.audiodrive = null;
|
||||
this.lipsync_comp = null;
|
||||
this.face = null;
|
||||
this.mixer = null;
|
||||
this.child = null;
|
||||
|
||||
this.auto_blink = true;
|
||||
this.currentAction;
|
||||
|
||||
this.blink_timer = 0.0;
|
||||
this.blink_every = 3.0;
|
||||
this.blink_position = 0.0;
|
||||
this.blink_speed = 8.0;
|
||||
this.blinking = false;
|
||||
this.st_blinking = false;
|
||||
this.blink_vrm = null;
|
||||
}
|
||||
|
||||
load(filepath, callback) {
|
||||
this.load_glb(filepath, callback);
|
||||
}
|
||||
|
||||
blink(delta) {
|
||||
if (this.blink_vrm == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.blink_timer += delta;
|
||||
if (this.blink_timer >= this.blink_every) {
|
||||
this.blinking = true;
|
||||
}
|
||||
|
||||
if (this.blinking) {
|
||||
if (this.blink_position < 1 && this.st_blinking == false) {
|
||||
this.blink_position += delta * this.blink_speed;
|
||||
} else if (this.blink_position > 0) {
|
||||
this.blink_position -= delta * this.blink_speed;
|
||||
this.st_blinking = true;
|
||||
} else {
|
||||
this.blink_position = 0.0;
|
||||
this.blink_timer = 0.0;
|
||||
this.blinking = false;
|
||||
this.st_blinking = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.blink_position > 1.1) {
|
||||
this.blink_position = 1.0;
|
||||
}
|
||||
if (this.blink_position < -0.1) {
|
||||
this.blink_position = 0.0;
|
||||
}
|
||||
|
||||
this.face.morphTargetInfluences[this.blink_vrm] = this.blink_position;
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
if (this.face != null && this.auto_blink) {
|
||||
this.blink(delta);
|
||||
if (this.mixer != null) {
|
||||
this.mixer.update(delta); // add speed here later.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3js clip
|
||||
animate(clip) {
|
||||
this.currentAction = this.mixer.clipAction(clip);
|
||||
this.currentAction.play();
|
||||
}
|
||||
|
||||
// talking and plays the audio
|
||||
// takes audio clip from folder on the server .wav
|
||||
sync_lips(filepath) {
|
||||
if(this.lipsync_comp != null){
|
||||
return fetch(filepath)
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error, status = ${response.status}`);
|
||||
}
|
||||
return response.arrayBuffer();
|
||||
}).then((arrayBuffer) => {
|
||||
this.lipsync_comp.startFromAudioFile(arrayBuffer);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a glb animation loads from the server
|
||||
load_animation(filepath, callback = null) {
|
||||
let glbLoader = new GLTFLoader();
|
||||
glbLoader.load(filepath,
|
||||
(object) => {
|
||||
let anim = object.animations[0];
|
||||
anim.name = this.name+'::'+anim.name;
|
||||
let animationAction = this.mixer.clipAction(anim);
|
||||
this.anims.push(animationAction);
|
||||
if (callback != null) {
|
||||
callback(this.name);
|
||||
}
|
||||
this.child.animations.push(anim);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// loads the mesh of the character
|
||||
load_glb(filepath, callback = null) {
|
||||
let glbLoader = new GLTFLoader();
|
||||
glbLoader.load(filepath, (glb) => {
|
||||
glb.scene.children.forEach(child => {
|
||||
child.traverse(c => {
|
||||
if (c.isMesh) {
|
||||
c.material.metalness = 0.0;
|
||||
c.material.specular = 0.0;
|
||||
c.castShadow = true;
|
||||
c.receiveShadow = true;
|
||||
c.frustrumCulled = false;
|
||||
c.material.transparent = false;
|
||||
if (c.morphTargetInfluences && c.morphTargetDictionary) {
|
||||
const blendShapeIndexI = c.morphTargetDictionary["E"];
|
||||
if (blendShapeIndexI != null && this.face == null) {
|
||||
this.face = c;
|
||||
this.lipsync_comp = new LipSync(this.face);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
child.frustrumCulled = false;
|
||||
child.userData.name = "CHAR::"+child.name; // Will be used for loading the character later.
|
||||
if(this.mixer == null) {
|
||||
this.mixer = new THREE.AnimationMixer(child);
|
||||
}
|
||||
if(this.face == null) {
|
||||
this.face = child;
|
||||
}
|
||||
this.child = child;
|
||||
});
|
||||
this.name = this.child.uuid;
|
||||
if (callback != null) {
|
||||
callback(this.name, glb.scene.children, this);
|
||||
}
|
||||
},
|
||||
(xhr) => {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default AnimatedItem;
|
||||
@@ -1,41 +0,0 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
class TransformObject {
|
||||
constructor(uuid) {
|
||||
this.name = "Transform";
|
||||
this.uuid = uuid;
|
||||
this.position = new THREE.Vector3(0, 0, 0);
|
||||
this.rotation = new THREE.Vector3(0, 0, 0);
|
||||
this.scale = new THREE.Vector3(1, 1, 1);
|
||||
}
|
||||
|
||||
get_json() {
|
||||
return { "name": this.name, "object": this.object, "position": this.position, "rotation": this.rotation, "scale": this.scale }
|
||||
}
|
||||
|
||||
get_html() {
|
||||
return `<div class="component">
|
||||
<a>`+ this.name + `</a>
|
||||
<hr>
|
||||
<span> Demo Position: `+ this.position.toArray() + `</span><br>
|
||||
<span> Demo Rotation: `+ this.rotation.toArray() + `</span><br>
|
||||
<span> Demo Scale: `+ this.scale.toArray() + `</span>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
class Animation {
|
||||
constructor(clip) {
|
||||
this.name = "Animation";
|
||||
this.clip = clip;
|
||||
}
|
||||
}
|
||||
|
||||
class Audio {
|
||||
constructor(audio_file) {
|
||||
this.name = "Audio Player";
|
||||
this.audio_file = audio_file;
|
||||
}
|
||||
}
|
||||
|
||||
export default TransformObject;
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as THREE from 'three';
|
||||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||||
import { TransformControls } from 'three/addons/controls/TransformControls.js';
|
||||
import Scene from './scene.js';
|
||||
import SaveManager from './serialization.js';
|
||||
import Scene from './scene.ts';
|
||||
import APIManager from './api_manager.ts';
|
||||
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
|
||||
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
|
||||
@@ -95,8 +94,6 @@ class Editor {
|
||||
this.playback = false;
|
||||
this.playback_location = 0;
|
||||
this.max_length = 10;
|
||||
// Save & Load.
|
||||
this.save_manager = new SaveManager(this.version);
|
||||
// Audio Engine Test.
|
||||
|
||||
this.audio_engine = new AudioEngine();
|
||||
@@ -311,7 +308,7 @@ class Editor {
|
||||
let delta_time = this.clock.getDelta()
|
||||
|
||||
// All calls that are not super important like timeline go here.
|
||||
this.activeScene.update(delta_time);
|
||||
//this.activeScene.update(delta_time);
|
||||
//this.orbit.update(0.1);
|
||||
|
||||
//console.log(this.transform_engine.clips[this.test_box_uuid]);
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
class PlayableClip {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.isPlaying = false;
|
||||
}
|
||||
|
||||
play() {
|
||||
this.isPlaying = true;
|
||||
console.log(`${this.name} is now playing.`);
|
||||
// Implementation of the play functionality
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.isPlaying = false;
|
||||
console.log(`${this.name} is paused.`);
|
||||
// Implementation of the pause functionality
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.isPlaying = false;
|
||||
console.log(`${this.name} has stopped.`);
|
||||
// Implementation of the stop functionality
|
||||
}
|
||||
}
|
||||
|
||||
class AudioClip extends PlayableClip {
|
||||
constructor(name, duration, format,location) {
|
||||
super(name);
|
||||
this.duration = duration; // in seconds
|
||||
this.format = format; // e.g., 'mp3', 'wav'
|
||||
this.location = location; // url path
|
||||
}
|
||||
|
||||
play() {
|
||||
super.play();
|
||||
// Additional implementation specific to AudioClip
|
||||
console.log(`Streaming audio for ${this.name}.`);
|
||||
}
|
||||
|
||||
pause() {
|
||||
super.pause();
|
||||
// Additional implementation specific to AudioClip
|
||||
console.log(`Audio stream paused for ${this.name}.`);
|
||||
}
|
||||
|
||||
stop() {
|
||||
super.stop();
|
||||
// Additional implementation specific to AudioClip
|
||||
console.log(`Audio stream stopped for ${this.name}.`);
|
||||
}
|
||||
}
|
||||
|
||||
class AnimationClip extends PlayableClip {
|
||||
constructor(name, frames, fps) {
|
||||
super(name);
|
||||
this.frames = frames; // Total number of frames
|
||||
this.fps = fps; // Frames per second
|
||||
}
|
||||
|
||||
play() {
|
||||
super.play();
|
||||
// Additional implementation specific to AnimationClip
|
||||
console.log(`Animation started for ${this.name}.`);
|
||||
}
|
||||
|
||||
pause() {
|
||||
super.pause();
|
||||
// Additional implementation specific to AnimationClip
|
||||
console.log(`Animation paused for ${this.name}.`);
|
||||
}
|
||||
|
||||
stop() {
|
||||
super.stop();
|
||||
// Additional implementation specific to AnimationClip
|
||||
console.log(`Animation stopped for ${this.name}.`);
|
||||
}
|
||||
}
|
||||
|
||||
class GameObjectClip extends PlayableClip {
|
||||
constructor(name, positions) {
|
||||
super(name);
|
||||
this.positions = positions; // Array of position objects { x, y, z }
|
||||
}
|
||||
|
||||
play() {
|
||||
super.play();
|
||||
// Additional implementation specific to GameObjectClip
|
||||
console.log(`GameObject movement started for ${this.name}.`);
|
||||
}
|
||||
|
||||
pause() {
|
||||
super.pause();
|
||||
// Additional implementation specific to GameObjectClip
|
||||
console.log(`GameObject movement paused for ${this.name}.`);
|
||||
}
|
||||
|
||||
stop() {
|
||||
super.stop();
|
||||
// Additional implementation specific to GameObjectClip
|
||||
console.log(`GameObject movement stopped for ${this.name}.`);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,14 @@ import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
|
||||
class Scene {
|
||||
constructor(name) {
|
||||
name: string;
|
||||
gridHelper: THREE.GridHelper | undefined;
|
||||
scene: THREE.Scene;
|
||||
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
this.gridHelper = null;
|
||||
this.gridHelper;
|
||||
this.scene = new THREE.Scene();
|
||||
this.activeItem = null;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@@ -15,7 +18,7 @@ class Scene {
|
||||
this._create_skybox();
|
||||
}
|
||||
|
||||
instantiate(name) {
|
||||
instantiate(name: string) {
|
||||
let material = new THREE.MeshPhongMaterial({ color: 0xffffff });
|
||||
let geometry;
|
||||
if (name == "Box") {
|
||||
@@ -43,19 +46,16 @@ class Scene {
|
||||
return obj.uuid;
|
||||
}
|
||||
|
||||
get_object_by_uuid(uuid) {
|
||||
get_object_by_uuid(uuid: string) {
|
||||
return this.scene.getObjectByProperty('uuid', uuid);
|
||||
}
|
||||
|
||||
update(delta) {
|
||||
|
||||
}
|
||||
|
||||
_disable_skybox() {
|
||||
this.scene.background = null;
|
||||
}
|
||||
|
||||
render_mode(enabled=true) {
|
||||
render_mode(enabled:boolean=true) {
|
||||
if(this.gridHelper == undefined) { return; }
|
||||
if(enabled) {
|
||||
this._disable_skybox();
|
||||
this.scene.remove(this.gridHelper);
|
||||
@@ -65,24 +65,13 @@ class Scene {
|
||||
}
|
||||
}
|
||||
|
||||
accept_animation_clip(clip) {
|
||||
this.animations.push(clip)
|
||||
}
|
||||
|
||||
play_anim_demo(character_uuid) {
|
||||
this.animated_items[character_uuid].animate(this.animated_items[character_uuid].anims[0]._clip);
|
||||
this.animated_items[character_uuid].sync_lips("/resources/sound/2pac.wav");
|
||||
this.activeItem = character_uuid;
|
||||
this.accept_animation_clip(this.animated_items[character_uuid].anims[0]._clip);
|
||||
}
|
||||
|
||||
async load_glb(filepath) { //: Promise<THREE.Object3D> {
|
||||
async load_glb(filepath: string) { //: Promise<THREE.Object3D> {
|
||||
return new Promise((resolve) => {
|
||||
let glbLoader = new GLTFLoader();
|
||||
glbLoader.load(filepath, (glb) => {
|
||||
glb.scene.children.forEach(child => {
|
||||
child.traverse(c => {
|
||||
if (c.isMesh) {
|
||||
child.traverse((c: THREE.Object3D) => {
|
||||
if (c instanceof THREE.Mesh) {
|
||||
c.material.metalness = 0.0;
|
||||
c.material.specular = 0.5;
|
||||
c.castShadow = true;
|
||||
@@ -1,97 +0,0 @@
|
||||
import * as THREE from 'three';
|
||||
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
|
||||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||
|
||||
class SaveManager {
|
||||
constructor(version) {
|
||||
this.version = version;
|
||||
this.scene = null;
|
||||
}
|
||||
|
||||
save(scene, scene_callback, audio_manager, timeline, animations) {
|
||||
let gltfExporter = new GLTFExporter();
|
||||
gltfExporter.parse(
|
||||
scene,
|
||||
function (gltf) {
|
||||
let save_json = {"glb": gltf, "audio": audio_manager.clips, "timeline": timeline}
|
||||
|
||||
// TODO: give the file name via a modal.
|
||||
const file = new File([JSON.stringify(gltf)], "test.glb", {type: 'application/json'});
|
||||
|
||||
let blobUrl = URL.createObjectURL(file);
|
||||
scene_callback(file);
|
||||
|
||||
let a = document.createElement('a');
|
||||
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
const randomNumber = Math.floor(Math.random() * 1000);
|
||||
let save_name = `save_${randomNumber}_${year}${month}${day}_${hours}${minutes}${seconds}.sav`;
|
||||
|
||||
a.href = blobUrl;
|
||||
a.download = save_name;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
},
|
||||
{
|
||||
trs: false,
|
||||
onlyVisible: false,
|
||||
animations: animations,
|
||||
binary: true
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
load(file, load_callback) {
|
||||
let reader = new FileReader();
|
||||
|
||||
reader.onload = function (event) {
|
||||
let data = JSON.parse(event.target.result);
|
||||
let glb = data.glb;
|
||||
let audio = data.audio;
|
||||
let timelineData = data.timeline;
|
||||
let animationData = data.animations;
|
||||
|
||||
let loader = new GLTFLoader();
|
||||
|
||||
loader.parse(glb, '', function (gltf) {
|
||||
let scene = gltf.scene;
|
||||
let clips = audio;
|
||||
let timeline = timelineData;
|
||||
let animations = animationData;
|
||||
load_callback(scene, clips, timeline, animations);
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
download(data, filename, type) {
|
||||
var file = new Blob([data], { type: type });
|
||||
if (window.navigator.msSaveOrOpenBlob) // IE10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
else { // Others
|
||||
var a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function () {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SaveManager;
|
||||
Whitespace-only changes.
Reference in new issue
Block a user