Commit 18f37e0e authored by Master Q's avatar Master Q

资源处理

parent 4ce8cf29
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<title>Three</title>
<style>
* {
padding: 0;
margin: 0;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
touch-action: none;
}
div {
user-select: none;
}
.load-container {
position: fixed;
width: 100vw;
height: 100vh;
margin: auto;
background: #ffffff;
z-index: 1000;
}
.load-container .boxLoading {
width: 50px;
height: 50px;
margin: auto;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.load-container .boxLoading:before {
content: "";
width: 50px;
height: 5px;
background: #000;
opacity: 0.1;
position: absolute;
top: 59px;
left: 0;
border-radius: 50%;
animation: shadow 0.5s linear infinite;
}
.load-container .boxLoading:after {
content: "";
width: 50px;
height: 50px;
background: #00adb5;
animation: animate 0.5s linear infinite;
position: absolute;
top: 0;
left: 0;
border-radius: 3px;
}
@keyframes animate {
17% {
border-bottom-right-radius: 3px;
}
25% {
transform: translateY(9px) rotate(22.5deg);
}
50% {
transform: translateY(18px) scale(1,0.9) rotate(45deg);
border-bottom-right-radius: 40px;
}
75% {
transform: translateY(9px) rotate(67.5deg);
}
100% {
transform: translateY(0) rotate(90deg);
}
}
@keyframes shadow {
0%,
100% {
transform: scale(1,1);
}
50% {
transform: scale(1.2,1);
}
}
</style>
<script src="//yun.duiba.com.cn/aurora/assets/4723050c150b41f362ecf483e9cf98eb31c4a15b.js"></script>
</head>
<body>
<div class="load-container">
<div class="boxLoading"></div>
</div>
<!-- 这里的 bundle 就是 webpack 临时打包出来 -->
<script src="/bundle.js"></script>
<script>
window.addEventListener("load", function () {
// window.screen.orientation.lock("landscape-primary");
window['showLoading'] = function() {
document.querySelector('.load-container').style.display = 'block'
}
window['hideLoading'] = function() {
document.querySelector('.load-container').style.display = 'none'
}
})
</script>
</body>
</html>
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"description": "three and oimo for car", "description": "three and oimo for car",
"main": "index.ts", "main": "index.ts",
"scripts": { "scripts": {
"dev": "webpack-dev-server", "dev": "node ./scripts/devServer -p 9016",
"build": "webpack" "build": "webpack"
}, },
"keywords": [ "keywords": [
...@@ -22,5 +22,8 @@ ...@@ -22,5 +22,8 @@
"webpack": "^5.74.0", "webpack": "^5.74.0",
"webpack-cli": "^4.10.0", "webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3" "webpack-dev-server": "^4.9.3"
},
"devDependencies": {
"webpack-merge": "^5.8.0"
} }
} }
import { BackSide } from "../constants";
import { BoxGeometry } from "../geometries/BoxGeometry";
import { PointLight } from "../lights/PointLight";
import { MeshBasicMaterial } from "../materials/MeshBasicMaterial";
import { MeshStandardMaterial } from "../materials/MeshStandardMaterial";
import { Mesh } from "../objects/Mesh";
import { Scene } from "../scenes/Scene";
class RoomEnvironment extends Scene {
constructor() {
super();
const geometry = new BoxGeometry();
geometry.deleteAttribute( 'uv' );
const roomMaterial = new MeshStandardMaterial( {
side: BackSide
} );
const boxMaterial = new MeshStandardMaterial();
const mainLight = new PointLight( 0xffffff, 5.0, 28, 2 );
mainLight.position.set( 0.418, 16.199, 0.300 );
this.add( mainLight );
const room = new Mesh( geometry, roomMaterial );
room.position.set( - 0.757, 13.219, 0.717 );
room.scale.set( 31.713, 28.305, 28.591 );
this.add( room );
const box1 = new Mesh( geometry, boxMaterial );
box1.position.set( - 10.906, 2.009, 1.846 );
box1.rotation.set( 0, - 0.195, 0 );
box1.scale.set( 2.328, 7.905, 4.651 );
this.add( box1 );
const box2 = new Mesh( geometry, boxMaterial );
box2.position.set( - 5.607, - 0.754, - 0.758 );
box2.rotation.set( 0, 0.994, 0 );
box2.scale.set( 1.970, 1.534, 3.955 );
this.add( box2 );
const box3 = new Mesh( geometry, boxMaterial );
box3.position.set( 6.167, 0.857, 7.803 );
box3.rotation.set( 0, 0.561, 0 );
box3.scale.set( 3.927, 6.285, 3.687 );
this.add( box3 );
const box4 = new Mesh( geometry, boxMaterial );
box4.position.set( - 2.017, 0.018, 6.124 );
box4.rotation.set( 0, 0.333, 0 );
box4.scale.set( 2.002, 4.566, 2.064 );
this.add( box4 );
const box5 = new Mesh( geometry, boxMaterial );
box5.position.set( 2.291, - 0.756, - 2.621 );
box5.rotation.set( 0, - 0.286, 0 );
box5.scale.set( 1.546, 1.552, 1.496 );
this.add( box5 );
const box6 = new Mesh( geometry, boxMaterial );
box6.position.set( - 2.193, - 0.369, - 5.547 );
box6.rotation.set( 0, 0.516, 0 );
box6.scale.set( 3.875, 3.487, 2.986 );
this.add( box6 ); // -x right
const light1 = new Mesh( geometry, createAreaLightMaterial( 50 ) );
light1.position.set( - 16.116, 14.37, 8.208 );
light1.scale.set( 0.1, 2.428, 2.739 );
this.add( light1 ); // -x left
const light2 = new Mesh( geometry, createAreaLightMaterial( 50 ) );
light2.position.set( - 16.109, 18.021, - 8.207 );
light2.scale.set( 0.1, 2.425, 2.751 );
this.add( light2 ); // +x
const light3 = new Mesh( geometry, createAreaLightMaterial( 17 ) );
light3.position.set( 14.904, 12.198, - 1.832 );
light3.scale.set( 0.15, 4.265, 6.331 );
this.add( light3 ); // +z
const light4 = new Mesh( geometry, createAreaLightMaterial( 43 ) );
light4.position.set( - 0.462, 8.89, 14.520 );
light4.scale.set( 4.38, 5.441, 0.088 );
this.add( light4 ); // -z
const light5 = new Mesh( geometry, createAreaLightMaterial( 20 ) );
light5.position.set( 3.235, 11.486, - 12.541 );
light5.scale.set( 2.5, 2.0, 0.1 );
this.add( light5 ); // +y
const light6 = new Mesh( geometry, createAreaLightMaterial( 100 ) );
light6.position.set( 0.0, 20.0, 0.0 );
light6.scale.set( 1.0, 0.1, 1.0 );
this.add( light6 );
}
dispose() {
const resources = new Set();
this.traverse( object => {
if ( object.isMesh ) {
resources.add( object.geometry );
resources.add( object.material );
}
} );
for ( const resource of resources ) {
resource.dispose();
}
}
}
function createAreaLightMaterial( intensity ) {
const material = new MeshBasicMaterial();
material.color.setScalar( intensity );
return material;
}
export {RoomEnvironment}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<title>Three</title>
<style>
* {
padding: 0;
margin: 0;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout:none;
-webkit-user-select:none;
-khtml-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
user-select:none;
touch-action: none;
}
div {
user-select: none;
}
</style>
<script src="./ammo.js"></script>
</head>
<body>
<!-- 这里的 bundle 就是 webpack 临时打包出来 -->
<script src="bundle.js"></script>
<script>
window.addEventListener("load", function () {
window.screen.orientation.lock("landscape-primary");
})
</script>
</body>
</html>
\ No newline at end of file
{
"groups": [
{
"keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf",
"name": "gltf"
},
{
"keys": "nx1.jpg,ny1.jpg,nz1.jpg,px1.jpg,py1.jpg,pz1.jpg",
"name": "skybox"
}
],
"path": "./resource/"
}
\ No newline at end of file
const path = require("path");
const runScript = require("./runScript");
const argv = process.argv;
const fs = require("fs");
// const skinUrl = "./resource/skin.json";
// fs.watchFile(skinUrl, { persistent: true, interval: 2000 }, (curr, prev) => {
// const skinDataAll = fs.readFileSync(skinUrl)
// var endFile = `export const SkinJson = ${skinDataAll}`
// fs.writeFileSync("./src/SkinJson.ts", endFile);
// console.log("SkinJson.ts文件已更新")
// })
// 修改resource文件夹任意内容自动刷新资源
fs.watch('./resource/', { recursive: true }, (event, filename) => {
if (
filename === ".DS_Store"
|| filename === "res.json"
|| filename === "skin.json"
) return;
runScript(path.resolve('./scripts/flushRes.js'), (err) => {
console.log(err);
});
});
runScript(path.resolve('./scripts/flushRes.js'), (err) => {
console.log(err);
});
const webpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('../webpack.dev.js');
// webpackDevServer.addDevServerEntrypoints(config, options);
const compiler = webpack(config);
const server = new webpackDevServer(config.devServer, compiler);
const runServer = async () => {
const ipV4 = await webpackDevServer.internalIP('v4')
console.log('========== ipV4 ==========', ipV4)
server.options.host = ipV4
const argvPort = +argv[argv.indexOf("-p") + 1]
argvPort && (server.options.port = +argv[argv.indexOf("-p") + 1])
await server.start()
}
runServer()
\ No newline at end of file
//生成res.json
//遍历资源文件夹,生成
var fs = require('fs');
var path = require("path");
var readPath = "./resource/"
var files = fs.readdirSync(readPath);
var obj = { groups: [] };//每项包括keys合name
files.forEach(function (file) {
//路径
let fPath = path.join(readPath, file);
//只处理文件夹
if (fs.statSync(fPath).isDirectory()) {
//继续读每个子文件夹,json和png名字有相同的,只留json,
var sonFiles = fs.readdirSync(fPath);
//没有文件
if (!sonFiles.length) return
//取出所有json
var jsons = sonFiles.filter((f) => { return f.substr(-5) == ".json" })
//去掉json所带png的图片
sonFiles = sonFiles.filter((f) => { return jsons.indexOf(f.substring(0, f.length - 4) + ".json") == -1 })
//去掉mac上的缓存文件
sonFiles = sonFiles.filter((f) => { return f != '.DS_Store' })
var group = {
keys: "",
name: file
}
for (var i = 0; i < sonFiles.length; i++) {
if (i != 0) group.keys += ",";
group.keys += sonFiles[i]
}
obj.groups.push(group)
}
})
obj.path="./resource/"
console.log("资源更新完成")
//生成json
fs.writeFileSync(readPath + "res.json", JSON.stringify(obj, "", "\t"));
//TS也更新
var endPath = './src/';
var endFile = `export const ResJson = ${JSON.stringify(obj, "", "\t")}`
fs.writeFileSync(endPath + "ResJson.ts", endFile);
\ No newline at end of file
/*
* runScript.js
* Created by 还有醋v on 2021/5/8.
* Copyright © 2021 haiyoucuv. All rights reserved.
*/
const childProcess = require('child_process');
module.exports = function runScript(scriptPath, callback) {
let invoked = false;
const process = childProcess.fork(scriptPath);
process.on('error', function (err) {
if (invoked) return;
invoked = true;
callback(err);
});
process.on('exit', function (code) {
if (invoked) return;
invoked = true;
const err = code === 0 ? null : new Error('exit code ' + code);
callback(err);
});
}
...@@ -143,7 +143,7 @@ export class CarScene extends PerspectiveScene { ...@@ -143,7 +143,7 @@ export class CarScene extends PerspectiveScene {
initUi() { initUi() {
const reflectionCube = new THREE.CubeTextureLoader() const reflectionCube = new THREE.CubeTextureLoader()
.setPath( '天空盒子4/' ) .setPath( '/resource/skybox/' )
.load( [ 'px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg' ] ); .load( [ 'px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg' ] );
reflectionCube.encoding = THREE.sRGBEncoding; reflectionCube.encoding = THREE.sRGBEncoding;
this.scene.background = reflectionCube; this.scene.background = reflectionCube;
...@@ -272,7 +272,7 @@ export class CarScene extends PerspectiveScene { ...@@ -272,7 +272,7 @@ export class CarScene extends PerspectiveScene {
scene: THREE.Scene, scene: THREE.Scene,
} }
GLTFLoaderIns.load('shamo_V10.gltf', (ins: GltfModel) => { GLTFLoaderIns.setPath('/resource/gltf/').load('shamo_V10.gltf', (ins: GltfModel) => {
console.log(ins) console.log(ins)
let terrainMesh: THREE.Mesh let terrainMesh: THREE.Mesh
......
...@@ -103,7 +103,7 @@ export class Vehicle extends THREE.Object3D{ ...@@ -103,7 +103,7 @@ export class Vehicle extends THREE.Object3D{
body.setActivationState(4); body.setActivationState(4);
var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength); var chassisMesh = this.chassisMesh = this.createChassisMesh(chassisWidth, chassisHeight, chassisLength);
GLTFLoaderIns.load('qiche_V6.gltf', (gltf: GltfModel) => { GLTFLoaderIns.setPath('/resource/gltf/').load('qiche_V6.gltf', (gltf: GltfModel) => {
chassisMesh.add(gltf.scene) chassisMesh.add(gltf.scene)
gltf.scene.visible = !VehicleDebugConfig.debugger gltf.scene.visible = !VehicleDebugConfig.debugger
gltf.scene.translateY(-1) gltf.scene.translateY(-1)
...@@ -356,7 +356,7 @@ export class Vehicle extends THREE.Object3D{ ...@@ -356,7 +356,7 @@ export class Vehicle extends THREE.Object3D{
const LuntaiIns = this.luntaiIns = await new Promise<GltfModel>(resolve => { const LuntaiIns = this.luntaiIns = await new Promise<GltfModel>(resolve => {
GLTFLoaderIns.load('luntai.gltf', (ins: GltfModel) => { GLTFLoaderIns.setPath('/resource/gltf/').load('luntai.gltf', (ins: GltfModel) => {
ins.scene.traverse(function(obj) { ins.scene.traverse(function(obj) {
// @ts-ignore // @ts-ignore
......
export const ResJson = {
"groups": [
{
"keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf",
"name": "gltf"
},
{
"keys": "nx1.jpg,ny1.jpg,nz1.jpg,px1.jpg,py1.jpg,pz1.jpg",
"name": "skybox"
}
],
"path": "./resource/"
}
\ No newline at end of file
import { CarScene } from "./CarScene" import { CarScene } from "./CarScene"
import * as THREE from 'three' import * as THREE from 'three'
import { RES } from "./module/RES"
import { ResJson } from "./ResJson"
window['THREE'] = THREE window['THREE'] = THREE
...@@ -8,7 +10,10 @@ export class StageScene { ...@@ -8,7 +10,10 @@ export class StageScene {
this.initStage() this.initStage()
} }
initStage() { async initStage() {
RES.loadConfig(ResJson)
await RES.loadGroup('skybox')
// @ts-expect-error // @ts-expect-error
Ammo().then(() => { Ammo().then(() => {
new CarScene() new CarScene()
......
import * as THREE from 'three'
import { GLTFLoader } from './loaders/GLTFLoader';
// 启用下吧,这里存的是 文件名, Three loader 会存 全路劲
THREE.Cache.enabled = true
export const TextureLoaderIns = new THREE.TextureLoader()
export const GltfLoaderIns = new GLTFLoader()
interface ResData {
/**
* 分组数据
*/
groups: GroupInt[];
//暂时没有工具,不用
resources?: any;
path?: string;
}
interface GroupInt {
/**
* 所有的资源名字,根据,分割,根据后缀区分类型
*
*/
keys: string;//"aa.png,bb.jpg,name.json"
/**
* 文件夹名字吧
*/
name: string;
/**
* 图集
* 线上打包合图可能有多张,暂时发现texturePacker版本问题只有一张
*/
atlas?: {
[name: string]: {
"x": number,
"y": number,
"w": number,
"h": number,
"ox": number,
"oy": number,
"sw": number,
"sh": number,
"ro": boolean
},
};
}
interface SkinInt {
name: string,
x: 0,
y: 0,
type: 'container' | 'text' | 'button' | 'sprite' | 'rect' | 'item',//item的不初始化进节点,只作为数据
children?: SkinInt[],
id?: string,
alpha: number,
props?: {
source?: string,
text: string,
size: number,
fillColor: string,
textAlpha: number,
width: number,
height: number,
tUp: string,
tDown: string,
tDisable: string
}
}
interface GLTFMODAL {
animations: THREE.AnimationClip[],
scene: THREE.Scene,
}
/**
* 简单点,有工具的话像egret那样玩,可以自动生成图片组数据
*/
export namespace RES {
let resData: ResData
/**
* 资源路径
*/
export let resPath: string;
/**
* RES单独缓存一下纹理,全局的FYGE缓存纹理对于多page有覆盖的问题;
*/
let textureHash: {
[name: string]: THREE.Texture;
} = {};
let gltfModalHash: {
[name: string]: GLTFMODAL
}
/**
* 音频的加载
*/
let soundHash = {}
/**
* 记录组加载完成
*/
let groupsCompleteHash: {
[name: string]: boolean
} = {}
/**
* 记录加载的promise TODO 这里是不是可以用一个 complete 就是fulfilled 的promise
*/
let groupsPromiseHash: {
[name: string]: Promise<any>
} = {}
/**
* 单独资源加载的promise记录
*/
let singleResPromiseHash: {
[name: string]: Promise<any>
} = {}
/**
*
* @param res 资源数据,就是对象,不考虑加载json先
* res格式{
* path:1111/
* groups: [
* {
*
* }
* ];
* }
* @param path
*/
export function loadConfig(res: ResData) {
resData = res;
resPath = res.path;
}
/**
* 根据组名加载一组资源,通常用于加载一个视图的的所有资源
* 里的promise的resolve并没有返回值
* @param name
*/
export function loadGroup(name: string): Promise<void> {
//已经加载完成的直接返回
if (groupsCompleteHash[name]) {//其实直接return就行
return new Promise((resolve) => {
resolve()
})
}
//如果是正在加载中的,返回正在加载中的promise
if (groupsPromiseHash[name]) {
return groupsPromiseHash[name];
}
//如果首次加载
//获取资源组
let arr = getGroupResByName(name);
//如果不存在arr,直接返回空p,且标记完成
if (!arr || !arr.length) {
groupsCompleteHash[name] = true;
return new Promise((resolve) => {
resolve()
})
}
// 建一个promise
let p:Promise<void> = new Promise((resolve, reject) => {
loadResList((s) => {
//移除
delete groupsPromiseHash[name];
if (s) {
groupsCompleteHash[name] = true;
resolve()
} else {
reject();
}
}, arr/*, resPath + name*/, name)
})
groupsPromiseHash[name] = p;
return p;
}
/**
* var textue = await RES.getResAsync(str);
* @param str 可以是网络图片路径或键值
* @param comFun 加载回调
* @param thisObj this指向
*/
export function getResAsync(str: string, comFun?: (res: any, str: string) => void, thisObj?: any, groupname?: string): Promise<any> {
// var arr = str.split(".");
var type = str.substring(str.lastIndexOf(".") + 1, str.length);
function resolveInvoke(data: any) {
comFun && comFun.call(thisObj, data, str)
}
//如果是图片
if (type == "png" || type == "jpg") {
//原先就有了,加载过的,且已加载完成的
let cached = textureHash[str] || THREE.Cache.get(str);
if (cached) {
//回调形式
comFun && comFun.call(thisObj, cached, str)
// return cached;
return new Promise((r) => { //为了能.then
r(cached)
})
}
//未加载完成的
else if (singleResPromiseHash[str]) {
return returnSingleResPromise(str, comFun, thisObj)
}
else {
//判断是否在资源里,判断是否要加载图集,注意已排除jpg
var groupName = groupname || hasRes(str);
if (groupName && type != "jpg") {
var group = getGroupByName(groupName);
if (group && group.atlas) {
//加载图集,现在就一张,以后有机会改
var json = groupName + ".json"//group.atlas.split(",")[0];
//找json是否在加载中
if (singleResPromiseHash[json]) {
return singleResPromiseHash[json].then(
(r) => {
//正在加载中,getResAsync首次加载的回调会缓存,完成后返回需要的,
let cached = textureHash[str] || THREE.Cache.get(str)
comFun && comFun.call(thisObj, cached, str)
return cached;
},
() => {
comFun && comFun.call(thisObj, null, str)
return null
}
)
} else {
return getResAsync(json)
.then(() => {
let cached = textureHash[str] || THREE.Cache.get(str)
comFun && comFun.call(thisObj, cached, str)
return cached
}, () => {
comFun && comFun.call(thisObj, null, str)
return null
})
}
}
}
var src = groupName ? resPath + groupName + "/" + str : str;
var p = new Promise((resolve, reject) => {
TextureLoaderIns.load(src, (texture) => {
//移除
delete singleResPromiseHash[str];
let cached = texture
//入RES,
textureHash[str] = cached;
comFun && comFun.call(thisObj, cached, str)
resolve(cached)
}, () => {
}, (error) => {
comFun && comFun.call(thisObj, null, str)
reject(error)
})
})
singleResPromiseHash[str] = p
return p
}
}
//json图集的话,不晓得用啥判断加载完成,所以不删除promise吧,其实json可能只是数据,不管先
else if (type == "json") {
// Three 加载图集 先不处理
return Promise.resolve()
// if (singleResPromiseHash[str]) {
// return returnSingleResPromise(str, comFun, thisObj)
// } else {
// var groupName = hasRes(str);//json现在肯定在内,暂时不能加载其他域名的json
// var src = groupName ? resPath + groupName + "/" + str : str;
// var p = new Promise((resolve, reject) => {
// var jsonData = getGroupByName(groupName).atlas
// TextureLoader.load(
// src.replace("json", "png"),
// (texture) => {
// // jsonData 图集资源 TODO three 打包图集有点问题
// var t: Record<string, any> = {}
// //缓存进RES
// for (let key in t) textureHash[key] = t[key];
// comFun && comFun.call(thisObj, t, str)
// resolve(t)
// },
// () => {},
// (error) => {
// //加载失败,移除要,否则再次触发加载会出问题
// delete singleResPromiseHash[str];
// comFun && comFun.call(thisObj, null, str)
// reject(error)
// }
// )
// })
// singleResPromiseHash[str] = p
// return p
// }
} else if (type == 'gltf') {
let cache = gltfModalHash[str]
if (cache) {
resolveInvoke(cache)
return Promise.resolve(cache)
} else if (singleResPromiseHash[str]) {
return returnSingleResPromise(str, comFun, thisObj)
} else {
var src = groupName ? resPath + groupName + "/" + str : str;
singleResPromiseHash[str] = new Promise<void>((resolve, reject) => {
GltfLoaderIns.load(
src,
(ins: GLTFMODAL) => {
delete singleResPromiseHash[str]
gltfModalHash[str] = ins
resolveInvoke(ins)
resolve()
},
() => {},
(error: any) => {
delete singleResPromiseHash[str]
resolveInvoke(null)
reject(error)
}
)
})
}
}
}
/**
* 待写,根据网络路径加载图片
*/
export function getResByUrl() {
}
/**
* 获取素材,
* @param str
* @return 已加载好得素材或null
*/
export function getRes(str: `${string}.${'png' | 'jpg' | 'gltf'}`)/*: Texture | VideoEntity*/ {
if (!str) return null;
var type = str.substring(str.lastIndexOf(".") + 1, str.length);
if (type == "png" || type == "jpg") {
return textureHash[str] || THREE.Cache.get(str) || null;
}
else if (type == "gltf") {
return gltfModalHash || null
}
}
/**
* 偷懒的方法,加载配置里所有的资源,基本也不用
*/
export function loadAllGroup() {
var groups = resData.groups;
var p: Promise<any>[] = []
groups.forEach((g) => {
p.push(loadGroup(g.name))
})
return Promise.all(p)
}
/**
* 判断是否在资源组里
* 考虑是否init就做表
* 有就返回组名,为了加载路径,不然以后有工具可以放入resources
*/
function hasRes(str: string): string {
for (var i = 0; i < resData.groups.length; i++) {
var group = resData.groups[i];
var keys = group.keys;
if (keys && keys.split(",").indexOf(str) > -1) {
return group.name;
}
//如果是图集的json,altas现在是图集
if (group.atlas && group.name + ".json" == str) {
return group.name;
}
}
return null
}
/**
* 处理数据,获得所有资源单项
* @param name
*/
function getGroupResByName(name: string) {
var group: GroupInt = getGroupByName(name);
if (!group) return null;
//判断加载图集还是单图
if (group.atlas) {
// var arr: string[] = [].concat(group.atlas.split(","));
var arr = [name + ".json"]
//再添加非图片的资源,和图集已排除jpg
if (group.keys) {
arr = arr.concat(group.keys.split(",").filter((k: string) => {
return k.substr(-4) != ".png" //&& k.substr(-4) != ".jpg"
}))
}
return arr
}
else if (group.keys) {
return group.keys.split(",")
} else {
return null
}
}
/**
* 根据名字找组
* @param name
*/
function getGroupByName(name: string): GroupInt {
var groups = resData.groups;
var group: GroupInt;
for (var i = 0; i < groups.length; i++) {
if (groups[i].name === name) {
group = groups[i];
break;
}
}
return group
}
/**
* 新版的加载一列资源
* @param callback
* @param arr
*/
function loadResList(this: any, callback: (allLoaded: boolean) => void, arr: string[], groupName:string) {
let count = 0;
let countAll = arr.length;
if (!countAll) callback(true);
let mark = true;
for (var i = 0; i < countAll; i++) {
let resName = arr[i];
getResAsync(resName, (res, str) => {
//标记失败,如果有一项资源加载失败,标记下
if (!res) mark = false
if (++count == countAll) callback(mark);
}, this, groupName)
}
}
/**
*
* @param str
* @param comFun
* @param thisObj
*/
function returnSingleResPromise(str: string, comFun?: (res: any, str: string) => void, thisObj?: any) {
//已判断是否存在
singleResPromiseHash[str].then(
(r) => {
comFun && comFun.call(thisObj, r, str)
},
() => {
comFun && comFun.call(thisObj, null, str)
}
)
return singleResPromiseHash[str];
}
//皮肤相关的也放在RES吧
let skinData: SkinInt
/**
* 添加皮肤配置文件
*/
export function loadSkinConfig(skinJson: any) {
skinData = skinJson;
}
/**
* 根据
* @param con 添加显示对象的容器
* @param skin 皮肤名字或数据
* @param root 根容器,为了添加自定义引用
*/
// export function initSkinDisplay(con: FYGE.Container, skin: string | SkinInt, root?: FYGE.Container) {
// //@ts-ignore
// var data: SkinInt = typeof (skin) == 'string' ? getSkinDataByName(skin) : skin;
// if (!data.children || !data.children.length) return;
// // for (var i = data.children.length - 1; i >= 0; i--) {
// for (var i = 0; i < data.children.length; i++) {
// var child = data.children[i];
// if (child.type == "item") continue;
// var dis = con.addChild(getDisplayByData(child));
// if (root && child.id) root[child.id] = dis;
// if (child.type == "container") initSkinDisplay(dis, child, root);
// }
// }
/**
* 遍历根据名字找节点数据,只会是container的
* @param skinName
*/
export function getSkinDataByName(skinName: string, skinNode: SkinInt = skinData): SkinInt {
if (!skinNode || !skinNode.children || !skinNode.children.length) return null;
for (var i = 0; i < skinNode.children.length; i++) {
var child = skinNode.children[i];
if (child.name == skinName && (child.type == "container" || child.type == "item")) return child;
var gson = getSkinDataByName(skinName, child);
if (gson) return gson
}
return null;
}
/**
* 通过数据创建显示对象
* @param data
*/
// function getDisplayByData(data: SkinInt): FYGE.Container {
// var dis: FYGE.Container;
// switch (data.type) {
// case "container":
// dis = new FYGE.Container();
// break;
// case "button":
// dis = new FYGE.Button(
// getRes(data.props.tUp),
// data.props.tDown ? getRes(data.props.tDown) : null,
// data.props.tDisable ? getRes(data.props.tDisable) : null,
// );
// break;
// case "text":
// dis = new FYGE.TextField();
// for (let key in data.props) dis[key] = data.props[key];
// break;
// case "sprite":
// dis = new FYGE.Sprite(getRes(data.props.source));
// break;
// case "rect":
// // dis = new FYGE.Graphics()
// // .beginFill(data.props.fillColor)
// // .drawRect(0, 0, data.props.width, data.props.height)
// // .endFill();
// dis = new FYGE.Shape()
// //@ts-ignore
// dis.beginFill(FYGE.string2hex(data.props.fillColor))
// //@ts-ignore
// dis.drawRect(0, 0, data.props.width, data.props.height)
// //@ts-ignore
// dis.endFill();
// break;
// }
// dis.name = data.name;
// dis.alpha = data.alpha || 1;
// dis.position.set(data.x, data.y);
// // if (data.type == "text") dis.y -= 4;//文本莫名偏下,移动下,手机调试的时候也试试
// return dis;
// }
/**
* 销毁组纹理
* 线上才有用,待测试,TODO
* @param name
*/
// export function destroyGroup(name: string) {
// var group: GroupInt = getGroupByName(name);
// if (!group) return;
// var arr = [];
// if (group.keys) {
// arr = group.keys.split(",")
// }
// var removedBase = [];
// //散图清除
// for (var i = 0; i < arr.length; i++) {
// var t: FYGE.Texture = getRes(arr[i]);
// if (t) {
// //base的清除,不要重复清除
// if (removedBase.indexOf(t.baseTexture) == -1) {
// t.baseTexture.destroy();
// removedBase.push(t.baseTexture)
// }
// //自己纹理清除
// t.destroy();
// }
// //RES里单独缓存的清除
// delete textureHash[arr[i]]
// }
// }
//貌似不需要,为了加载过一次的资源不用重新加载
function destroyRES() {
}
}
import * as THREE from 'three'
import { RES } from '../../RES'
export class PreloadGroup extends THREE.Group {
get groupNames(): string[] { return null }
constructor(...args: any[]) {
super()
this._preloadRes()
}
_preloadRes() {
new Promise((resolve, reject) => {
if (this.groupNames && this.groupNames.length) {
Promise.all(
this.groupNames.map(name => RES.loadGroup(name))
).then(resolve, reject)
} else {
resolve(1)
}
}).then(this.initUi)
}
protected initUi() {}
}
\ No newline at end of file
...@@ -28,12 +28,6 @@ module.exports = { ...@@ -28,12 +28,6 @@ module.exports = {
}, },
output: { output: {
filename: 'bundle.js', filename: 'bundle.js',
path: path.resolve(__dirname, './dist') path: path.resolve(__dirname, './dist'),
},
devServer: {
port: '0.0.0.0',
hot: true,
open: true,
port: 9017
} }
} }
\ No newline at end of file
const {
merge
} = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path')
// const webpack = require('webpack');
// const MockWebpackPlugin = require('mock-webpack-plugin');
// const mockConfig = require('./mock/config.js');
module.exports = merge(common, {
mode: "development",
devtool: 'eval-source-map',
devServer: {
port: '0.0.0.0',
hot: true,
open: true,
port: 9017,
proxy: {
},
static: '.'
}
// plugins: [
// new MockWebpackPlugin({
// config: mockConfig,
// port: 3000
// })
// ]
});
...@@ -2053,7 +2053,7 @@ webpack-dev-server@^4.9.3: ...@@ -2053,7 +2053,7 @@ webpack-dev-server@^4.9.3:
webpack-dev-middleware "^5.3.1" webpack-dev-middleware "^5.3.1"
ws "^8.4.2" ws "^8.4.2"
webpack-merge@^5.7.3: webpack-merge@^5.7.3, webpack-merge@^5.8.0:
version "5.8.0" version "5.8.0"
resolved "http://npm.dui88.com:80/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" resolved "http://npm.dui88.com:80/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61"
integrity sha1-Kznb8ir4d3atdEw5AiNzHTCmj2E= integrity sha1-Kznb8ir4d3atdEw5AiNzHTCmj2E=
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment