- {this.getRenderButton({
- iconName: "Save",
- i18NKey: "Command.Bar.Save.Info",
- click: () => {
- this.props.status?.archive.save(this.props.status.model);
- }
- })}
- {this.getRenderButton({
+
+
+
+ {getRenderButton({
iconName: this.props.status?.actuator.start() ? "Pause" : "Play",
i18NKey: "Command.Bar.Play.Info",
click: () => this.props.status ? this.props.status.actuator.start(
!this.props.status.actuator.start()
) : undefined
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "HandsFree", i18NKey: "Command.Bar.Drag.Info",
active: mouseMod === MouseMod.Drag,
click: () => this.props.status ? this.props.status.setMouseMod(MouseMod.Drag) : undefined
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "TouchPointer", i18NKey: "Command.Bar.Select.Info",
active: mouseMod === MouseMod.click,
click: () => this.props.status ? this.props.status.setMouseMod(MouseMod.click) : undefined
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "WebAppBuilderFragmentCreate",
i18NKey: "Command.Bar.Add.Group.Info",
click: () => {
this.props.status ? this.props.status.newGroup() : undefined;
}
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "ProductVariant",
i18NKey: "Command.Bar.Add.Range.Info",
click: () => {
this.props.status ? this.props.status.newRange() : undefined;
}
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "Running",
i18NKey: "Command.Bar.Add.Behavior.Info",
click: () => {
this.props.status?.popup.showPopup(BehaviorPopup, {});
}
})}
- {this.getRenderButton({
+
+ {getRenderButton({
iconName: "Tag",
i18NKey: "Command.Bar.Add.Tag.Info",
click: () => {
this.props.status ? this.props.status.newLabel() : undefined;
}
})}
- {this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
+
+ {getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })}
- {this.getRenderButton({
+ {getRenderButton({
iconName: "Settings",
i18NKey: "Command.Bar.Setting.Info",
click: () => {
@@ -98,25 +147,6 @@ class CommandBar extends Component
}
-
- private getRenderButton(param: {
- i18NKey: AllI18nKeys;
- iconName?: string;
- click?: () => void;
- active?: boolean;
- }): ReactNode {
- return
-
-
- }
}
export { CommandBar };
\ No newline at end of file
diff --git a/source/Component/HeaderBar/HeaderBar.tsx b/source/Component/HeaderBar/HeaderBar.tsx
index 8322029..8009871 100644
--- a/source/Component/HeaderBar/HeaderBar.tsx
+++ b/source/Component/HeaderBar/HeaderBar.tsx
@@ -123,7 +123,7 @@ class HeaderWindowsAction extends Component {
* 头部信息栏
*/
@useSettingWithEvent("language")
-@useStatusWithEvent("fileSave")
+@useStatusWithEvent("fileSave", "fileChange", "fileLoad")
class HeaderBar extends Component {
public render(): ReactNode {
diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx
index 69f0dea..ac88446 100644
--- a/source/Context/Status.tsx
+++ b/source/Context/Status.tsx
@@ -32,6 +32,7 @@ function randomColor(unNormal: boolean = false) {
interface IStatusEvent {
fileSave: void;
fileLoad: void;
+ fileChange: void;
renderLoop: number;
physicsLoop: number;
mouseModChange: void;
@@ -128,11 +129,15 @@ class Status extends Emitter {
this.popup.on("popupChange", () => this.emit("popupChange"));
// 对象变换时执行渲染,更新渲染器数据
- this.on("objectChange", this.delayDraw);
- this.model.on("individualChange", this.delayDraw);
this.model.on("individualChange", () => {
this.emit("individualChange");
});
+
+ // 渲染器重绘
+ this.on("objectChange", this.delayDraw);
+ this.on("individualChange", this.delayDraw);
+ this.on("groupAttrChange", this.delayDraw);
+ this.on("rangeAttrChange", this.delayDraw);
// 当模型中的标签和对象改变时,更新全部行为参数中的受控对象
const updateBehaviorParameter = () => {
@@ -158,7 +163,24 @@ class Status extends Emitter {
// 映射
this.emit("fileLoad");
- })
+ });
+
+
+ // 处理存档事件
+ const handelFileChange = () => {
+ if (this.archive.isSaved) {
+ this.emit("fileChange");
+ }
+ }
+ this.on("objectChange", handelFileChange);
+ this.on("behaviorChange", handelFileChange);
+ this.on("labelChange", handelFileChange);
+ this.on("individualChange", handelFileChange);
+ this.on("groupAttrChange", handelFileChange);
+ this.on("rangeAttrChange", handelFileChange);
+ this.on("labelAttrChange", handelFileChange);
+ this.on("behaviorAttrChange", handelFileChange);
+ this.on("fileChange", () => this.archive.emit("fileChange"));
}
public bindRenderer(renderer: AbstractRenderer) {
@@ -200,7 +222,6 @@ class Status extends Emitter {
if (range && range instanceof Range) {
range[key] = val;
this.emit("rangeAttrChange");
- this.model.draw();
}
}
@@ -213,7 +234,6 @@ class Status extends Emitter {
if (group && group instanceof Group) {
group[key] = val;
this.emit("groupAttrChange");
- this.model.draw();
}
}
diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts
index cba84c0..0fb6cdd 100644
--- a/source/Localization/EN-US.ts
+++ b/source/Localization/EN-US.ts
@@ -4,7 +4,7 @@ const EN_US = {
"Header.Bar.Title": "Living Together | Emulator",
"Header.Bar.Title.Info": "Group Behavior Research Emulator",
"Header.Bar.File.Name.Info": "{file} ({status})",
- "Header.Bar.New.File.Name": "New File",
+ "Header.Bar.New.File.Name": "NewFile.ltss",
"Header.Bar.File.Save.Status.Saved": "Saved",
"Header.Bar.File.Save.Status.Unsaved": "UnSaved",
"Header.Bar.Fps": "FPS: {renderFps} | {physicsFps}",
diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts
index f44fbc4..0933c15 100644
--- a/source/Localization/ZH-CN.ts
+++ b/source/Localization/ZH-CN.ts
@@ -4,7 +4,7 @@ const ZH_CN = {
"Header.Bar.Title": "群生共进 | 仿真器",
"Header.Bar.Title.Info": "群体行为研究仿真器",
"Header.Bar.File.Name.Info": "{file} ({status})",
- "Header.Bar.New.File.Name": "新存档",
+ "Header.Bar.New.File.Name": "新存档.ltss",
"Header.Bar.File.Save.Status.Saved": "已保存",
"Header.Bar.File.Save.Status.Unsaved": "未保存",
"Header.Bar.Fps": "帧率: {renderFps} | {physicsFps}",
diff --git a/source/Model/Archive.ts b/source/Model/Archive.ts
index a0e1f84..edf5577 100644
--- a/source/Model/Archive.ts
+++ b/source/Model/Archive.ts
@@ -12,6 +12,7 @@ import { IArchiveParseFn, IObjectParamArchiveType, IRealObjectType } from "@Mode
interface IArchiveEvent {
fileSave: Archive;
fileLoad: Archive;
+ fileChange: void;
}
interface IArchiveObject {
@@ -243,25 +244,34 @@ class Archive extends Emitter {
* 保存文件
* 模型转换为文件
*/
- public save(model: Model): void {
-
- console.log(this.parseModel2Archive(model));
-
+ public save(model: Model): string {
this.isSaved = true;
this.emit("fileSave", this);
+ return this.parseModel2Archive(model);
}
/**
* 加载文件为模型
* @return Model
*/
- public load(model: Model, data: string) {
-
- this.loadArchiveIntoModel(model, data);
+ public load(model: Model, data: string): string | undefined {
+ try {
+ this.loadArchiveIntoModel(model, data);
+ } catch (e) {
+ return e as string;
+ }
+
this.isSaved = true;
this.emit("fileLoad", this);
};
+
+ public constructor() {
+ super();
+ this.on("fileChange", () => {
+ this.isSaved = false;
+ })
+ }
}
export { Archive };
\ No newline at end of file
diff --git a/source/Page/SimulatorDesktop/SimulatorDesktop.tsx b/source/Page/SimulatorDesktop/SimulatorDesktop.tsx
index 7cb8347..b1f74a7 100644
--- a/source/Page/SimulatorDesktop/SimulatorDesktop.tsx
+++ b/source/Page/SimulatorDesktop/SimulatorDesktop.tsx
@@ -119,8 +119,8 @@ class SimulatorDesktop extends Component {
-
-
+
+
}
diff --git a/source/Page/SimulatorWeb/SimulatorWeb.tsx b/source/Page/SimulatorWeb/SimulatorWeb.tsx
index 44b475d..09fab25 100644
--- a/source/Page/SimulatorWeb/SimulatorWeb.tsx
+++ b/source/Page/SimulatorWeb/SimulatorWeb.tsx
@@ -208,8 +208,8 @@ class SimulatorWeb extends Component {
-
-
+
+
}