Add parse to obj function & Bind clip recoder & loader event #51
300
config/parseSave2Obj.js
Normal file
300
config/parseSave2Obj.js
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
const PATH = require("path");
|
||||||
|
const FS = require("fs");
|
||||||
|
const MINIMIST = require("minimist");
|
||||||
|
const READLINE = require("readline-sync");
|
||||||
|
|
||||||
|
const ARGS = MINIMIST(process.argv.slice(2), {
|
||||||
|
alias: {i: ["input", "save"], o: ["output", "obj"]}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取路径
|
||||||
|
const inputFilePath = PATH.resolve(ARGS.i ?? "./save.ltss");
|
||||||
|
const outputFilePath = PATH.resolve(ARGS.o ?? "./output.obj");
|
||||||
|
|
||||||
|
// 读取文件
|
||||||
|
const fileString = FS.readFileSync(inputFilePath);
|
||||||
|
console.log("文件读取成功...\r\n");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 引入所需类型
|
||||||
|
* @typedef {import("../source/Model/Archive").IArchiveObject} IArchiveObject
|
||||||
|
* @typedef {import("../source/Model/Clip").IArchiveClip} IArchiveClip
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析文件
|
||||||
|
* @type {IArchiveObject}
|
||||||
|
*/
|
||||||
|
const archive = JSON.parse(fileString);
|
||||||
|
console.log("文件解析成功...\r\n");
|
||||||
|
|
||||||
|
// 打印全部的剪辑列表
|
||||||
|
if (archive.clipPool.length > 0) {
|
||||||
|
console.log("这个存档中存在以下剪辑:");
|
||||||
|
}
|
||||||
|
archive.clipPool.map((item, index) => {
|
||||||
|
console.log(" \033[44;30m" + (index + 1) + "\033[40;32m " + item.name + " [" + item.id + "]\033[0m");
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择剪辑
|
||||||
|
* @type {IArchiveClip}
|
||||||
|
*/
|
||||||
|
let clip;
|
||||||
|
if (archive.clipPool.length <= 0) {
|
||||||
|
console.log("存档中没有剪辑, 退出程序...\r\n");
|
||||||
|
process.exit();
|
||||||
|
} else if (archive.clipPool.length === 1) {
|
||||||
|
console.log("\r\n存档中只有一个剪辑, 自动选择...\r\n");
|
||||||
|
clip = archive.clipPool[0];
|
||||||
|
} else {
|
||||||
|
console.log("\r\n请选择一个剪辑: ");
|
||||||
|
let userInput = READLINE.question();
|
||||||
|
for (let i = 0; i < archive.clipPool.length; i++) {
|
||||||
|
if ((i + 1) == userInput) {
|
||||||
|
clip = archive.clipPool[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择提示
|
||||||
|
if (clip) {
|
||||||
|
console.log("已选择剪辑: " + clip.name + "\r\n");
|
||||||
|
} else {
|
||||||
|
console.log("没有选择任何剪辑, 退出程序...\r\n");
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解压缩文件
|
||||||
|
console.log("正在还原压缩剪辑记录...\r\n");
|
||||||
|
const frames = clip.frames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Map<string, {name: string, type: string, select?: boolean}}
|
||||||
|
*/
|
||||||
|
const objectMapper = new Map();
|
||||||
|
|
||||||
|
const LastFrameData = "@";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {IArchiveClip["frames"]}
|
||||||
|
*/
|
||||||
|
const F = [];
|
||||||
|
frames.forEach((frame) => {
|
||||||
|
/**
|
||||||
|
* @type {IArchiveClip["frames"][number]["commands"]}
|
||||||
|
*/
|
||||||
|
const FCS = [];
|
||||||
|
frame.commands.forEach((command) => {
|
||||||
|
|
||||||
|
// 压缩指令
|
||||||
|
const FC = {
|
||||||
|
id: command.id,
|
||||||
|
type: command.type
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上一帧
|
||||||
|
* @type {IArchiveClip["frames"][number]}
|
||||||
|
*/
|
||||||
|
const lastFrame = F[F.length - 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上一帧指令
|
||||||
|
* @type {IArchiveClip["frames"][number]["commands"][number]}
|
||||||
|
*/
|
||||||
|
const lastCommand = lastFrame?.commands.filter((c) => {
|
||||||
|
if (c.type === command.type && c.id === command.id) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
// 记录
|
||||||
|
FC.name = (LastFrameData === command.name) ? lastCommand?.name : command.name;
|
||||||
|
|
||||||
|
FC.data = (LastFrameData === command.data) ? lastCommand?.data : command.data;
|
||||||
|
|
||||||
|
FC.mapId = (LastFrameData === command.mapId) ? lastCommand?.mapId : command.mapId;
|
||||||
|
|
||||||
|
FC.position = (LastFrameData === command.position) ? lastCommand?.position : command.position;
|
||||||
|
|
||||||
|
FC.radius = (LastFrameData === command.radius) ? lastCommand?.radius : command.radius;
|
||||||
|
|
||||||
|
// 获取 Mapper
|
||||||
|
const mapper = objectMapper.get(FC.id);
|
||||||
|
if (mapper) {
|
||||||
|
mapper.type = FC.type ?? mapper.type;
|
||||||
|
mapper.name = FC.name ?? mapper.name;
|
||||||
|
} else {
|
||||||
|
objectMapper.set(FC.id, {
|
||||||
|
type: FC.type,
|
||||||
|
name: FC.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FCS.push(FC);
|
||||||
|
});
|
||||||
|
|
||||||
|
F.push({
|
||||||
|
duration: frame.duration,
|
||||||
|
process: frame.process,
|
||||||
|
commands: FCS
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("剪辑记录还原成功...\r\n");
|
||||||
|
console.log("剪辑共 " + F.length + " 帧, 对象 " + objectMapper.size + " 个\r\n");
|
||||||
|
if (objectMapper.size) {
|
||||||
|
console.log("剪辑记录中存在以下对象:");
|
||||||
|
} else {
|
||||||
|
console.log("剪辑记录中没有任何对象,退出程序...");
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
let objectMapperForEachIndex = 1;
|
||||||
|
objectMapper.forEach((item, key) => {
|
||||||
|
console.log(" \033[44;30m" + (objectMapperForEachIndex ++) + "\033[40;32m " + item.type + " " + item.name + " [" + key + "]\033[0m");
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number[]}
|
||||||
|
*/
|
||||||
|
const pointMapper = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
|
* @param {number} z
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function getPointID(x, y, z) {
|
||||||
|
let search = -1;
|
||||||
|
let pointMapperLength = (pointMapper.length / 3);
|
||||||
|
// for (let i = 0; i < pointMapperLength; i++) {
|
||||||
|
// if (
|
||||||
|
// pointMapper[i * 3 + 0] === x &&
|
||||||
|
// pointMapper[i * 3 + 1] === y &&
|
||||||
|
// pointMapper[i * 3 + 2] === z
|
||||||
|
// ) {
|
||||||
|
// search = i;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (search >= 0) {
|
||||||
|
return search;
|
||||||
|
} else {
|
||||||
|
pointMapper.push(x);
|
||||||
|
pointMapper.push(y);
|
||||||
|
pointMapper.push(z);
|
||||||
|
return pointMapperLength + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let frameId = 0;
|
||||||
|
/**
|
||||||
|
* @type {Map<string, {id: number, start: number, last: number, name: string, point: number[]}[]>}
|
||||||
|
*/
|
||||||
|
const objectLineMapper = new Map();
|
||||||
|
/**
|
||||||
|
* @param {string} obj
|
||||||
|
* @param {number} id
|
||||||
|
* @param {number} point
|
||||||
|
*/
|
||||||
|
function recordPoint(obj, id, point) {
|
||||||
|
let searchObj = objectLineMapper.get(obj);
|
||||||
|
if (searchObj) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {{id: number, start: number, last: number, point: number[]}}
|
||||||
|
*/
|
||||||
|
let search;
|
||||||
|
for (let i = 0; i < searchObj.length; i++) {
|
||||||
|
if (searchObj[i].id === id && searchObj[i].last === (frameId - 1)) {
|
||||||
|
search = searchObj[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
search.point.push(point);
|
||||||
|
search.last = frameId;
|
||||||
|
} else {
|
||||||
|
searchObj.push({
|
||||||
|
id: id,
|
||||||
|
start: frameId,
|
||||||
|
last: frameId,
|
||||||
|
point: [point]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
objectLineMapper.set(obj, [{
|
||||||
|
id: id,
|
||||||
|
start: frameId,
|
||||||
|
last: frameId,
|
||||||
|
point: [point]
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\r\n正在收集多边形数据...\r\n");
|
||||||
|
for (frameId = 0; frameId < F.length; frameId ++) {
|
||||||
|
F[frameId].commands.forEach((command) => {
|
||||||
|
|
||||||
|
if (command.type === "points" && command.mapId && command.data) {
|
||||||
|
command.mapId.forEach((pid, index) => {
|
||||||
|
|
||||||
|
const x = command.data[index * 3 + 0];
|
||||||
|
const y = command.data[index * 3 + 1]
|
||||||
|
const z = command.data[index * 3 + 2]
|
||||||
|
|
||||||
|
if (
|
||||||
|
x !== undefined &&
|
||||||
|
y !== undefined &&
|
||||||
|
z !== undefined
|
||||||
|
) {
|
||||||
|
recordPoint(command.id, pid, getPointID(x, y, z));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let pointCount = (pointMapper.length / 3);
|
||||||
|
|
||||||
|
console.log("收集点数据 " + pointCount + "个\r\n");
|
||||||
|
console.log("收集样条:");
|
||||||
|
let objectLineMapperIndexPrint = 1;
|
||||||
|
objectLineMapper.forEach((item, key) => {
|
||||||
|
let iName = objectMapper.get(key).name;
|
||||||
|
console.log(" \033[44;30m" + (objectLineMapperIndexPrint ++) + "\033[40;32m " + item.length + " " + iName + " [" + key + "]\033[0m");
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\r\n正在生成 .obj 文件...\r\n");
|
||||||
|
|
||||||
|
let fileStr = ""; let fileStrVec = "";
|
||||||
|
|
||||||
|
objectLineMapper.forEach((item, key) => {
|
||||||
|
|
||||||
|
for (let i = 0; i < item.length; i++) {
|
||||||
|
fileStr += "\r\n";
|
||||||
|
fileStr += ("o " + objectMapper.get(key).name + " " + item[i].id + "\r\n");
|
||||||
|
fileStr += "usemtl default\r\n";
|
||||||
|
fileStr += "l ";
|
||||||
|
// fileStr += (getPointID(item[i].id, item[i].start, item[i].last) + " ");
|
||||||
|
fileStr += item[i].point.join(" ");
|
||||||
|
fileStr += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
fileStr += "\r\n";
|
||||||
|
});
|
||||||
|
|
||||||
|
pointCount = (pointMapper.length / 3);
|
||||||
|
for (let i = 0; i < pointCount; i++) {
|
||||||
|
fileStrVec += ("v " + pointMapper[i * 3 + 0] + " " + pointMapper[i * 3 + 1] + " " + pointMapper[i * 3 + 2] + "\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = "# Create with Living Together (Parse from .ltss file)\r\n\r\n" + fileStrVec + fileStr;
|
||||||
|
|
||||||
|
console.log("正在生成保存文件...\r\n");
|
||||||
|
FS.writeFileSync(outputFilePath, file);
|
||||||
|
console.log("成功\r\n");
|
14
package-lock.json
generated
14
package-lock.json
generated
@ -19,6 +19,7 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"readline-sync": "^1.4.10",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -6367,6 +6368,14 @@
|
|||||||
"node": ">=8.10.0"
|
"node": ">=8.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readline-sync": {
|
||||||
|
"version": "1.4.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/readline-sync/-/readline-sync-1.4.10.tgz",
|
||||||
|
"integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rechoir": {
|
"node_modules/rechoir": {
|
||||||
"version": "0.7.1",
|
"version": "0.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
||||||
@ -13309,6 +13318,11 @@
|
|||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readline-sync": {
|
||||||
|
"version": "1.4.10",
|
||||||
|
"resolved": "https://registry.npmmirror.com/readline-sync/-/readline-sync-1.4.10.tgz",
|
||||||
|
"integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw=="
|
||||||
|
},
|
||||||
"rechoir": {
|
"rechoir": {
|
||||||
"version": "0.7.1",
|
"version": "0.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"readline-sync": "^1.4.10",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,11 +174,13 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
this.emit("objectChange");
|
this.emit("objectChange");
|
||||||
this.emit("labelChange");
|
this.emit("labelChange");
|
||||||
this.emit("behaviorChange");
|
this.emit("behaviorChange");
|
||||||
|
this.emit("clipChange");
|
||||||
|
|
||||||
// 清除焦点对象
|
// 清除焦点对象
|
||||||
this.setBehaviorObject();
|
this.setBehaviorObject();
|
||||||
this.setFocusObject(new Set());
|
this.setFocusObject(new Set());
|
||||||
this.setLabelObject();
|
this.setLabelObject();
|
||||||
|
this.setClipObject();
|
||||||
|
|
||||||
// 映射
|
// 映射
|
||||||
this.emit("fileLoad");
|
this.emit("fileLoad");
|
||||||
@ -196,11 +198,13 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
this.on("objectChange", handelFileChange);
|
this.on("objectChange", handelFileChange);
|
||||||
this.on("behaviorChange", handelFileChange);
|
this.on("behaviorChange", handelFileChange);
|
||||||
this.on("labelChange", handelFileChange);
|
this.on("labelChange", handelFileChange);
|
||||||
|
this.on("clipChange", handelFileChange);
|
||||||
this.on("individualChange", handelFileChange);
|
this.on("individualChange", handelFileChange);
|
||||||
this.on("groupAttrChange", handelFileChange);
|
this.on("groupAttrChange", handelFileChange);
|
||||||
this.on("rangeAttrChange", handelFileChange);
|
this.on("rangeAttrChange", handelFileChange);
|
||||||
this.on("labelAttrChange", handelFileChange);
|
this.on("labelAttrChange", handelFileChange);
|
||||||
this.on("behaviorAttrChange", handelFileChange);
|
this.on("behaviorAttrChange", handelFileChange);
|
||||||
|
this.on("clipAttrChange", handelFileChange);
|
||||||
this.on("fileChange", () => this.archive.emit("fileChange"));
|
this.on("fileChange", () => this.archive.emit("fileChange"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,4 +301,4 @@ class Archive extends Emitter<IArchiveEvent> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Archive };
|
export { Archive, IArchiveObject };
|
@ -7,7 +7,9 @@ import { archiveObject2Parameter, IArchiveParseFn, parameter2ArchiveObject } fro
|
|||||||
interface IDrawCommand {
|
interface IDrawCommand {
|
||||||
type: "points" | "cube";
|
type: "points" | "cube";
|
||||||
id: string;
|
id: string;
|
||||||
|
name?: string;
|
||||||
data?: Float32Array;
|
data?: Float32Array;
|
||||||
|
mapId?: number[];
|
||||||
position?: number[];
|
position?: number[];
|
||||||
radius?: number[];
|
radius?: number[];
|
||||||
parameter?: IAnyObject;
|
parameter?: IAnyObject;
|
||||||
@ -143,7 +145,7 @@ class Clip {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isArrayEqual(a1?: number[], a2?: number[]): boolean {
|
public isArrayEqual(a1?: Array<number | string>, a2?: Array<number | string>): boolean {
|
||||||
|
|
||||||
if ((a1 && !a2) || (!a1 && a2)) {
|
if ((a1 && !a2) || (!a1 && a2)) {
|
||||||
return false;
|
return false;
|
||||||
@ -179,6 +181,26 @@ class Clip {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID 映射
|
||||||
|
*/
|
||||||
|
private sorterIdMapper: Map<string, number> = new Map();
|
||||||
|
private sorterIdMapperNextId: number = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取映射ID
|
||||||
|
*/
|
||||||
|
private getMapperId = (id: string): number => {
|
||||||
|
let mapperId = this.sorterIdMapper.get(id);
|
||||||
|
if (mapperId === undefined) {
|
||||||
|
mapperId = this.sorterIdMapperNextId ++;
|
||||||
|
this.sorterIdMapper.set(id, mapperId);
|
||||||
|
return mapperId;
|
||||||
|
} else {
|
||||||
|
return mapperId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 录制一帧
|
* 录制一帧
|
||||||
*/
|
*/
|
||||||
@ -196,10 +218,12 @@ class Clip {
|
|||||||
const lastCommand = this.getCommandFromLastFrame("points", object.id);
|
const lastCommand = this.getCommandFromLastFrame("points", object.id);
|
||||||
|
|
||||||
// 记录
|
// 记录
|
||||||
|
const dataBuffer = object.exportPositionId(this.getMapperId);
|
||||||
const recodeData: IDrawCommand = {
|
const recodeData: IDrawCommand = {
|
||||||
type: "points",
|
type: "points",
|
||||||
id: object.id,
|
id: object.id,
|
||||||
data: object.exportPositionData()
|
name: object.displayName,
|
||||||
|
data: dataBuffer[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对比校验
|
// 对比校验
|
||||||
@ -209,6 +233,12 @@ class Clip {
|
|||||||
recodeData.parameter = this.cloneRenderParameter(object.renderParameter);
|
recodeData.parameter = this.cloneRenderParameter(object.renderParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isArrayEqual(dataBuffer[1], lastCommand?.mapId)) {
|
||||||
|
recodeData.mapId = lastCommand?.mapId;
|
||||||
|
} else {
|
||||||
|
recodeData.mapId = dataBuffer[1];
|
||||||
|
}
|
||||||
|
|
||||||
commands.push(recodeData);
|
commands.push(recodeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +251,8 @@ class Clip {
|
|||||||
// 记录
|
// 记录
|
||||||
const recodeData: IDrawCommand = {
|
const recodeData: IDrawCommand = {
|
||||||
type: "cube",
|
type: "cube",
|
||||||
id: object.id
|
id: object.id,
|
||||||
|
name: object.displayName
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放上一帧的内存
|
// 释放上一帧的内存
|
||||||
@ -260,7 +291,7 @@ class Clip {
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly LastFrameData: "@L" = "@L";
|
public readonly LastFrameData: "@" = "@";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 压缩帧数据
|
* 压缩帧数据
|
||||||
@ -287,9 +318,15 @@ class Clip {
|
|||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
// 记录
|
// 记录
|
||||||
|
command.name = (lastCommand?.name === commands[j].name) ?
|
||||||
|
this.LastFrameData as any : commands[j].name;
|
||||||
|
|
||||||
command.data = (lastCommand?.data === commands[j].data) ?
|
command.data = (lastCommand?.data === commands[j].data) ?
|
||||||
this.LastFrameData as any : Array.from(commands[j].data ?? []);
|
this.LastFrameData as any : Array.from(commands[j].data ?? []);
|
||||||
|
|
||||||
|
command.mapId = (lastCommand?.mapId === commands[j].mapId) ?
|
||||||
|
this.LastFrameData as any : commands[j].mapId;
|
||||||
|
|
||||||
command.position = (lastCommand?.position === commands[j].position) ?
|
command.position = (lastCommand?.position === commands[j].position) ?
|
||||||
this.LastFrameData as any : commands[j].position?.concat([]);
|
this.LastFrameData as any : commands[j].position?.concat([]);
|
||||||
|
|
||||||
@ -336,12 +373,16 @@ class Clip {
|
|||||||
this.getCommandFromLastFrame(command.type, command.id, resFrame[resFrame.length - 1]) :
|
this.getCommandFromLastFrame(command.type, command.id, resFrame[resFrame.length - 1]) :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
console.log(lastCommand);
|
|
||||||
|
|
||||||
// 记录
|
// 记录
|
||||||
|
command.name = (this.LastFrameData as any === commands[j].name) ?
|
||||||
|
lastCommand?.name : commands[j].name;
|
||||||
|
|
||||||
command.data = (this.LastFrameData as any === commands[j].data) ?
|
command.data = (this.LastFrameData as any === commands[j].data) ?
|
||||||
lastCommand?.data : new Float32Array(commands[j].data ?? []);
|
lastCommand?.data : new Float32Array(commands[j].data ?? []);
|
||||||
|
|
||||||
|
command.mapId = (this.LastFrameData as any === commands[j].mapId) ?
|
||||||
|
lastCommand?.mapId : commands[j].mapId;
|
||||||
|
|
||||||
command.position = (this.LastFrameData as any === commands[j].position) ?
|
command.position = (this.LastFrameData as any === commands[j].position) ?
|
||||||
lastCommand?.position : commands[j].position;
|
lastCommand?.position : commands[j].position;
|
||||||
|
|
||||||
|
@ -428,6 +428,22 @@ class Group extends CtrlObject<IArchiveGroup> {
|
|||||||
return dataBuffer;
|
return dataBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出个体id列表
|
||||||
|
*/
|
||||||
|
public exportPositionId(idMapper: (id: string) => number ): [Float32Array, number[]] {
|
||||||
|
let bi = 0; let ii = 0;
|
||||||
|
let dataBuffer = new Float32Array(this.individuals.size * 3);
|
||||||
|
let idBUffer: number[] = new Array(this.individuals.size).fill("");
|
||||||
|
this.individuals.forEach((individual) => {
|
||||||
|
idBUffer[ii ++] = idMapper(individual.id);
|
||||||
|
dataBuffer[bi ++] = individual.position[0];
|
||||||
|
dataBuffer[bi ++] = individual.position[1];
|
||||||
|
dataBuffer[bi ++] = individual.position[2];
|
||||||
|
});
|
||||||
|
return [dataBuffer, idBUffer];
|
||||||
|
}
|
||||||
|
|
||||||
public override toArchive(): IArchiveCtrlObject & IArchiveGroup {
|
public override toArchive(): IArchiveCtrlObject & IArchiveGroup {
|
||||||
return {
|
return {
|
||||||
...super.toArchive(),
|
...super.toArchive(),
|
||||||
|
Loading…
Reference in New Issue
Block a user