Add parameter archive func & Add ctrl object archive function #42
92
package-lock.json
generated
92
package-lock.json
generated
@ -15,13 +15,15 @@
|
|||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^17.0.2",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@atao60/fse-cli": "^0.1.7",
|
"@atao60/fse-cli": "^0.1.7",
|
||||||
"@types/detect-port": "^1.3.2",
|
"@types/detect-port": "^1.3.2",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
"@types/uuid": "^8.3.4",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"css-loader": "^6.5.1",
|
"css-loader": "^6.5.1",
|
||||||
"electron": "^18.0.4",
|
"electron": "^18.0.4",
|
||||||
@ -1273,6 +1275,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz",
|
||||||
@ -1737,9 +1745,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/async": {
|
"node_modules/async": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
|
||||||
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
|
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lodash": "^4.17.14"
|
"lodash": "^4.17.14"
|
||||||
@ -5214,9 +5222,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/node-forge": {
|
"node_modules/node-forge": {
|
||||||
"version": "1.2.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
|
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6.13.0"
|
"node": ">= 6.13.0"
|
||||||
@ -6354,6 +6362,16 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/request/node_modules/uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"uuid": "bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/require-directory": {
|
"node_modules/require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
@ -6937,15 +6955,6 @@
|
|||||||
"websocket-driver": "^0.7.4"
|
"websocket-driver": "^0.7.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sockjs/node_modules/uuid": {
|
|
||||||
"version": "8.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
|
||||||
"uuid": "dist/bin/uuid"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/socks": {
|
"node_modules/socks": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
|
||||||
@ -7628,13 +7637,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "3.4.0",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"uuid": "bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/validate-npm-package-license": {
|
"node_modules/validate-npm-package-license": {
|
||||||
@ -9238,6 +9245,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/ws": {
|
"@types/ws": {
|
||||||
"version": "8.5.0",
|
"version": "8.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz",
|
||||||
@ -9620,9 +9633,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"async": {
|
"async": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
|
||||||
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
|
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lodash": "^4.17.14"
|
"lodash": "^4.17.14"
|
||||||
@ -12326,9 +12339,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "1.2.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||||
"integrity": "sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w==",
|
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node-gyp": {
|
"node-gyp": {
|
||||||
@ -13181,6 +13194,14 @@
|
|||||||
"tough-cookie": "~2.5.0",
|
"tough-cookie": "~2.5.0",
|
||||||
"tunnel-agent": "^0.6.0",
|
"tunnel-agent": "^0.6.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require-directory": {
|
"require-directory": {
|
||||||
@ -13619,14 +13640,6 @@
|
|||||||
"faye-websocket": "^0.11.3",
|
"faye-websocket": "^0.11.3",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"websocket-driver": "^0.7.4"
|
"websocket-driver": "^0.7.4"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"uuid": {
|
|
||||||
"version": "8.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
|
||||||
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"socks": {
|
"socks": {
|
||||||
@ -14161,10 +14174,9 @@
|
|||||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.4.0",
|
"version": "8.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"validate-npm-package-license": {
|
"validate-npm-package-license": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
"@types/detect-port": "^1.3.2",
|
"@types/detect-port": "^1.3.2",
|
||||||
"@types/react": "^17.0.38",
|
"@types/react": "^17.0.38",
|
||||||
"@types/react-dom": "^17.0.11",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
"@types/uuid": "^8.3.4",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"css-loader": "^6.5.1",
|
"css-loader": "^6.5.1",
|
||||||
"electron": "^18.0.4",
|
"electron": "^18.0.4",
|
||||||
@ -72,6 +73,7 @@
|
|||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2"
|
"react-dom": "^17.0.2",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,10 +117,26 @@ class BehaviorPopupComponent extends Component<
|
|||||||
if (this.props.status && recorder instanceof BehaviorRecorder) {
|
if (this.props.status && recorder instanceof BehaviorRecorder) {
|
||||||
let newBehavior = this.props.status.model.addBehavior(recorder);
|
let newBehavior = this.props.status.model.addBehavior(recorder);
|
||||||
|
|
||||||
// 初始化名字
|
// 根据用户的命名搜索下一个名字
|
||||||
newBehavior.name = recorder.getTerms(
|
let searchKey = recorder.getTerms(
|
||||||
recorder.behaviorName, this.props.setting?.language
|
recorder.behaviorName, this.props.setting?.language
|
||||||
) + " " + (recorder.nameIndex - 1).toString();
|
);
|
||||||
|
|
||||||
|
let nextIndex = 1;
|
||||||
|
this.props.status.model.behaviorPool.forEach((obj) => {
|
||||||
|
if (obj.behaviorId === recorder.behaviorId && obj.name.indexOf(searchKey) >= 0) {
|
||||||
|
let searchRes = obj.name.match(/(\d+)$/);
|
||||||
|
if (searchRes) {
|
||||||
|
let nameNumber = parseInt(searchRes[1]);
|
||||||
|
if (!isNaN(nameNumber)) {
|
||||||
|
nextIndex = Math.max(nextIndex, nameNumber + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化名字
|
||||||
|
newBehavior.name = `${searchKey} ${nextIndex}`;
|
||||||
|
|
||||||
// 赋予一个随机颜色
|
// 赋予一个随机颜色
|
||||||
newBehavior.color = randomColor(true);
|
newBehavior.color = randomColor(true);
|
||||||
|
@ -56,12 +56,6 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
|
|
||||||
public setting: Setting = undefined as any;
|
public setting: Setting = undefined as any;
|
||||||
|
|
||||||
/**
|
|
||||||
* 对象命名
|
|
||||||
*/
|
|
||||||
public objectNameIndex = 1;
|
|
||||||
public labelNameIndex = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染器
|
* 渲染器
|
||||||
*/
|
*/
|
||||||
@ -300,34 +294,72 @@ class Status extends Emitter<IStatusEvent> {
|
|||||||
*/
|
*/
|
||||||
public mouseMod: MouseMod = MouseMod.Drag;
|
public mouseMod: MouseMod = MouseMod.Drag;
|
||||||
|
|
||||||
|
private readonly SEARCH_NAME_KEY_REG = /(\d+)$/;
|
||||||
|
private getNextNumber(name: string, searchKey: string): number {
|
||||||
|
if (name.indexOf(searchKey) < 0) return 1;
|
||||||
|
let searchRes = name.match(this.SEARCH_NAME_KEY_REG);
|
||||||
|
if (searchRes) {
|
||||||
|
let nameNumber = parseInt(searchRes[1]);
|
||||||
|
if (isNaN(nameNumber)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return nameNumber + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public newGroup() {
|
public newGroup() {
|
||||||
const group = this.model.addGroup();
|
const group = this.model.addGroup();
|
||||||
group.color = randomColor();
|
group.color = randomColor();
|
||||||
group.displayName = I18N(this.setting.language, "Object.List.New.Group", {
|
let searchKey = I18N(this.setting.language, "Object.List.New.Group", { id: "" });
|
||||||
id: this.objectNameIndex.toString()
|
let nextIndex = 1;
|
||||||
|
this.model.objectPool.forEach((obj) => {
|
||||||
|
if (obj instanceof Group) {
|
||||||
|
nextIndex = Math.max(nextIndex, this.getNextNumber(
|
||||||
|
obj.displayName, searchKey
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
group.displayName = I18N(this.setting.language, "Object.List.New.Group", {
|
||||||
|
id: nextIndex.toString()
|
||||||
});
|
});
|
||||||
this.objectNameIndex ++;
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
public newRange() {
|
public newRange() {
|
||||||
const range = this.model.addRange();
|
const range = this.model.addRange();
|
||||||
range.color = randomColor();
|
range.color = randomColor();
|
||||||
range.displayName = I18N(this.setting.language, "Object.List.New.Range", {
|
let searchKey = I18N(this.setting.language, "Object.List.New.Range", { id: "" });
|
||||||
id: this.objectNameIndex.toString()
|
let nextIndex = 1;
|
||||||
|
this.model.objectPool.forEach((obj) => {
|
||||||
|
if (obj instanceof Range) {
|
||||||
|
nextIndex = Math.max(nextIndex, this.getNextNumber(
|
||||||
|
obj.displayName, searchKey
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
range.displayName = I18N(this.setting.language, "Object.List.New.Range", {
|
||||||
|
id: nextIndex.toString()
|
||||||
});
|
});
|
||||||
this.objectNameIndex ++;
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
public newLabel() {
|
public newLabel() {
|
||||||
|
let searchKey = I18N(this.setting.language, "Object.List.New.Label", { id: "" });
|
||||||
|
let nextIndex = 1;
|
||||||
|
this.model.labelPool.forEach((obj) => {
|
||||||
|
nextIndex = Math.max(nextIndex, this.getNextNumber(
|
||||||
|
obj.name, searchKey
|
||||||
|
));
|
||||||
|
});
|
||||||
const label = this.model.addLabel(
|
const label = this.model.addLabel(
|
||||||
I18N(this.setting.language, "Object.List.New.Label", {
|
I18N(this.setting.language, "Object.List.New.Label", {
|
||||||
id: this.labelNameIndex.toString()
|
id: nextIndex.toString()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
label.color = randomColor(true);
|
label.color = randomColor(true);
|
||||||
this.labelNameIndex ++;
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,6 @@ class Archive<
|
|||||||
*/
|
*/
|
||||||
public save(model: Model): string {
|
public save(model: Model): string {
|
||||||
let fileData: Record<string, any> = {};
|
let fileData: Record<string, any> = {};
|
||||||
|
|
||||||
// 保存 Next ID
|
|
||||||
fileData.idIndex = model.idIndex;
|
|
||||||
|
|
||||||
// 保存对象
|
// 保存对象
|
||||||
fileData.objects = [];
|
fileData.objects = [];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Emitter, EventType } from "@Model/Emitter";
|
import { Emitter, EventType } from "@Model/Emitter";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
import type { Individual } from "@Model/Individual";
|
import type { Individual } from "@Model/Individual";
|
||||||
import type { Group } from "@Model/Group";
|
import type { Group } from "@Model/Group";
|
||||||
import type { Model } from "@Model/Model";
|
import type { Model } from "@Model/Model";
|
||||||
@ -10,7 +11,7 @@ import { getDefaultValue, IParameter, IParameterOption, IParameterValue } from "
|
|||||||
type IBehaviorConstructor<
|
type IBehaviorConstructor<
|
||||||
P extends IParameter = {},
|
P extends IParameter = {},
|
||||||
E extends Record<EventType, any> = {}
|
E extends Record<EventType, any> = {}
|
||||||
> = new (id: string, parameter: IParameterValue<P>) => Behavior<P, E>;
|
> = new (parameter: IParameterValue<P>) => Behavior<P, E>;
|
||||||
|
|
||||||
type IAnyBehavior = Behavior<any, any>;
|
type IAnyBehavior = Behavior<any, any>;
|
||||||
type IAnyBehaviorRecorder = BehaviorRecorder<any, any>;
|
type IAnyBehaviorRecorder = BehaviorRecorder<any, any>;
|
||||||
@ -76,18 +77,6 @@ class BehaviorRecorder<
|
|||||||
E extends Record<EventType, any> = {}
|
E extends Record<EventType, any> = {}
|
||||||
> extends BehaviorInfo<{}> {
|
> extends BehaviorInfo<{}> {
|
||||||
|
|
||||||
/**
|
|
||||||
* 命名序号
|
|
||||||
*/
|
|
||||||
public nameIndex: number = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取下一个 ID
|
|
||||||
*/
|
|
||||||
public getNextId() {
|
|
||||||
return `B-${this.behaviorId}-${this.nameIndex ++}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行为类型
|
* 行为类型
|
||||||
*/
|
*/
|
||||||
@ -107,13 +96,13 @@ class BehaviorRecorder<
|
|||||||
* 创建一个新的行为实例
|
* 创建一个新的行为实例
|
||||||
*/
|
*/
|
||||||
public new(): Behavior<P, E> {
|
public new(): Behavior<P, E> {
|
||||||
return new this.behavior(this.getNextId(), getDefaultValue(this.parameterOption));
|
return new this.behavior(getDefaultValue(this.parameterOption));
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructor(behavior: IBehaviorConstructor<P, E>) {
|
public constructor(behavior: IBehaviorConstructor<P, E>) {
|
||||||
super();
|
super();
|
||||||
this.behavior = behavior;
|
this.behavior = behavior;
|
||||||
this.behaviorInstance = new this.behavior(this.getNextId(), {} as any);
|
this.behaviorInstance = new this.behavior({} as any);
|
||||||
this.parameterOption = this.behaviorInstance.parameterOption;
|
this.parameterOption = this.behaviorInstance.parameterOption;
|
||||||
this.iconName = this.behaviorInstance.iconName;
|
this.iconName = this.behaviorInstance.iconName;
|
||||||
this.behaviorId = this.behaviorInstance.behaviorId;
|
this.behaviorId = this.behaviorInstance.behaviorId;
|
||||||
@ -168,9 +157,9 @@ class Behavior<
|
|||||||
*/
|
*/
|
||||||
public parameterOption: IParameterOption<P> = {} as any;
|
public parameterOption: IParameterOption<P> = {} as any;
|
||||||
|
|
||||||
public constructor(id: string, parameter: IParameterValue<P>) {
|
public constructor(parameter: IParameterValue<P>) {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = uuid();
|
||||||
this.parameter = parameter;
|
this.parameter = parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,23 @@
|
|||||||
import { LabelObject } from "@Model/Label"
|
import { LabelObject } from "@Model/Label"
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
import { parameter2ArchiveObject, archiveObject2Parameter, IArchiveParseFn } from "@Model/Parameter";
|
||||||
import type { IAnyObject, Model } from "@Model/Model";
|
import type { IAnyObject, Model } from "@Model/Model";
|
||||||
import type { ObjectID } from "@Model/Model";
|
import type { ObjectID } from "@Model/Model";
|
||||||
|
|
||||||
|
interface IArchiveCtrlObject {
|
||||||
|
displayName: CtrlObject["displayName"];
|
||||||
|
color: CtrlObject["color"];
|
||||||
|
display: CtrlObject["display"];
|
||||||
|
update: CtrlObject["update"];
|
||||||
|
id: string;
|
||||||
|
renderParameter: any;
|
||||||
|
deleteFlag: CtrlObject["deleteFlag"];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可控对象
|
* 可控对象
|
||||||
*/
|
*/
|
||||||
class CtrlObject extends LabelObject {
|
class CtrlObject<A extends IAnyObject = IAnyObject> extends LabelObject {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示名称
|
* 显示名称
|
||||||
@ -45,10 +57,10 @@ class CtrlObject extends LabelObject {
|
|||||||
/**
|
/**
|
||||||
* 构造器
|
* 构造器
|
||||||
*/
|
*/
|
||||||
public constructor(model: Model, id: ObjectID) {
|
public constructor(model: Model) {
|
||||||
super();
|
super();
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.id = id;
|
this.id = uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,7 +108,30 @@ class CtrlObject extends LabelObject {
|
|||||||
public isDeleted(): boolean {
|
public isDeleted(): boolean {
|
||||||
return this.deleteFlag;
|
return this.deleteFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public toArchive(): IArchiveCtrlObject & A {
|
||||||
|
return {
|
||||||
|
displayName: this.displayName,
|
||||||
|
color: this.color.concat([]),
|
||||||
|
display: !!this.display,
|
||||||
|
update: !!this.update,
|
||||||
|
id: this.id,
|
||||||
|
renderParameter: parameter2ArchiveObject(this.renderParameter),
|
||||||
|
deleteFlag: !!this.deleteFlag
|
||||||
|
} as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
public fromArchive(archive: IArchiveCtrlObject & A, paster?: IArchiveParseFn): void {
|
||||||
|
this.displayName = archive.displayName;
|
||||||
|
this.color = archive.color.concat([]);
|
||||||
|
this.display = !!archive.display;
|
||||||
|
this.update = !!archive.update;
|
||||||
|
this.id = archive.id;
|
||||||
|
this.renderParameter = archiveObject2Parameter(
|
||||||
|
archive.renderParameter, paster ?? (() => undefined)
|
||||||
|
);
|
||||||
|
this.deleteFlag = !!archive.deleteFlag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CtrlObject;
|
export { CtrlObject, IArchiveCtrlObject };
|
||||||
export { CtrlObject };
|
|
@ -407,9 +407,9 @@ class Group extends CtrlObject {
|
|||||||
return dataBuffer;
|
return dataBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructor(model: Model, id: ObjectID) {
|
public constructor(model: Model) {
|
||||||
|
|
||||||
super(model, id);
|
super(model);
|
||||||
|
|
||||||
if (model.renderer) {
|
if (model.renderer) {
|
||||||
this.renderParameter = getDefaultValue(model.renderer.pointsParameterOption);
|
this.renderParameter = getDefaultValue(model.renderer.pointsParameterOption);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import type { Model, ObjectID } from "@Model/Model";
|
import type { Model, ObjectID } from "@Model/Model";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据标签
|
* 数据标签
|
||||||
@ -35,9 +36,9 @@ class Label {
|
|||||||
* @param id 标签 ID
|
* @param id 标签 ID
|
||||||
* @param name 用户定义的名称
|
* @param name 用户定义的名称
|
||||||
*/
|
*/
|
||||||
public constructor(model: Model, id: ObjectID, name?: string) {
|
public constructor(model: Model, name?: string) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.id = id;
|
this.id = uuid();
|
||||||
this.name = name ?? this.name;
|
this.name = name ?? this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,8 @@ import { Label } from "@Model/Label";
|
|||||||
import { Group } from "@Model/Group";
|
import { Group } from "@Model/Group";
|
||||||
import { Range } from "@Model/Range";
|
import { Range } from "@Model/Range";
|
||||||
import { IParamValue } from "@Model/Parameter";
|
import { IParamValue } from "@Model/Parameter";
|
||||||
import { Individual } from "@Model/Individual";
|
|
||||||
import { CtrlObject } from "@Model/CtrlObject";
|
import { CtrlObject } from "@Model/CtrlObject";
|
||||||
import { Emitter, EventType, EventMixin } from "@Model/Emitter";
|
import { Emitter } from "@Model/Emitter";
|
||||||
import { AbstractRenderer } from "@Model/Renderer";
|
import { AbstractRenderer } from "@Model/Renderer";
|
||||||
import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior";
|
import { Behavior, IAnyBehavior, IAnyBehaviorRecorder } from "@Model/Behavior";
|
||||||
|
|
||||||
@ -30,14 +29,6 @@ type ModelEvent = {
|
|||||||
*/
|
*/
|
||||||
class Model extends Emitter<ModelEvent> {
|
class Model extends Emitter<ModelEvent> {
|
||||||
|
|
||||||
/**
|
|
||||||
* 下一个需要分配的 ID
|
|
||||||
*/
|
|
||||||
public idIndex: number = 1;
|
|
||||||
public nextId(label: string = "U"): string {
|
|
||||||
return `${label}-${this.idIndex ++}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象列表
|
* 对象列表
|
||||||
*/
|
*/
|
||||||
@ -75,10 +66,10 @@ class Model extends Emitter<ModelEvent> {
|
|||||||
* 添加标签
|
* 添加标签
|
||||||
*/
|
*/
|
||||||
public addLabel(name: string): Label {
|
public addLabel(name: string): Label {
|
||||||
console.log(`Model: Creat label with id ${this.idIndex}`);
|
let label = new Label(this, name);
|
||||||
let label = new Label(this, this.nextId("L"), name);
|
|
||||||
this.labelPool.push(label);
|
this.labelPool.push(label);
|
||||||
this.emit("labelChange", this.labelPool);
|
this.emit("labelChange", this.labelPool);
|
||||||
|
console.log(`Model: Creat label with id ${label.id}`);
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +131,10 @@ class Model extends Emitter<ModelEvent> {
|
|||||||
* 添加组
|
* 添加组
|
||||||
*/
|
*/
|
||||||
public addGroup(): Group {
|
public addGroup(): Group {
|
||||||
console.log(`Model: Creat group with id ${this.idIndex}`);
|
let group = new Group(this);
|
||||||
let group = new Group(this, this.nextId("G"));
|
|
||||||
this.objectPool.push(group);
|
this.objectPool.push(group);
|
||||||
this.emit("objectChange", this.objectPool);
|
this.emit("objectChange", this.objectPool);
|
||||||
|
console.log(`Model: Creat group with id ${group.id}`);
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,10 +142,10 @@ class Model extends Emitter<ModelEvent> {
|
|||||||
* 添加范围
|
* 添加范围
|
||||||
*/
|
*/
|
||||||
public addRange(): Range {
|
public addRange(): Range {
|
||||||
console.log(`Model: Creat range with id ${this.idIndex}`);
|
let range = new Range(this);
|
||||||
let range = new Range(this, this.nextId("R"));
|
|
||||||
this.objectPool.push(range);
|
this.objectPool.push(range);
|
||||||
this.emit("objectChange", this.objectPool);
|
this.emit("objectChange", this.objectPool);
|
||||||
|
console.log(`Model: Creat range with id ${range.id}`);
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,14 +384,4 @@ class Model extends Emitter<ModelEvent> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { Model, ObjectID, IAnyObject }
|
||||||
Individual,
|
|
||||||
Group,
|
|
||||||
Emitter,
|
|
||||||
EventType,
|
|
||||||
EventMixin,
|
|
||||||
Model,
|
|
||||||
CtrlObject,
|
|
||||||
ObjectID,
|
|
||||||
IAnyObject
|
|
||||||
}
|
|
@ -1,6 +1,12 @@
|
|||||||
import type { Group } from "@Model/Group";
|
import { Group } from "@Model/Group";
|
||||||
import type { Range } from "@Model/Range";
|
import { Range } from "@Model/Range";
|
||||||
import type { Label } from "@Model/Label";
|
import { Label } from "@Model/Label";
|
||||||
|
import { Behavior } from "@Model/Behavior";
|
||||||
|
|
||||||
|
type IObjectParamArchiveType = {
|
||||||
|
__LIVING_TOGETHER_OBJECT_ID: string;
|
||||||
|
__LIVING_TOGETHER_OBJECT_TYPE: string;
|
||||||
|
}
|
||||||
|
|
||||||
type IObjectParamCacheType<P, Q = P> = {
|
type IObjectParamCacheType<P, Q = P> = {
|
||||||
picker: P;
|
picker: P;
|
||||||
@ -26,6 +32,15 @@ type IMapObjectParamTypeKeyToType = {
|
|||||||
"CLG": IObjectParamCacheType<Label | Group | undefined, Group[]>;
|
"CLG": IObjectParamCacheType<Label | Group | undefined, Group[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IMapArchiveObjectParamTypeKeyToType = {
|
||||||
|
"R": IObjectParamCacheType<IObjectParamArchiveType | undefined>;
|
||||||
|
"G": IObjectParamCacheType<IObjectParamArchiveType | undefined>;
|
||||||
|
"LR": IObjectParamCacheType<IObjectParamArchiveType | undefined, IObjectParamArchiveType[]>;
|
||||||
|
"LG": IObjectParamCacheType<IObjectParamArchiveType | undefined, IObjectParamArchiveType[]>;
|
||||||
|
"CG": IObjectParamCacheType<IObjectParamArchiveType | undefined>;
|
||||||
|
"CLG": IObjectParamCacheType<IObjectParamArchiveType | undefined, IObjectParamArchiveType[]>;
|
||||||
|
}
|
||||||
|
|
||||||
type IMapVectorParamTypeKeyToType = {
|
type IMapVectorParamTypeKeyToType = {
|
||||||
"vec": number[];
|
"vec": number[];
|
||||||
"color": number[];
|
"color": number[];
|
||||||
@ -35,30 +50,42 @@ type IMapVectorParamTypeKeyToType = {
|
|||||||
* 参数类型映射
|
* 参数类型映射
|
||||||
*/
|
*/
|
||||||
type AllMapType = IMapBasicParamTypeKeyToType & IMapObjectParamTypeKeyToType & IMapVectorParamTypeKeyToType;
|
type AllMapType = IMapBasicParamTypeKeyToType & IMapObjectParamTypeKeyToType & IMapVectorParamTypeKeyToType;
|
||||||
|
type AllArchiveMapType = IMapBasicParamTypeKeyToType & IMapArchiveObjectParamTypeKeyToType & IMapVectorParamTypeKeyToType;
|
||||||
type IParamType = keyof AllMapType;
|
type IParamType = keyof AllMapType;
|
||||||
type IObjectType = keyof IMapObjectParamTypeKeyToType;
|
type IObjectType = keyof IMapObjectParamTypeKeyToType;
|
||||||
type IVectorType = keyof IMapVectorParamTypeKeyToType;
|
type IVectorType = keyof IMapVectorParamTypeKeyToType;
|
||||||
type IParamValue<K extends IParamType> = AllMapType[K];
|
type IParamValue<K extends IParamType> = AllMapType[K];
|
||||||
|
type IArchiveParamValue<K extends IParamType> = AllArchiveMapType[K];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 特殊对象类型判定
|
* 特殊对象类型判定
|
||||||
*/
|
*/
|
||||||
const objectTypeListEnumSet = new Set<string>(["R", "G", "LR", "LG", "CG", "CLG"]);
|
const objectTypeListEnumSet = new Set<string>(["R", "G", "LR", "LG", "CG", "CLG"]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象断言表达式
|
* 对象断言表达式
|
||||||
*/
|
*/
|
||||||
function isObjectType(key: string): key is IVectorType {
|
function isObjectType(key: string): key is IVectorType {
|
||||||
return objectTypeListEnumSet.has(key);
|
return objectTypeListEnumSet.has(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向量断言表达式
|
* 向量断言表达式
|
||||||
*/
|
*/
|
||||||
function isVectorType(key: string): key is IObjectType {
|
function isVectorType(key: string): key is IObjectType {
|
||||||
return key === "vec";
|
return key === "vec";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 压缩对象断言表达式
|
||||||
|
*/
|
||||||
|
function isArchiveObjectType(key: Object): key is IObjectParamArchiveType {
|
||||||
|
return !!(
|
||||||
|
(key as IObjectParamArchiveType).__LIVING_TOGETHER_OBJECT_ID &&
|
||||||
|
(key as IObjectParamArchiveType).__LIVING_TOGETHER_OBJECT_TYPE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模型参数类型
|
* 模型参数类型
|
||||||
*/
|
*/
|
||||||
@ -144,6 +171,10 @@ type IParameterValue<P extends IParameter> = {
|
|||||||
[X in keyof P]: IParamValue<P[X]>
|
[X in keyof P]: IParamValue<P[X]>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IArchiveParameterValue<P extends IParameter> = {
|
||||||
|
[X in keyof P]: IArchiveParamValue<P[X]>
|
||||||
|
}
|
||||||
|
|
||||||
function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IParameterValue<P> {
|
function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IParameterValue<P> {
|
||||||
let defaultObj = {} as IParameterValue<P>;
|
let defaultObj = {} as IParameterValue<P>;
|
||||||
for (let key in option) {
|
for (let key in option) {
|
||||||
@ -193,7 +224,132 @@ function getDefaultValue<P extends IParameter> (option: IParameterOption<P>): IP
|
|||||||
return defaultObj;
|
return defaultObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IRealObjectType = Range | Group | Label | Behavior;
|
||||||
|
type IArchiveParseFn = (archive: IObjectParamArchiveType) => IRealObjectType | undefined;
|
||||||
|
|
||||||
|
function object2ArchiveObject(object: IRealObjectType | IRealObjectType[] | any, testArray: boolean = true):
|
||||||
|
IObjectParamArchiveType | IObjectParamArchiveType[] | undefined {
|
||||||
|
if (object instanceof Range) {
|
||||||
|
return {
|
||||||
|
__LIVING_TOGETHER_OBJECT_ID: "Range",
|
||||||
|
__LIVING_TOGETHER_OBJECT_TYPE: object.id
|
||||||
|
}
|
||||||
|
} else if (object instanceof Group) {
|
||||||
|
return {
|
||||||
|
__LIVING_TOGETHER_OBJECT_ID: "Group",
|
||||||
|
__LIVING_TOGETHER_OBJECT_TYPE: object.id
|
||||||
|
}
|
||||||
|
} else if (object instanceof Label) {
|
||||||
|
return {
|
||||||
|
__LIVING_TOGETHER_OBJECT_ID: "Label",
|
||||||
|
__LIVING_TOGETHER_OBJECT_TYPE: object.id
|
||||||
|
}
|
||||||
|
} else if (object instanceof Behavior) {
|
||||||
|
return {
|
||||||
|
__LIVING_TOGETHER_OBJECT_ID: "Behavior",
|
||||||
|
__LIVING_TOGETHER_OBJECT_TYPE: object.id
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(object) && testArray) {
|
||||||
|
const hasValue = (item: any): item is IObjectParamArchiveType => !!item;
|
||||||
|
return object.map(item => object2ArchiveObject(item, false)).filter(hasValue);
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parameter2ArchiveObject<P extends IParameter>
|
||||||
|
(value: IParameterValue<P>, option?: IParameterOption<P>): IArchiveParameterValue<P> {
|
||||||
|
let archive = {} as IArchiveParameterValue<P>;
|
||||||
|
|
||||||
|
const handelColl = (key: string, cValue: IParamValue<IParamType>) => {
|
||||||
|
|
||||||
|
// 处理对象类型
|
||||||
|
if (cValue instanceof Object && !Array.isArray(cValue)) {
|
||||||
|
const picker = (cValue as IObjectParamCacheType<any>).picker;
|
||||||
|
const objects = (cValue as IObjectParamCacheType<any>).objects;
|
||||||
|
|
||||||
|
(archive[key] as any) = {
|
||||||
|
picker: object2ArchiveObject(picker),
|
||||||
|
objects: object2ArchiveObject(objects)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数组类型
|
||||||
|
else if (Array.isArray(cValue)) {
|
||||||
|
(archive[key] as any) = cValue.concat([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数值
|
||||||
|
else {
|
||||||
|
(archive[key] as any) = cValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存在参考设置对象
|
||||||
|
if (option) {
|
||||||
|
for (const key in option) {
|
||||||
|
handelColl(key, value[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不存在设置对象
|
||||||
|
else {
|
||||||
|
for (const key in value) {
|
||||||
|
handelColl(key, value[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return archive;
|
||||||
|
}
|
||||||
|
|
||||||
|
function archiveObject2Parameter<P extends IParameter>
|
||||||
|
(value: IArchiveParameterValue<P>, parse: IArchiveParseFn, option?: IParameterOption<P>): IParameterValue<P> {
|
||||||
|
let parameter = {} as IParameterValue<P>;
|
||||||
|
|
||||||
|
const handelColl = (key: string, cValue: IArchiveParamValue<IParamType>) => {
|
||||||
|
|
||||||
|
// 处理对象类型
|
||||||
|
if (cValue instanceof Object && !Array.isArray(cValue)) {
|
||||||
|
const picker = (cValue as IObjectParamCacheType<IObjectParamArchiveType>).picker;
|
||||||
|
const objects = (cValue as IObjectParamCacheType<IObjectParamArchiveType>).objects;
|
||||||
|
|
||||||
|
(parameter[key] as any) = {
|
||||||
|
picker: picker ? parse(picker) : picker,
|
||||||
|
objects: objects ? parse(objects) : objects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数组类型
|
||||||
|
else if (Array.isArray(cValue)) {
|
||||||
|
(parameter[key] as any) = cValue.concat([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理数值
|
||||||
|
else {
|
||||||
|
(parameter[key] as any) = cValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存在参考设置对象
|
||||||
|
if (option) {
|
||||||
|
for (const key in option) {
|
||||||
|
handelColl(key, value[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不存在设置对象
|
||||||
|
else {
|
||||||
|
for (const key in value) {
|
||||||
|
handelColl(key, value[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
IParamType, IParamValue, isObjectType, isVectorType, getDefaultValue,
|
IParamType, IParamValue, isObjectType, isVectorType, getDefaultValue,
|
||||||
IParameterOptionItem, IParameter, IParameterOption, IParameterValue
|
IParameterOptionItem, IParameter, IParameterOption, IParameterValue,
|
||||||
|
object2ArchiveObject, parameter2ArchiveObject, archiveObject2Parameter,
|
||||||
|
IArchiveParseFn
|
||||||
}
|
}
|
@ -1,11 +1,16 @@
|
|||||||
import { CtrlObject } from "@Model/CtrlObject";
|
import { CtrlObject, IArchiveCtrlObject } from "@Model/CtrlObject";
|
||||||
import { Model, ObjectID } from "@Model/Model";
|
import { Model } from "@Model/Model";
|
||||||
import { getDefaultValue } from "@Model/Parameter";
|
import { getDefaultValue, IArchiveParseFn, parameter2ArchiveObject } from "@Model/Parameter";
|
||||||
|
|
||||||
|
interface IArchiveRange {
|
||||||
|
position: Range["position"];
|
||||||
|
radius: Range["radius"];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 范围
|
* 范围
|
||||||
*/
|
*/
|
||||||
class Range extends CtrlObject {
|
class Range extends CtrlObject<IArchiveRange> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 坐标
|
* 坐标
|
||||||
@ -17,16 +22,29 @@ class Range extends CtrlObject {
|
|||||||
*/
|
*/
|
||||||
public radius: number[] = [1, 1, 1];
|
public radius: number[] = [1, 1, 1];
|
||||||
|
|
||||||
public constructor(model: Model, id: ObjectID) {
|
public constructor(model: Model) {
|
||||||
|
|
||||||
super(model, id);
|
super(model);
|
||||||
|
|
||||||
if (model.renderer) {
|
if (model.renderer) {
|
||||||
this.renderParameter = getDefaultValue(model.renderer.cubeParameterOption);
|
this.renderParameter = getDefaultValue(model.renderer.cubeParameterOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override toArchive(): IArchiveCtrlObject & IArchiveRange {
|
||||||
|
return {
|
||||||
|
...super.toArchive(),
|
||||||
|
position: this.position.concat([]),
|
||||||
|
radius: this.radius.concat([])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fromArchive(archive: IArchiveCtrlObject & IArchiveRange, paster?: IArchiveParseFn): void {
|
||||||
|
super.fromArchive(archive, paster);
|
||||||
|
this.position = archive.position.concat([]),
|
||||||
|
this.radius = archive.radius.concat([])
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Range;
|
export { Range, IArchiveRange };
|
||||||
export { Range };
|
|
@ -153,7 +153,10 @@ class SimulatorWeb extends Component {
|
|||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
(window as any).s = this;
|
(window as any).LT = {
|
||||||
|
status: this.status,
|
||||||
|
setting: this.setting
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
|
@ -4,6 +4,8 @@ import { useSetting, IMixinSettingProps } from "@Context/Setting";
|
|||||||
import { Localization } from "@Component/Localization/Localization";
|
import { Localization } from "@Component/Localization/Localization";
|
||||||
import { DetailsList } from "@Component/DetailsList/DetailsList";
|
import { DetailsList } from "@Component/DetailsList/DetailsList";
|
||||||
import { ObjectID } from "@Model/Model";
|
import { ObjectID } from "@Model/Model";
|
||||||
|
import { Group } from "@Model/Group";
|
||||||
|
import { Range } from "@Model/Range";
|
||||||
import { Icon } from "@fluentui/react";
|
import { Icon } from "@fluentui/react";
|
||||||
import "./ObjectList.scss";
|
import "./ObjectList.scss";
|
||||||
|
|
||||||
@ -24,12 +26,21 @@ class ObjectList extends Component<IMixinStatusProps & IMixinSettingProps> {
|
|||||||
return <DetailsList
|
return <DetailsList
|
||||||
className="object-list"
|
className="object-list"
|
||||||
items={objList.concat([]).map((object => {
|
items={objList.concat([]).map((object => {
|
||||||
|
|
||||||
|
let objectType = "";
|
||||||
|
if (object instanceof Group) {
|
||||||
|
objectType = "G";
|
||||||
|
} else if (object instanceof Range) {
|
||||||
|
objectType = "R";
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: object.id.toString(),
|
key: object.id.toString(),
|
||||||
name: object.displayName,
|
name: object.displayName,
|
||||||
color: object.color,
|
color: object.color,
|
||||||
display: object.display,
|
display: object.display,
|
||||||
update: object.update,
|
update: object.update,
|
||||||
|
type: objectType,
|
||||||
select: this.props.status ?
|
select: this.props.status ?
|
||||||
this.props.status.focusObject.has(object.id.toString()) ||
|
this.props.status.focusObject.has(object.id.toString()) ||
|
||||||
this.props.status.focusObject.has(object.id) :
|
this.props.status.focusObject.has(object.id) :
|
||||||
@ -41,10 +52,10 @@ class ObjectList extends Component<IMixinStatusProps & IMixinSettingProps> {
|
|||||||
this.props.status.setFocusObject(new Set<ObjectID>().add(item.key));
|
this.props.status.setFocusObject(new Set<ObjectID>().add(item.key));
|
||||||
}
|
}
|
||||||
if (this.props.setting) {
|
if (this.props.setting) {
|
||||||
if (item.key.slice(0, 1) === "R") {
|
if (item.type === "R") {
|
||||||
this.props.setting.layout.focus("RangeDetails");
|
this.props.setting.layout.focus("RangeDetails");
|
||||||
}
|
}
|
||||||
if (item.key.slice(0, 1) === "G") {
|
else if (item.type === "G") {
|
||||||
this.props.setting.layout.focus("GroupDetails");
|
this.props.setting.layout.focus("GroupDetails");
|
||||||
}
|
}
|
||||||
this.props.setting.layout.focus("ObjectList");
|
this.props.setting.layout.focus("ObjectList");
|
||||||
@ -71,13 +82,13 @@ class ObjectList extends Component<IMixinStatusProps & IMixinSettingProps> {
|
|||||||
}}
|
}}
|
||||||
renderCheckbox={(item, click) => {
|
renderCheckbox={(item, click) => {
|
||||||
let icon = "CheckMark";
|
let icon = "CheckMark";
|
||||||
if (item.key.slice(0, 1) === "R") {
|
if (item.type === "R") {
|
||||||
icon = "CubeShape";
|
icon = "CubeShape";
|
||||||
}
|
}
|
||||||
if (item.key.slice(0, 1) === "G") {
|
else if (item.type === "G") {
|
||||||
icon = "WebAppBuilderFragment";
|
icon = "WebAppBuilderFragment";
|
||||||
}
|
}
|
||||||
return <div
|
return <div
|
||||||
className="object-list-checkbox details-list-checkbox"
|
className="object-list-checkbox details-list-checkbox"
|
||||||
onClick={click}
|
onClick={click}
|
||||||
>
|
>
|
||||||
|
Loading…
Reference in New Issue
Block a user