diff --git a/app/main.ts b/app/main.ts
index 7f9f75d..0668026 100644
--- a/app/main.ts
+++ b/app/main.ts
@@ -57,7 +57,7 @@ function createWindow(): BrowserWindow {
{
label: "Gamesystem",
click: () => {
- win!.webContents.send('context-menu', "new-location");
+ win!.webContents.send('context-menu', "new-gamesystem");
}
},
{
diff --git a/e2e/game-model/gamesystems/CreateGamesystem.spec.ts b/e2e/game-model/gamesystems/CreateGamesystem.spec.ts
new file mode 100644
index 0000000..84e01c5
--- /dev/null
+++ b/e2e/game-model/gamesystems/CreateGamesystem.spec.ts
@@ -0,0 +1,53 @@
+import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
+import { test, expect } from '@playwright/test';
+import * as PATH from 'path';
+import {GameModel} from "../../../src/app/game-model/GameModel";
+import {Gamesystem} from "../../src/app/game-model/gamesystems/Gamesystem";
+import {ScriptAccount} from "../../../src/app/game-model/scriptAccounts/ScriptAccount";
+import {ModelComponentType} from "../../../src/app/game-model/ModelComponentType";
+import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
+import exp = require("node:constants");
+import {end} from "electron-debug";
+import {GamesystemTrainer} from "./GamesystemTrainer";
+import {ProductGamesystem} from "../../../src/app/game-model/gamesystems/ProductGamesystem";
+test.describe('Test Create Gamesystems', () => {
+
+ test('Test creating gamesystem with invalid name', async => {
+ const gameModel = GamesystemTrainer.givenEmptyGameModel();
+ let result = gameModel.createGamesystem(undefined, undefined);
+ expect(result).toBeUndefined();
+
+ result = gameModel.createGamesystem(null, undefined);
+ expect(result).toBeUndefined();
+ })
+
+ test("Test creating gamesystem with valid name but without parent", async => {
+ const gameModel = GamesystemTrainer.givenEmptyGameModel();
+ let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME, undefined);
+ expect(result).toBeDefined();
+ expect(gameModel.gamesystems.length).toEqual(1);
+ expect(gameModel.findGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME)).toBeDefined();
+ })
+
+ test("Test creating Gamesystem with valid name but with Product Parent", async => {
+ const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer();
+ let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEM_LEAF_LEFT, GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME);
+ expect(result).toBeDefined();
+ expect(result.parentGamesystem!.componentName).toEqual(GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME);
+ expect(result.parentGamesystem!.innerGamesystems.length).toEqual(3);
+ expect(result.parentGamesystem!.innerGamesystems.includes(result)).toBeTruthy();
+ })
+
+ test("Test creating Gamesystem with valid name but with Simple Parent", async() => {
+ const gameModel = GamesystemTrainer.givenGameModelWithSimpleGamesystemOnTopLayer();
+ let result = gameModel.createGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEM_LEAF_LEFT, GamesystemTrainer.SIMPLEGAMESYSTEMNAME);
+ expect(result).toBeDefined();
+ expect(gameModel.gamesystems.length).toEqual(1);
+ expect(gameModel.gamesystems[0]).toBeInstanceOf(ProductGamesystem);
+ expect(gameModel.gamesystems[0]).toEqual(result.parentGamesystem);
+ expect((gameModel.gamesystems[0] as ProductGamesystem).innerGamesystems.length).toEqual(1);
+ expect((gameModel.gamesystems[0] as ProductGamesystem).innerGamesystems.includes(result)).toBeTruthy();
+ })
+
+
+});
diff --git a/e2e/game-model/gamesystems/FindGamesystem.spec.ts b/e2e/game-model/gamesystems/FindGamesystem.spec.ts
new file mode 100644
index 0000000..879717b
--- /dev/null
+++ b/e2e/game-model/gamesystems/FindGamesystem.spec.ts
@@ -0,0 +1,50 @@
+import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
+import { test, expect } from '@playwright/test';
+import * as PATH from 'path';
+import {GameModel} from "../../../src/app/game-model/GameModel";
+import {Gamesystem} from "../../src/app/game-model/gamesystems/Gamesystem";
+import {ScriptAccount} from "../../../src/app/game-model/scriptAccounts/ScriptAccount";
+import {ModelComponentType} from "../../../src/app/game-model/ModelComponentType";
+import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
+import exp = require("node:constants");
+import {end} from "electron-debug";
+import {GamesystemTrainer} from "./GamesystemTrainer";
+test.describe('Test Find Gamesystems', () => {
+ const GAMEMODELNAME: string = "GameModel";
+ const SIMPLEGAMESYSTEM_NAME: string = "Simple Gamesystem";
+
+
+ test('Find null or undefined Gamesystem', async () => {
+ const gameModel = new GameModel(GAMEMODELNAME);
+ expect(gameModel.findGamesystem(null)).toBeUndefined();
+ expect(gameModel.findGamesystem(undefined)).toBeUndefined();
+ })
+
+ test('Find non existend Gamesystem', async () => {
+ const gameModel = new GameModel(GAMEMODELNAME);
+ expect(gameModel.findGamesystem("Gamesystem")).toBeUndefined();
+ })
+
+ test("Find existend simple Gamesystem on top layer", async () => {
+ const gameModel = new GameModel(GAMEMODELNAME);
+ const gamesystem = new SimpleGamesystem(SIMPLEGAMESYSTEM_NAME);
+ gameModel.addGamesystem(gamesystem);
+
+ expect(gameModel.findGamesystem(SIMPLEGAMESYSTEM_NAME)).toBeDefined();
+ expect(gameModel.findGamesystem(SIMPLEGAMESYSTEM_NAME)).toEqual(gamesystem);
+ })
+
+ test('Find existent product gamesystem on top layer', async () => {
+ const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer();
+ const result = gameModel.findGamesystem(GamesystemTrainer.TOP_PRODUCT_GAMESYSTEM_NAME);
+ expect(result).toBeDefined();
+
+ })
+
+ test('Find existent simple gamesystem on lower layer', async () => {
+ const gameModel = GamesystemTrainer.givenGameModelWithProductGamesytemOnTopLayer();
+ const result = gameModel.findGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME);
+ expect(result).toBeDefined();
+
+ })
+});
diff --git a/e2e/game-model/gamesystems/GamesystemTrainer.ts b/e2e/game-model/gamesystems/GamesystemTrainer.ts
new file mode 100644
index 0000000..515882e
--- /dev/null
+++ b/e2e/game-model/gamesystems/GamesystemTrainer.ts
@@ -0,0 +1,55 @@
+import {GameModel} from "../../../src/app/game-model/GameModel";
+import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
+import {ProductGamesystem} from "../../../src/app/game-model/gamesystems/ProductGamesystem";
+
+export class GamesystemTrainer {
+
+ static GAMEMODELNAME: string = "GAMEMODEL";
+ static SIMPLEGAMESYSTEMNAME: string = "SIMPLE GAMESYSTEM";
+ static TOP_PRODUCT_GAMESYSTEM_NAME: string = "Top Product Gamesystem"
+
+ static SIMPLEGAMESYSTEM2: string = "Simple Gamesystem Leaf 2";
+ static SIMPLEGAMESYSTEM_LEAF_LEFT: string = "Leaf Gamesystem Left"
+ static SIMPLEGAMESYSTEM_LEAF_RIGHT: string = "Leaf Gamesystem Right";
+
+ static givenEmptyGameModel() {
+ return new GameModel(GamesystemTrainer.GAMEMODELNAME);
+ }
+
+ static givenGameModelWithSimpleGamesystemOnTopLayer() {
+ const gameModel = new GameModel(GamesystemTrainer.GAMEMODELNAME);
+ const gamesytem = new SimpleGamesystem(GamesystemTrainer.SIMPLEGAMESYSTEMNAME);
+ gameModel.addGamesystem(gamesytem);
+
+ return gameModel;
+ }
+
+ static givenGameModelWithProductGamesytemOnTopLayer() {
+ const gameModel = new GameModel(GamesystemTrainer.GAMEMODELNAME);
+ const productGamesystem = new ProductGamesystem(this.TOP_PRODUCT_GAMESYSTEM_NAME);
+ const leaf1 = new SimpleGamesystem(this.SIMPLEGAMESYSTEMNAME);
+ const leaf2 = new SimpleGamesystem(this.SIMPLEGAMESYSTEM2);
+ productGamesystem.innerGamesystems.push(leaf1);
+ productGamesystem.innerGamesystems.push(leaf2);
+ gameModel.addGamesystem(productGamesystem);
+
+ return gameModel;
+ }
+
+ static givenGameModelWithProductGamesystemOnLowerLayer() {
+ const gameModel = new GameModel(GamesystemTrainer.GAMEMODELNAME);
+ const top_productGamesystem = new ProductGamesystem(this.TOP_PRODUCT_GAMESYSTEM_NAME);
+ const leaf1 = new ProductGamesystem(this.SIMPLEGAMESYSTEMNAME);
+ const leaf2 = new SimpleGamesystem(this.SIMPLEGAMESYSTEM2);
+ top_productGamesystem.innerGamesystems.push(leaf1);
+ top_productGamesystem.innerGamesystems.push(leaf2);
+ gameModel.addGamesystem(top_productGamesystem);
+
+ const leaf_1_1 = new SimpleGamesystem(this.SIMPLEGAMESYSTEM_LEAF_LEFT);
+ leaf1.addChildGamesystem(leaf_1_1);
+ const leaf_1_2 = new SimpleGamesystem(this.SIMPLEGAMESYSTEM_LEAF_RIGHT);
+ leaf1.addChildGamesystem(leaf_1_2);
+ }
+
+
+}
diff --git a/e2e/game-model/gamesystems/SimpleGamesystem.spec.ts b/e2e/game-model/gamesystems/SimpleGamesystem.spec.ts
new file mode 100644
index 0000000..4c61efd
--- /dev/null
+++ b/e2e/game-model/gamesystems/SimpleGamesystem.spec.ts
@@ -0,0 +1,172 @@
+import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
+import { test, expect } from '@playwright/test';
+import * as PATH from 'path';
+import {GameModel} from "../../../src/app/game-model/GameModel";
+import {Gamesystem} from "../../src/app/game-model/gamesystems/Gamesystem";
+import {ScriptAccount} from "../../../src/app/game-model/scriptAccounts/ScriptAccount";
+import {ModelComponentType} from "../../../src/app/game-model/ModelComponentType";
+import {SimpleGamesystem} from "../../../src/app/game-model/gamesystems/SimpleGamesystem";
+import exp = require("node:constants");
+import {end} from "electron-debug";
+
+test.describe('Test SimpleGamesystem', () => {
+
+ test("Create SimpleState", async () => {
+ const gamesystem = new SimpleGamesystem();
+ let state = gamesystem.createState("Test", "Test2");
+ expect(state.stateLabel).toEqual("Test");
+ expect(state.stateDescription).toEqual("Test2");
+ expect(state.incomingTransitions.length).toEqual(0);
+ expect(state.outgoingTransitions.length).toEqual(0);
+ expect(gamesystem.states.includes(state)).toBeTruthy();
+
+ state = gamesystem.createState(null, null);
+ expect(state).toBeUndefined();
+ expect(gamesystem.states.includes(state)).toBeFalsy();
+
+ state = gamesystem.createState(null, "test2");
+ expect(state).toBeUndefined()
+ expect(gamesystem.states.includes(state)).toBeFalsy();
+
+ state = gamesystem.createState("test2", null);
+ expect(state).toBeDefined();
+ expect(state.stateLabel).toEqual("test2");
+ expect(state.stateDescription).toEqual("");
+ expect(gamesystem.states.includes(state)).toBeTruthy();
+
+ state = gamesystem.createState(undefined, "State");
+ expect(state).toBeUndefined();
+ expect(gamesystem.states.includes(state)).toBeFalsy();
+
+ state = gamesystem.createState("Test3", undefined);
+ expect(state).toBeDefined();
+ expect(state.stateLabel).toEqual("Test3");
+ expect(state.stateDescription).toEqual("");
+ expect(gamesystem.states.includes(state)).toBeTruthy();
+
+ state = gamesystem.createState("", "");
+ expect(state).toBeDefined();
+ expect(state.stateLabel).toEqual("");
+ expect(state.stateDescription).toEqual("");
+ expect(gamesystem.states.includes(state)).toBeTruthy();
+
+ state = gamesystem.createState("Test3", "");
+ expect(state).toBeUndefined();
+ expect(gamesystem.states.includes(state)).toBeFalsy();
+ })
+
+ test("Create SimpleTransition", async () => {
+ const gamesystem = new SimpleGamesystem();
+ const startingState = gamesystem.createState("StartingState", "")!;
+ const endingState = gamesystem.createState("EndingState", "")!
+
+ let transition = gamesystem.createTransition(startingState, endingState);
+ expect(transition).toBeDefined();
+ expect(transition.startingState).toEqual(startingState);
+ expect(transition.endingState).toEqual(endingState);
+ expect(startingState.outgoingTransitions.includes(transition)).toBeTruthy();
+ expect(endingState.incomingTransitions.includes(transition)).toBeTruthy();
+ expect(gamesystem.transitions.includes(transition)).toBeTruthy();
+
+ transition = gamesystem.createTransition(null, null);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(null, endingState);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(undefined, undefined);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(undefined, endingState);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(startingState, null);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(startingState, undefined);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(startingState, startingState);
+ expect(transition).toBeUndefined();
+
+ transition = gamesystem.createTransition(startingState, endingState);
+ expect(transition).toBeUndefined();
+
+ })
+
+ test("Remove SimpleState", async () => {
+ const gamesystem = new SimpleGamesystem("Test");
+ const state1 = gamesystem.createState("State1", "");
+
+ const state1_delete = gamesystem.removeState(state1);
+ expect(state1_delete).toBeTruthy();
+ expect(gamesystem.states.includes(state1)).toBeFalsy();
+
+ let startingState = gamesystem.createState("Start", "End");
+ let endingState = gamesystem.createState("End", "");
+ let transition = gamesystem.createTransition(startingState, endingState);
+ let result = gamesystem.removeState(startingState);
+ expect(result).toBeTruthy();
+ expect(gamesystem.states.includes(startingState)).toBeFalsy();
+ expect(gamesystem.states.includes(endingState)).toBeTruthy();
+ expect(gamesystem.transitions.length).toEqual(0);
+
+ startingState = gamesystem.createState("Start");
+ transition = gamesystem.createTransition(startingState, endingState);
+ gamesystem.removeState(endingState);
+ expect(result).toBeTruthy();
+ expect(gamesystem.states.includes(startingState)).toBeTruthy();
+ expect(gamesystem.states.includes(endingState)).toBeFalsy();
+ expect(gamesystem.transitions.length).toEqual(0);
+
+ endingState = gamesystem.createState("End");
+ transition = gamesystem.createTransition(startingState, endingState);
+ const testingState = gamesystem.createState("TestingState", "");
+ result = gamesystem.removeState(testingState);
+ expect(result).toBeTruthy();
+ expect(gamesystem.transitions.includes(transition)).toBeTruthy();
+
+ const gamesystem2 = new SimpleGamesystem("test2");
+ const state2 = gamesystem2.createState("Test", "");
+ result = gamesystem.removeState(state2);
+ expect(result).toBeFalsy();
+
+ result = gamesystem.removeState(null);
+ expect(result).toBeFalsy();
+
+ result = gamesystem.removeState(undefined);
+ expect(result).toBeFalsy();
+ })
+
+ test("Remove SimpleTransition", async () => {
+ const gamesystem = new SimpleGamesystem("Gamesystem");
+ const A = gamesystem.createState("A");
+ const B = gamesystem.createState("B");
+ let AB = gamesystem.createTransition(A, B);
+
+ let result = gamesystem.removeTransition(AB);
+ expect(result).toBeTruthy();
+ expect(gamesystem.transitions.includes(AB)).toBeFalsy();
+
+ AB = gamesystem.createTransition(A, B);
+ const C = gamesystem.createState("C");
+ const D = gamesystem.createState("D");
+ let CD = gamesystem.createTransition(C, D);
+
+ result = gamesystem.removeTransition(AB);
+ expect(result).toBeTruthy();
+ expect(gamesystem.transitions.includes(AB)).toBeFalsy();
+ expect(gamesystem.transitions.includes(CD)).toBeTruthy();
+
+ let BA = gamesystem.createTransition(B, A);
+ AB = gamesystem.createTransition(A, B);
+ result = gamesystem.removeTransition(AB);
+ expect(result).toBeTruthy();
+ expect(gamesystem.transitions.includes(AB)).toBeFalsy();
+ expect(gamesystem.transitions.includes(BA)).toBeTruthy();
+
+ result = gamesystem.removeTransition(AB);
+ expect(result).toBeFalsy();
+
+ })
+});
diff --git a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts
index c7eb65b..00688ac 100644
--- a/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts
+++ b/e2e/game-model/scriptAccounts/ScriptAccountTest.spec.ts
@@ -21,24 +21,24 @@ test.describe('Test ScriptAccounts', () => {
test("Test Adding ScriptAccounts", async () => {
const gameModel: GameModel = new GameModel("GameModel");
- let scriptAccount =gameModel.addScriptAccount("ScriptAccount");
+ let scriptAccount =gameModel.createScriptAccount("ScriptAccount");
expect(scriptAccount).toBeDefined();
expect(gameModel.scriptAccounts.length).toEqual(1);
expect(gameModel.scriptAccounts.includes(scriptAccount)).toBeTruthy();
//Test adding scriptAccount with already existing name
- const scriptAccount2 = gameModel.addScriptAccount("ScriptAccount")
+ const scriptAccount2 = gameModel.createScriptAccount("ScriptAccount")
expect(scriptAccount2).toBeUndefined();
expect(gameModel.scriptAccounts.length).toEqual(1);
//Test for adding invalid names as scriptaccount names (null/undefined/empty)
- let result = gameModel.addScriptAccount(null);
+ let result = gameModel.createScriptAccount(null);
expect(result).toBeUndefined();
expect(gameModel.scriptAccounts.length).toEqual(1);
- result = gameModel.addScriptAccount(undefined);
+ result = gameModel.createScriptAccount(undefined);
expect(result).toBeUndefined();
expect(gameModel.scriptAccounts.length).toEqual(1);
- result = gameModel.addScriptAccount("");
+ result = gameModel.createScriptAccount("");
expect(result).toBeUndefined();
expect(gameModel.scriptAccounts.length).toEqual(1);
})
@@ -50,7 +50,7 @@ test.describe('Test ScriptAccounts', () => {
gameModel.removeScriptAccount(scriptAccount);
expect(gameModel.scriptAccounts.length).toEqual(0);
- scriptAccount = gameModel.addScriptAccount("ScriptAccount");
+ scriptAccount = gameModel.createScriptAccount("ScriptAccount");
gameModel.removeScriptAccount(scriptAccount);
expect(gameModel.scriptAccounts.length).toEqual(0);
@@ -60,8 +60,8 @@ test.describe('Test ScriptAccounts', () => {
gameModel.removeScriptAccount(null);
expect(gameModel.scriptAccounts.length).toEqual(0);
- scriptAccount = gameModel.addScriptAccount(scriptAccount);
- let scriptAccount2 = gameModel.addScriptAccount("ScriptAccount 2");
+ scriptAccount = gameModel.createScriptAccount(scriptAccount);
+ let scriptAccount2 = gameModel.createScriptAccount("ScriptAccount 2");
gameModel.removeScriptAccount(scriptAccount);
expect(gameModel.scriptAccounts.length).toEqual(1);
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 2beb7f6..85d1f15 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -2,6 +2,8 @@
+
@@ -17,13 +19,15 @@
+
-
+
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 325cbac..c23a46e 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -13,6 +13,8 @@ import {
import {MatDialog} from "@angular/material/dialog";
import {DeleteConfirmationDialogComponent} from "./delete-confirmation-dialog/delete-confirmation-dialog.component";
import {ScriptAccount} from "./game-model/scriptAccounts/ScriptAccount";
+import {GamescriptOverviewComponent} from "./side-overviews/gamescript-overview/gamescript-overview.component";
+import {SimpleGamesystem} from "./game-model/gamesystems/SimpleGamesystem";
@Component({
selector: 'app-root',
@@ -25,6 +27,7 @@ export class AppComponent implements OnInit{
@ViewChild('drawer') drawer: MatDrawerContainer|undefined
@ViewChild('editor') editor: EditorComponent|undefined
@ViewChild('scriptAccountOverview') scriptAccountOverview: ScriptAccountOverviewComponent | undefined
+ @ViewChild('gamesystemOverview') gamesystemOverview: GamescriptOverviewComponent | undefined
gameModel: GameModel | undefined
@@ -42,29 +45,89 @@ export class AppComponent implements OnInit{
electronService.ipcRenderer.on('context-menu', (event: any, message: string) => {
this.zone.run(() => {
- if(message == "edit") {
- if(this.openContent == ModelComponentType.SCRIPTACCOUNT && this.scriptAccountOverview != undefined && this.scriptAccountOverview.selectedScriptAccount != undefined) {
- this.editor!.openGameModelComponent(this.scriptAccountOverview.selectedScriptAccount!);
- }
- } else if(message == "delete") {
- const affectedModelComponent = this.getSelectedModelComponent();
- const dialogRef = this.dialog.open(DeleteConfirmationDialogComponent, {data: affectedModelComponent, minWidth: "400px"});
-
- dialogRef.afterClosed().subscribe(res => {
- if(res != undefined && res) {
- if(affectedModelComponent instanceof ScriptAccount) {
- this.gameModel!.removeScriptAccount(affectedModelComponent);
- }
- }
- })
- }
- })
+ this.onContextMenuMessageRecieved(message);
+ });
})
} else {
console.log('Run in browser');
}
}
+ onContextMenuMessageRecieved(message: string) {
+ if(message == "edit") {
+ this.onEditModelComponent();
+ } else if(message == "delete") {
+ this.onDeleteModelComponent();
+ } else if(message.startsWith("new")) {
+ const splittedMessage = message.split("-");
+ const modelComponentType = ModelComponentTypeUtillities.fromString(splittedMessage[1]);
+ if(modelComponentType != undefined) {
+ this.onCreateModelComponent(modelComponentType);
+ } else {
+ console.log("[ERROR] [App-Component] Unknown Context-Menu Command!")
+ }
+ }
+ }
+
+ private onEditModelComponent() {
+ switch (this.openContent!) {
+ case ModelComponentType.SCRIPTACCOUNT: {
+ if(this.scriptAccountOverview!.selectedScriptAccount != undefined) {
+ this.editor!.openGameModelComponent(this.scriptAccountOverview!.selectedScriptAccount);
+ }
+ } break;
+ case ModelComponentType.GAMESYTEM: {
+ if(this.gamesystemOverview!.selectedGamesystem != undefined) {
+ const gamesystem = this.gameModel!.findGamesystem(this.gamesystemOverview!.selectedGamesystemName!);
+ this.editor!.openGameModelComponent(gamesystem!);
+ }
+ } break
+ }
+ }
+
+ private onDeleteModelComponent() {
+ const affectedModelComponent = this.getSelectedModelComponent();
+ const dialogRef = this.dialog.open(DeleteConfirmationDialogComponent, {data: affectedModelComponent, minWidth: "400px"});
+
+ dialogRef.afterClosed().subscribe(res => {
+ if(res != undefined && res) {
+ if(affectedModelComponent instanceof ScriptAccount) {
+ this.gameModel!.removeScriptAccount(affectedModelComponent);
+ }
+ }
+ })
+ }
+
+ private onCreateModelComponent(modelComponentType: ModelComponentType) {
+ switch (modelComponentType) {
+ case ModelComponentType.SCRIPTACCOUNT: this.onCreateNewScriptAccount(); break
+ case ModelComponentType.GAMESYTEM: this.onCreateNewGamesystem(); break
+ }
+ }
+
+ private onCreateNewScriptAccount() {
+ const createdScriptAccount = this.gameModel!.createScriptAccount("New ScriptAccount");
+ if(createdScriptAccount != undefined) {
+ this.editor?.openGameModelComponent(createdScriptAccount);
+ } else {
+ console.log("[DEBUG] [App-Component] ScriptAccount could not be created (Name not unique)");
+ }
+ }
+
+ private onCreateNewGamesystem() {
+ let parentGamesystemName = undefined
+ if(this.openContent != ModelComponentType.GAMESYTEM) {
+ this.openGamesystemsOverview();
+ } else {
+ parentGamesystemName = this.gamesystemOverview!.selectedGamesystemName;
+ }
+ const createdGamesystem = this.gameModel!.createGamesystem("New Gamesystem", parentGamesystemName);
+ if(createdGamesystem != undefined) {
+ this.gamesystemOverview!.refresh();
+ this.editor?.openGameModelComponent(createdGamesystem!);
+ }
+ }
+
private getSelectedModelComponent(): ModelComponent | undefined {
if(this.openContent == ModelComponentType.SCRIPTACCOUNT) {
if(this.scriptAccountOverview != undefined) {
@@ -78,8 +141,19 @@ export class AppComponent implements OnInit{
ngOnInit() {
this.gameModel = new GameModel("No More");
- this.gameModel.addScriptAccount("Temperature");
- this.gameModel.addScriptAccount("Luftfeuchtigkeit");
+ this.gameModel.createScriptAccount("Temperature");
+ this.gameModel.createScriptAccount("Luftfeuchtigkeit");
+
+ const weather = new SimpleGamesystem("Weather");
+ const season = new SimpleGamesystem("Season");
+
+ const springState = season.createState("Spring", "Spring, also known as springtime, is one of the four temperate seasons, succeeding winter and preceding summer.");
+ const summerState = season.createState("Summer", "Summer is the hottest and brightest of the four temperate seasons, occurring after spring and before autumn. ");
+
+ season.createTransition(springState!, summerState!);
+
+ this.gameModel.addGamesystem(weather)
+ this.gameModel.addGamesystem(season);
}
openScriptAccountsOverview() {
@@ -87,6 +161,11 @@ export class AppComponent implements OnInit{
this.drawer!.open();
}
+ openGamesystemsOverview() {
+ this.openContent = ModelComponentType.GAMESYTEM;
+ this.drawer!.open();
+ }
+
protected readonly ModelComponentType = ModelComponentType;
closeContentOverview() {
@@ -102,6 +181,11 @@ export class AppComponent implements OnInit{
} else {
console.log("[WARN] [App.Component] Editor is undefined")
}
+ }
+ onModelNameUpdate() {
+ if(this.openContent == ModelComponentType.GAMESYTEM) {
+ this.gamesystemOverview!.refresh();
+ }
}
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index c3edf21..4461bfd 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -14,7 +14,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MatIcon} from "@angular/material/icon";
import {MatToolbar} from "@angular/material/toolbar";
import {MatButton, MatIconButton, MatMiniFabButton} from "@angular/material/button";
-import {MatError, MatFormField, MatLabel} from "@angular/material/form-field";
+import {MatError, MatFormField, MatHint, MatLabel} from "@angular/material/form-field";
import {MatInput} from "@angular/material/input";
import {MatDrawer, MatDrawerContainer} from "@angular/material/sidenav";
import {MatMenu, MatMenuItem, MatMenuTrigger} from "@angular/material/menu";
@@ -28,6 +28,29 @@ import {ScriptAccountEditorComponent} from "./editor/script-account-editor/scrip
import {ModelComponentEditorComponent} from "./editor/model-component-editor/model-component-editor.component";
import {DeleteConfirmationDialogComponent} from "./delete-confirmation-dialog/delete-confirmation-dialog.component";
import {MatDialogActions, MatDialogContent, MatDialogTitle} from "@angular/material/dialog";
+import {GamescriptOverviewComponent} from "./side-overviews/gamescript-overview/gamescript-overview.component";
+import {MatTree, MatTreeModule} from "@angular/material/tree";
+import {GamesystemEditorComponent} from "./editor/gamesystem-editor/gamesystem-editor.component";
+import {
+ SimpleGamesystemEditorComponent
+} from "./editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component";
+import {
+ SimpleStateEditorComponent
+} from "./editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component";
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
+ MatTable
+} from "@angular/material/table";
+import {MatCheckbox} from "@angular/material/checkbox";
+import {
+ SimpleTransitionEditorComponent
+} from "./editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component";
+import {MatOption, MatSelect} from "@angular/material/select";
// AoT requires an exported function for factories
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
@@ -39,7 +62,12 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
EditorComponent,
ScriptAccountEditorComponent,
ModelComponentEditorComponent,
- DeleteConfirmationDialogComponent
+ DeleteConfirmationDialogComponent,
+ GamescriptOverviewComponent,
+ GamesystemEditorComponent,
+ SimpleGamesystemEditorComponent,
+ SimpleStateEditorComponent,
+ SimpleTransitionEditorComponent
],
imports: [
BrowserModule,
@@ -79,6 +107,21 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
MatDialogContent,
MatDialogActions,
MatMiniFabButton,
+ MatTreeModule,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatCellDef,
+ MatCell,
+ MatHeaderRow,
+ MatRow,
+ MatHeaderRowDef,
+ MatRowDef,
+ MatCheckbox,
+ MatSelect,
+ MatOption,
+ MatHint
],
providers: [],
bootstrap: [AppComponent]
diff --git a/src/app/editor/editor.component.html b/src/app/editor/editor.component.html
index ef4276b..dc13cc1 100644
--- a/src/app/editor/editor.component.html
+++ b/src/app/editor/editor.component.html
@@ -1,13 +1,17 @@
- inventory_2
+ inventory_2
+ code
+
{{modelComponent.componentName}}
-
+
+
diff --git a/src/app/editor/editor.component.ts b/src/app/editor/editor.component.ts
index 6b222fe..c042346 100644
--- a/src/app/editor/editor.component.ts
+++ b/src/app/editor/editor.component.ts
@@ -1,8 +1,11 @@
-import {Component, Input} from '@angular/core';
+import {Component, EventEmitter, Input, Output} from '@angular/core';
import {GameModel} from "../game-model/GameModel";
import {ModelComponent} from "../game-model/ModelComponent";
import {ModelComponentType} from "../game-model/ModelComponentType";
import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount";
+import {Gamesystem} from "../game-model/gamesystems/Gamesystem";
+import {State} from "../game-model/gamesystems/State";
+import {Transition} from "../game-model/gamesystems/Transition";
@Component({
selector: 'app-editor',
@@ -11,6 +14,7 @@ import {ScriptAccount} from "../game-model/scriptAccounts/ScriptAccount";
})
export class EditorComponent {
gameModelComponents: ModelComponent[] = [];
+ @Output("onModelNameUpdate") onModelNameUpdateEmitter = new EventEmitter();
openGameModelComponent(gameModelComponent: ModelComponent) {
if(!this.gameModelComponents.includes(gameModelComponent)) {
@@ -28,5 +32,15 @@ export class EditorComponent {
}
}
+ convertModelComponentToGamesystem(modelComponent: ModelComponent) {
+ if(modelComponent instanceof Gamesystem) {
+ return modelComponent as Gamesystem, Transition>;
+ }
+ }
+
protected readonly ModelComponentType = ModelComponentType;
+
+ onModelNameUpdate() {
+ this.onModelNameUpdateEmitter.emit(true);
+ }
}
diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.html b/src/app/editor/gamesystem-editor/gamesystem-editor.component.html
new file mode 100644
index 0000000..49bfe84
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/gamesystem-editor.component.html
@@ -0,0 +1 @@
+
diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.scss b/src/app/editor/gamesystem-editor/gamesystem-editor.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.spec.ts b/src/app/editor/gamesystem-editor/gamesystem-editor.component.spec.ts
new file mode 100644
index 0000000..febd88c
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/gamesystem-editor.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GamesystemEditorComponent } from './gamesystem-editor.component';
+
+describe('GamesystemEditorComponent', () => {
+ let component: GamesystemEditorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [GamesystemEditorComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(GamesystemEditorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts b/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts
new file mode 100644
index 0000000..666f6a6
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/gamesystem-editor.component.ts
@@ -0,0 +1,33 @@
+import {Component, Input} from '@angular/core';
+import {GameModel} from "../../game-model/GameModel";
+import {Gamesystem} from "../../game-model/gamesystems/Gamesystem";
+import {State} from "../../game-model/gamesystems/State";
+import {Transition} from "../../game-model/gamesystems/Transition";
+import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem";
+import {ProductGamesystem} from "../../game-model/gamesystems/ProductGamesystem";
+
+@Component({
+ selector: 'app-gamesystem-editor',
+ templateUrl: './gamesystem-editor.component.html',
+ styleUrl: './gamesystem-editor.component.scss'
+})
+export class GamesystemEditorComponent {
+
+ @Input() gamesystem: Gamesystem, Transition> | undefined
+
+ isSimpleGamesystem() {
+ return this.gamesystem instanceof SimpleGamesystem;
+ }
+
+ convertGamesystemToSimpleGamesystem() {
+ if(this.gamesystem instanceof SimpleGamesystem) {
+ return this.gamesystem as SimpleGamesystem;
+ }
+ }
+
+ convertGamesystemToProductGamesystem() {
+ if(this.gamesystem instanceof ProductGamesystem) {
+ return this.gamesystem as ProductGamesystem;
+ }
+ }
+}
diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html
new file mode 100644
index 0000000..5ad3526
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.html
@@ -0,0 +1,2 @@
+
+
diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.scss b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.scss
new file mode 100644
index 0000000..7112fce
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.scss
@@ -0,0 +1,3 @@
+.transition-editor {
+ margin-top: 15px;
+}
diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.spec.ts b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.spec.ts
new file mode 100644
index 0000000..b5688c0
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SimpleGamesystemEditorComponent } from './simple-gamesystem-editor.component';
+
+describe('SimpleGamesystemEditorComponent', () => {
+ let component: SimpleGamesystemEditorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [SimpleGamesystemEditorComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(SimpleGamesystemEditorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts
new file mode 100644
index 0000000..ab4fcc5
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/simple-gamesystem-editor/simple-gamesystem-editor.component.ts
@@ -0,0 +1,16 @@
+import {Component, Input} from '@angular/core';
+import {SimpleGamesystem} from "../../../game-model/gamesystems/SimpleGamesystem";
+import {MatTableDataSource} from "@angular/material/table";
+
+@Component({
+ selector: 'app-simple-gamesystem-editor',
+ templateUrl: './simple-gamesystem-editor.component.html',
+ styleUrl: './simple-gamesystem-editor.component.scss'
+})
+export class SimpleGamesystemEditorComponent {
+
+ @Input() simpleGamesystem: SimpleGamesystem | undefined
+
+
+
+}
diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html
new file mode 100644
index 0000000..f723e19
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.html
@@ -0,0 +1,77 @@
+
+
+ Label |
+
+ {{state.stateLabel}}
+
+
+ warningMissing State-Label Information
+
+ |
+
+
+
+
+
+
+ {{element.stateDescription}}
+
+ Description
+
+
+
+ |
+
+
+
+
+
+ Initial |
+
+
+ done
+ close
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.scss b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.scss
new file mode 100644
index 0000000..0830e19
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.scss
@@ -0,0 +1,63 @@
+table {
+ width: 100%;
+}
+
+tr.example-detail-row {
+ height: 0;
+}
+
+tr.example-element-row:not(.example-expanded-row):hover {
+ background: #545456
+}
+
+tr.example-element-row:not(.example-expanded-row):active {
+ background: #545456;
+}
+
+.example-element-row td {
+ border-bottom-width: 0;
+}
+
+.example-element-detail {
+ overflow: hidden;
+ display: flex;
+}
+
+.example-element-diagram {
+ min-width: 80px;
+ border: 2px solid black;
+ padding: 8px;
+ font-weight: lighter;
+ margin: 8px 0;
+ height: 104px;
+}
+
+.example-element-symbol {
+ font-weight: bold;
+ font-size: 40px;
+ line-height: normal;
+}
+
+.example-element-description {
+ padding: 16px;
+}
+
+.example-element-description-attribution {
+ opacity: 0.5;
+}
+
+.mat-column-edit, .mat-column-delete, .mat-column-expand {
+ width: 32px;
+}
+
+.long-form {
+ width: 100%;
+}
+
+.mat-error {
+ color: red;
+}
+
+.warning-icon {
+ margin-right: 5px;
+}
diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.spec.ts b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.spec.ts
new file mode 100644
index 0000000..c667357
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SimpleStateEditorComponent } from './simple-state-editor.component';
+
+describe('SimpleStateEditorComponent', () => {
+ let component: SimpleStateEditorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [SimpleStateEditorComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(SimpleStateEditorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts
new file mode 100644
index 0000000..76c5bef
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/state-editor/simple-state-editor/simple-state-editor.component.ts
@@ -0,0 +1,86 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {SimpleState} from "../../../../game-model/gamesystems/SimpleState";
+import {MatTableDataSource} from "@angular/material/table";
+import {animate, state, style, transition, trigger} from "@angular/animations";
+import {MatSnackBar} from "@angular/material/snack-bar";
+import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
+
+@Component({
+ selector: 'app-simple-state-editor',
+ templateUrl: './simple-state-editor.component.html',
+ styleUrl: './simple-state-editor.component.scss',
+ animations: [
+ trigger('detailExpand', [
+ state('collapsed,void', style({height: '0px', minHeight: '0'})),
+ state('expanded', style({height: '*'})),
+ transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+ ]),
+ ],
+})
+export class SimpleStateEditorComponent implements OnInit{
+
+ @Input() states: SimpleState[] = [];
+ @Input() gamesystem: SimpleGamesystem | undefined
+ dataSource = new MatTableDataSource();
+ displayedColumns = ["name", "initial", "edit", "delete"];
+ columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
+ expandedElement: SimpleState | null = null;
+ editedElement: SimpleState | null = null;
+
+ editedStateLabelError: boolean = false;
+
+ constructor(private snackbar: MatSnackBar) {
+ }
+
+ ngOnInit() {
+ this.dataSource.data = this.states;
+ }
+
+ editState(state: SimpleState) {
+ if(this.editedElement === state) {
+ this.editedElement = null;
+ } else {
+ this.editedElement = state;
+ }
+ }
+
+ finishEditing() {
+ if(this.isEditedStateValid()) {
+ this.editedElement = null;
+ }
+ }
+
+ isEditedStateValid(): boolean {
+ if(this.editedElement!.stateLabel.length > 0) {
+ this.editedStateLabelError = false;
+ return true;
+ } else {
+ this.editedStateLabelError = true;
+ }
+ return false;
+ }
+
+ deleteState(state: SimpleState) {
+ if(this.gamesystem == undefined || this.gamesystem.parentGamesystem == undefined) {
+ this.gamesystem?.removeState(state);
+ this.dataSource.data = this.gamesystem!.states
+ } else {
+
+ }
+ }
+
+ addState() {
+ if(this.gamesystem != undefined) {
+ const simpleState = this.gamesystem.createState("New State", "");
+ if(simpleState != undefined) {
+ this.dataSource.data = this.gamesystem.states;
+ this.editedElement = simpleState;
+ this.expandedElement = simpleState;
+ this.onStateChange();
+ }
+ }
+ }
+ onStateChange() {
+ this.gamesystem!.onModifyContent();
+ }
+}
diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html
new file mode 100644
index 0000000..1ad5505
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.html
@@ -0,0 +1,81 @@
+
+
+ Starting State |
+
+ {{transition.startingState.stateLabel}}
+
+
+ {{state.stateLabel}}
+
+ warning Starting and Ending State cannot be the same!
+ warning Select a valid Starting State!
+
+ |
+
+
+
+ Ending State |
+
+ {{transition.endingState.stateLabel}}
+
+
+ {{state.stateLabel}}
+
+ warning Starting and Ending State cannot be the same!
+ warning Select a valid Ending State!
+
+ |
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.scss b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.scss
new file mode 100644
index 0000000..3292508
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.scss
@@ -0,0 +1,63 @@
+table {
+ width: 100%;
+ margin-top: 20px;
+}
+.mat-column-edit, .mat-column-delete, .mat-column-expand {
+ width: 32px;
+}
+
+tr.example-detail-row {
+ height: 0;
+}
+
+tr.example-element-row:not(.example-expanded-row):hover {
+ background: #545456;
+}
+
+tr.example-element-row:not(.example-expanded-row):active {
+ background: #545456;
+}
+
+.example-element-row td {
+ border-bottom-width: 0;
+}
+
+.example-element-detail {
+ overflow: hidden;
+ display: flex;
+}
+
+.example-element-diagram {
+ min-width: 80px;
+ border: 2px solid black;
+ padding: 8px;
+ font-weight: lighter;
+ margin: 8px 0;
+ height: 104px;
+}
+
+.example-element-symbol {
+ font-weight: bold;
+ font-size: 40px;
+ line-height: normal;
+}
+
+.example-element-description {
+ padding: 16px;
+}
+
+.example-element-description-attribution {
+ opacity: 0.5;
+}
+
+.long-form {
+ width: 100%;
+}
+
+.warning-icon {
+ margin-right: 5px;
+}
+
+.mat-error {
+ color: red;
+}
diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.spec.ts b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.spec.ts
new file mode 100644
index 0000000..0edfece
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SimpleTransitionEditorComponent } from './simple-transition-editor.component';
+
+describe('SimpleTransitionEditorComponent', () => {
+ let component: SimpleTransitionEditorComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [SimpleTransitionEditorComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(SimpleTransitionEditorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts
new file mode 100644
index 0000000..c1f64ee
--- /dev/null
+++ b/src/app/editor/gamesystem-editor/transition-editor/simple-transition-editor/simple-transition-editor.component.ts
@@ -0,0 +1,86 @@
+import {Component, Input, OnInit} from '@angular/core';
+import {GameModel} from "../../../../game-model/GameModel";
+import {SimpleGamesystem} from "../../../../game-model/gamesystems/SimpleGamesystem";
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
+ MatTable,
+ MatTableDataSource
+} from "@angular/material/table";
+import {SimpleTransition} from "../../../../game-model/gamesystems/SimpleTransition";
+import {animate, state, style, transition, trigger} from "@angular/animations";
+import {SimpleState} from "../../../../game-model/gamesystems/SimpleState";
+
+@Component({
+ selector: 'app-simple-transition-editor',
+ templateUrl: './simple-transition-editor.component.html',
+ styleUrl: './simple-transition-editor.component.scss',
+ animations: [
+ trigger('detailExpand', [
+ state('collapsed,void', style({height: '0px', minHeight: '0'})),
+ state('expanded', style({height: '*'})),
+ transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+ ]),
+ ],
+})
+export class SimpleTransitionEditorComponent implements OnInit {
+
+ @Input() gamesystem: SimpleGamesystem | undefined
+ displayedColumns: string[] = ["starting-state", "ending-state", "edit", "delete"];
+ dataSource = new MatTableDataSource();
+ columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
+ expandedElement: SimpleTransition | null = null;
+ editedTransition: SimpleTransition | undefined
+ editedTransitionIndex = -1;
+
+ defaultStartingState: SimpleState = new SimpleState("None", "");
+ defaultEndingState: SimpleState = new SimpleState("None", "");
+
+ transitionError: boolean = false;
+ transitionStartingStateError = true;
+ transitionEndingStateError = true;
+ ngOnInit() {
+ this.dataSource.data = this.gamesystem!.transitions;
+ }
+
+ addTransition() {
+ this.editedTransition = new SimpleTransition(this.defaultStartingState, this.defaultEndingState);
+ const updatedData = this.dataSource.data;
+ updatedData.push(this.editedTransition);
+ this.dataSource.data = updatedData;
+ this.editedTransitionIndex = this.dataSource.data.length;
+ }
+
+ validateEditedTransition() {
+ this.transitionError = false;
+ this.transitionStartingStateError = false;
+ this.transitionEndingStateError = false;
+ if(this.editedTransition!.startingState === this.editedTransition!.endingState) {
+ this.transitionError = true;
+ } else if(this.editedTransition!.startingState == this.defaultStartingState) {
+ this.transitionStartingStateError = true;
+ } else if(this.editedTransition!.endingState == this.defaultEndingState) {
+ this.transitionEndingStateError = true;
+ }
+ }
+
+ finishEditing() {
+ this.validateEditedTransition();
+ if(this.transitionError || this.transitionStartingStateError || this.transitionEndingStateError) {
+ return;
+ }
+ this.gamesystem?.createTransition(this.editedTransition!.startingState, this.editedTransition!.endingState);
+ this.dataSource.data = this.gamesystem!.transitions;
+ this.editedTransition = undefined;
+ }
+
+ deleteTransition(transition: SimpleTransition) {
+ if(this.gamesystem!.parentGamesystem == undefined) {
+ this.gamesystem!.removeTransition(transition);
+ this.dataSource.data = this.gamesystem!.transitions;
+ }
+ }
+}
diff --git a/src/app/editor/model-component-editor/model-component-editor.component.ts b/src/app/editor/model-component-editor/model-component-editor.component.ts
index c3a4e67..c527bb5 100644
--- a/src/app/editor/model-component-editor/model-component-editor.component.ts
+++ b/src/app/editor/model-component-editor/model-component-editor.component.ts
@@ -1,4 +1,4 @@
-import {Component, Input, OnInit} from '@angular/core';
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ModelComponent} from "../../game-model/ModelComponent";
import {FormControl, Validators} from "@angular/forms";
@@ -9,6 +9,7 @@ import {FormControl, Validators} from "@angular/forms";
})
export class ModelComponentEditorComponent implements OnInit{
@Input('modelComponent') modelComponent: ModelComponent | undefined
+ @Output("onModelNameUpdated") onModelNameUpdateEmitter = new EventEmitter();
nameCtrl: FormControl = new FormControl('', [Validators.required]);
descriptionCtrl: FormControl = new FormControl('' );
@@ -21,6 +22,7 @@ export class ModelComponentEditorComponent implements OnInit{
onUpdateName() {
this.modelComponent!.componentName = this.nameCtrl.value;
this.modelComponent!.onModifyContent();
+ this.onModelNameUpdateEmitter.emit(true);
}
onUpdateDescription() {
diff --git a/src/app/game-model/GameModel.ts b/src/app/game-model/GameModel.ts
index a061db3..ac4d355 100644
--- a/src/app/game-model/GameModel.ts
+++ b/src/app/game-model/GameModel.ts
@@ -1,10 +1,14 @@
import {Gamesystem} from "./gamesystems/Gamesystem";
import {ScriptAccount} from "./scriptAccounts/ScriptAccount";
+import {Transition} from "./gamesystems/Transition";
+import {State} from "./gamesystems/State";
+import {ProductGamesystem} from "./gamesystems/ProductGamesystem";
+import {SimpleGamesystem} from "./gamesystems/SimpleGamesystem";
export class GameModel {
private readonly _gameModelName: string
- private _gamesystems: Gamesystem[] = [];
+ private _gamesystems: Gamesystem[] = [];
private _scriptAccounts: ScriptAccount[] = [];
constructor(gameModelName: string) {
@@ -13,26 +17,25 @@ export class GameModel {
get gameModelName(): string {
return this._gameModelName;
}
-
-
- get gamesystems(): Gamesystem[] {
+ get gamesystems(): Gamesystem[] {
return this._gamesystems;
}
get scriptAccounts(): ScriptAccount[] {
return this._scriptAccounts;
}
- addGamesystem(gamesystem: Gamesystem) {
- if(!this.gamesystems.includes(gamesystem)) {
+ addGamesystem(gamesystem: Gamesystem) {
+ if(this.findGamesystem(gamesystem.componentName) == undefined) {
this._gamesystems.push(gamesystem);
}
+
}
- removeGamesystem(gamesystem : Gamesystem) {
+ removeGamesystem(gamesystem : Gamesystem) {
this._gamesystems = this._gamesystems.filter(g => g !== gamesystem);
}
- addScriptAccount(scriptAccountName: string) {
+ createScriptAccount(scriptAccountName: string) {
if(scriptAccountName != undefined && scriptAccountName.length > 0) {
const scriptAccount = new ScriptAccount(scriptAccountName, "");
const searchedScriptAccount = this.scriptAccounts.find(s => s.componentName === scriptAccount.componentName);
@@ -44,10 +47,47 @@ export class GameModel {
return undefined;
}
+ createGamesystem(gamesystemName: string, parentGamesystemName: string | undefined) {
+ if(gamesystemName != undefined && this.findGamesystem(gamesystemName) == undefined) {
+ const simpleGamesystem = new SimpleGamesystem(gamesystemName);
+ if(parentGamesystemName != undefined) {
+ const parentGamesystem = this.findGamesystem(parentGamesystemName);
+ if(parentGamesystem instanceof SimpleGamesystem) {
+ const parentProductGamesystem = ProductGamesystem.constructFromSimpleGamesystem(parentGamesystem, this);
+ parentProductGamesystem.addChildGamesystem(simpleGamesystem);
+ simpleGamesystem.parentGamesystem = parentProductGamesystem;
+ } else {
+ const productParentGamesystem = parentGamesystem as ProductGamesystem;
+ productParentGamesystem.addChildGamesystem(simpleGamesystem);
+ simpleGamesystem.parentGamesystem = productParentGamesystem;
+ }
+ } else {
+ this.gamesystems.push(simpleGamesystem);
+
+ }
+ return simpleGamesystem;
+ }
+ }
+
removeScriptAccount(scriptAccount: ScriptAccount) {
if(scriptAccount != undefined) {
this._scriptAccounts = this.scriptAccounts.filter(s => s != scriptAccount);
}
}
+ findGamesystem(gamesystemName: string) {
+ const gamesystemQueue : Gamesystem, Transition>[] = [];
+ this.gamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem));
+
+ while(gamesystemQueue.length > 0) {
+ const currentGamesystem = gamesystemQueue.shift()!;
+ if(currentGamesystem.componentName == gamesystemName) {
+ return currentGamesystem;
+ } else if(currentGamesystem instanceof ProductGamesystem) {
+ const currentProductGamesystem = currentGamesystem as ProductGamesystem;
+ currentProductGamesystem.innerGamesystems.forEach(gamesystem => gamesystemQueue.push(gamesystem));
+ }
+ }
+ }
+
}
diff --git a/src/app/game-model/ModelComponentType.ts b/src/app/game-model/ModelComponentType.ts
index 5218558..77a75a7 100644
--- a/src/app/game-model/ModelComponentType.ts
+++ b/src/app/game-model/ModelComponentType.ts
@@ -1,5 +1,5 @@
export enum ModelComponentType {
- SCRIPTACCOUNT
-
+ SCRIPTACCOUNT,
+ GAMESYTEM
}
diff --git a/src/app/game-model/ModelComponentTypeUtillities.ts b/src/app/game-model/ModelComponentTypeUtillities.ts
index c92fce9..da1f827 100644
--- a/src/app/game-model/ModelComponentTypeUtillities.ts
+++ b/src/app/game-model/ModelComponentTypeUtillities.ts
@@ -1,10 +1,10 @@
import {ModelComponentType} from "./ModelComponentType";
-import {ModelComponent} from "./ModelComponent";
export class ModelComponentTypeUtillities {
static toString(modelComponentType: ModelComponentType | undefined): string {
switch (modelComponentType) {
case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccounts";
+ case ModelComponentType.GAMESYTEM: return "Gamesystems";
default: return "Undefined";
}
}
@@ -12,7 +12,15 @@ export class ModelComponentTypeUtillities {
static toSingleString(modelComponentType: ModelComponentType | undefined): string {
switch (modelComponentType) {
case ModelComponentType.SCRIPTACCOUNT: return "ScriptAccount";
+ case ModelComponentType.GAMESYTEM: return "Gamesystem";
default: return "Undefined";
}
}
+
+ static fromString(string: string) : ModelComponentType | undefined {
+ switch (string) {
+ case "gamesystem": return ModelComponentType.GAMESYTEM;
+ case "scriptaccount": return ModelComponentType.SCRIPTACCOUNT;
+ }
+ }
}
diff --git a/src/app/game-model/gamesystems/Gamesystem.ts b/src/app/game-model/gamesystems/Gamesystem.ts
index 989e9c0..0dea6ba 100644
--- a/src/app/game-model/gamesystems/Gamesystem.ts
+++ b/src/app/game-model/gamesystems/Gamesystem.ts
@@ -1,8 +1,35 @@
-export class Gamesystem {
- gamesystemName: string
+import {SimpleGamesystem} from "./SimpleGamesystem";
+import {ProductGamesystem} from "./ProductGamesystem";
+import {ModelComponent} from "../ModelComponent";
+import {ModelComponentType} from "../ModelComponentType";
+
+export abstract class Gamesystem extends ModelComponent{
+
+ states: S[] = [];
+ transitions: T[] = [];
constructor(gamesystemName: string) {
- this.gamesystemName = gamesystemName;
+ super(gamesystemName, "", ModelComponentType.GAMESYTEM);
+ }
+
+ abstract createState(label: string, description: string): S|undefined;
+
+ abstract createTransition(startingState: S, endingState: S): T|undefined;
+
+ abstract removeState(state: S): boolean;
+
+ removeTransition(transition: T): boolean {
+ const updatedTransitions = this.transitions.filter(t => t !== transition);
+ if(updatedTransitions.length == this.transitions.length) {
+ return false;
+ }
+
+ this.transitions = updatedTransitions;
+ return true;
}
+ save() {
+
+ }
+
}
diff --git a/src/app/game-model/gamesystems/ProductGamesystem.ts b/src/app/game-model/gamesystems/ProductGamesystem.ts
new file mode 100644
index 0000000..84a135d
--- /dev/null
+++ b/src/app/game-model/gamesystems/ProductGamesystem.ts
@@ -0,0 +1,60 @@
+import {Gamesystem} from "./Gamesystem";
+import {ProductState} from "./ProductState";
+import {ProductTransition} from "./ProductTransition";
+import {State} from "./State";
+import {Transition} from "./Transition";
+import {SimpleState} from "./SimpleState";
+import {SimpleGamesystem} from "./SimpleGamesystem";
+import {GameModel} from "../GameModel";
+
+export class ProductGamesystem extends Gamesystem {
+
+ innerGamesystems: Gamesystem, Transition>[] = [];
+ parentGamesystem: ProductGamesystem | undefined
+
+ static constructFromSimpleGamesystem(simpleGamesystem: SimpleGamesystem, gameModel: GameModel) {
+ const productGamesystem = new ProductGamesystem(simpleGamesystem.componentName);
+ const parentGamesystem = simpleGamesystem.parentGamesystem;
+
+ if(simpleGamesystem.states.length > 0) {
+ simpleGamesystem.componentName += "(Child)";
+ productGamesystem.addChildGamesystem(simpleGamesystem);
+ }
+
+
+ if(parentGamesystem != undefined) {
+ parentGamesystem.removeChildGamesystem(simpleGamesystem);
+ parentGamesystem.addChildGamesystem(productGamesystem);
+ } else {
+ gameModel.removeGamesystem(simpleGamesystem);
+ gameModel.addGamesystem(productGamesystem);
+ }
+
+ return productGamesystem;
+ }
+
+ createState(label: string, description: string): ProductState | undefined {
+ return undefined;
+ }
+
+ createTransition(startingState: ProductState, endingState: ProductState): ProductTransition | undefined {
+ return undefined;
+ }
+
+ removeState(state: ProductState): boolean {
+ return false;
+ }
+
+ removeInnerState(state: SimpleState) {
+
+ }
+
+
+ addChildGamesystem(gamesystem: Gamesystem, Transition>) {
+ this.innerGamesystems.push(gamesystem);
+ }
+
+ private removeChildGamesystem(gamesystem: Gamesystem, Transition>) {
+ this.innerGamesystems = this.innerGamesystems.filter(childSystem => childSystem != gamesystem);
+ }
+}
diff --git a/src/app/game-model/gamesystems/ProductState.ts b/src/app/game-model/gamesystems/ProductState.ts
new file mode 100644
index 0000000..8a5cbaf
--- /dev/null
+++ b/src/app/game-model/gamesystems/ProductState.ts
@@ -0,0 +1,7 @@
+import {ProductTransition} from "./ProductTransition";
+import {State} from "./State";
+import {SimpleState} from "./SimpleState";
+
+export class ProductState extends State {
+ innerStates: SimpleState[] = [];
+}
diff --git a/src/app/game-model/gamesystems/ProductTransition.ts b/src/app/game-model/gamesystems/ProductTransition.ts
new file mode 100644
index 0000000..3e862ea
--- /dev/null
+++ b/src/app/game-model/gamesystems/ProductTransition.ts
@@ -0,0 +1,6 @@
+import {Transition} from "./Transition";
+import {ProductState} from "./ProductState";
+
+export class ProductTransition extends Transition {
+
+}
diff --git a/src/app/game-model/gamesystems/SimpleGamesystem.ts b/src/app/game-model/gamesystems/SimpleGamesystem.ts
new file mode 100644
index 0000000..4021c93
--- /dev/null
+++ b/src/app/game-model/gamesystems/SimpleGamesystem.ts
@@ -0,0 +1,60 @@
+import {Gamesystem} from "./Gamesystem";
+import {SimpleState} from "./SimpleState";
+import {SimpleTransition} from "./SimpleTransition";
+import {State} from "./State";
+import {Transition} from "./Transition";
+import {ProductState} from "./ProductState";
+import {ProductTransition} from "./ProductTransition";
+import {ProductGamesystem} from "./ProductGamesystem";
+export class SimpleGamesystem extends Gamesystem {
+
+ parentGamesystem: ProductGamesystem | undefined
+
+ createState(label: string, description: string): SimpleState | undefined {
+ if(label == null) {
+ return undefined;
+ }
+
+ if(description == null) {
+ description = "";
+ }
+
+ const state = new SimpleState(label, description);
+ if(this.states.find(s => s.stateLabel == label) == undefined) {
+ this.states.push(state);
+ return state;
+ } else {
+ return undefined
+ }
+ }
+
+ createTransition(startingState: SimpleState, endingState: SimpleState): SimpleTransition | undefined{
+ if((startingState == null || endingState == null) || startingState === endingState) {
+ return undefined;
+ }
+
+ const transition = new SimpleTransition(startingState, endingState);
+ if(this.transitions.find(t => t.startingState === startingState && t.endingState === endingState) == undefined) {
+ this.transitions.push(transition)
+ return transition;
+ } else {
+ startingState.removeOutgoingTransition(transition);
+ endingState.removeIncomingTransition(transition);
+ return undefined
+ }
+
+ }
+
+
+ removeState(state: SimpleState): boolean {
+ const updatedStates = this.states.filter(s => s !== state);
+ const updated = updatedStates.length != this.states.length;
+ this.states = updatedStates;
+
+ this.transitions = this.transitions.filter(t => t.startingState !== state && t.endingState !== state);
+
+ return updated;
+ }
+
+
+}
diff --git a/src/app/game-model/gamesystems/SimpleState.ts b/src/app/game-model/gamesystems/SimpleState.ts
new file mode 100644
index 0000000..d39ffba
--- /dev/null
+++ b/src/app/game-model/gamesystems/SimpleState.ts
@@ -0,0 +1,6 @@
+import {State} from "./State";
+import {SimpleTransition} from "./SimpleTransition";
+
+export class SimpleState extends State {
+
+}
diff --git a/src/app/game-model/gamesystems/SimpleTransition.ts b/src/app/game-model/gamesystems/SimpleTransition.ts
new file mode 100644
index 0000000..e7356ed
--- /dev/null
+++ b/src/app/game-model/gamesystems/SimpleTransition.ts
@@ -0,0 +1,6 @@
+import {SimpleState} from "./SimpleState";
+import {Transition} from "./Transition";
+
+export class SimpleTransition extends Transition {
+
+}
diff --git a/src/app/game-model/gamesystems/State.ts b/src/app/game-model/gamesystems/State.ts
new file mode 100644
index 0000000..5184811
--- /dev/null
+++ b/src/app/game-model/gamesystems/State.ts
@@ -0,0 +1,32 @@
+import {Transition} from "./Transition";
+
+export abstract class State> {
+ stateLabel: string = "";
+ stateDescription: string = "";
+ incomingTransitions: T[] =[];
+ outgoingTransitions: T[] =[];
+
+ initial: boolean = false;
+
+
+ constructor(stateLabel: string, stateDescription: string) {
+ this.stateLabel = stateLabel;
+ this.stateDescription = stateDescription;
+ }
+
+ addIncomingTransition(transition: T) {
+ this.incomingTransitions.push(transition);
+ }
+
+ addOutgoingTransition(transition: T) {
+ this.outgoingTransitions.push(transition);
+ }
+
+ removeIncomingTransition(transition: T) {
+
+ }
+
+ removeOutgoingTransition(transition: T) {
+
+ }
+}
diff --git a/src/app/game-model/gamesystems/Transition.ts b/src/app/game-model/gamesystems/Transition.ts
new file mode 100644
index 0000000..5f75cbd
--- /dev/null
+++ b/src/app/game-model/gamesystems/Transition.ts
@@ -0,0 +1,15 @@
+import {State} from "./State";
+
+export abstract class Transition> {
+ startingState: S
+ endingState: S
+
+
+ constructor(startingState: S, endingState: S) {
+ this.startingState = startingState;
+ this.endingState = endingState;
+
+ this.startingState.addOutgoingTransition(this);
+ this.endingState.addIncomingTransition(this);
+ }
+}
diff --git a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.html b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.html
new file mode 100644
index 0000000..d12b880
--- /dev/null
+++ b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+ {{node.name}}
+
+
+
+
+
+
+
+ {{node.name}}
+
+
+
diff --git a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.scss b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.scss
new file mode 100644
index 0000000..6a35f58
--- /dev/null
+++ b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.scss
@@ -0,0 +1,40 @@
+.mat-tree-node {
+ min-height: 1.8em !important;
+ height: 1.8em;
+}
+
+
+.small-icon-button {
+ width: 26px !important;
+ height: 26px !important;
+ padding: 0px !important;
+ display: inline-flex !important;
+ align-items: center;
+ justify-content: center;
+ margin-left: 5px;
+ margin-bottom: 2px;
+
+ & > *[role=img] {
+ width: 18px;
+ height: 18px;
+ font-size: 18px;
+
+ svg {
+ width: 18px;
+ height: 18px;
+ }
+ }
+
+ .mat-mdc-button-touch-target {
+ width: 22px !important;
+ height: 22px !important;
+ }
+}
+
+.small-icon-button mat-icon {
+ color: whitesmoke;
+}
+
+.selected-node {
+ background-color: #545456
+}
diff --git a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.spec.ts b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.spec.ts
new file mode 100644
index 0000000..afcbba8
--- /dev/null
+++ b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GamescriptOverviewComponent } from './gamescript-overview.component';
+
+describe('GamescriptOverviewComponent', () => {
+ let component: GamescriptOverviewComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [GamescriptOverviewComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(GamescriptOverviewComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts
new file mode 100644
index 0000000..4c07292
--- /dev/null
+++ b/src/app/side-overviews/gamescript-overview/gamescript-overview.component.ts
@@ -0,0 +1,106 @@
+import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
+import {Gamesystem} from "../../game-model/gamesystems/Gamesystem";
+import {State} from "../../game-model/gamesystems/State";
+import {Transition} from "../../game-model/gamesystems/Transition";
+import {ProductGamesystem} from "../../game-model/gamesystems/ProductGamesystem";
+import {FlatTreeControl} from "@angular/cdk/tree";
+import {
+ MatTree,
+ MatTreeFlatDataSource,
+ MatTreeFlattener,
+ MatTreeNode, MatTreeNodeDef,
+ MatTreeNodePadding, MatTreeNodeToggle
+} from "@angular/material/tree";
+import {MatIcon} from "@angular/material/icon";
+import {MatIconButton} from "@angular/material/button";
+import {SimpleGamesystem} from "../../game-model/gamesystems/SimpleGamesystem";
+import {GameModel} from "../../game-model/GameModel";
+import {ElectronService} from "../../core/services";
+
+
+interface FlatNode {
+ expandable: boolean,
+ name: string,
+ level: number
+}
+@Component({
+ selector: 'app-gamescript-overview',
+ templateUrl: './gamescript-overview.component.html',
+ styleUrl: './gamescript-overview.component.scss'
+})
+export class GamescriptOverviewComponent implements OnInit {
+
+ @Input('gameModel') gameModel: GameModel | undefined
+ @Output('openGamesystemEditor') openGamesystemEmitter : EventEmitter, Transition>> = new EventEmitter, Transition>>();
+
+
+ ngOnInit() {
+ this.dataSource.data = this.gameModel!.gamesystems;
+ }
+
+ private _transformer = (node: Gamesystem, Transition>, level: number) => {
+ return {
+ expandable: this.isProductGamesystem(node) && !!(node as ProductGamesystem).innerGamesystems && (node as ProductGamesystem).innerGamesystems.length > 0,
+ name: node.componentName,
+ level: level
+ }
+ }
+
+ treeControl = new FlatTreeControl(
+ node => node.level,
+ node => node.expandable
+ )
+
+ treeFlattener = new MatTreeFlattener(
+ this._transformer,
+ node => node.level,
+ node => node.expandable,
+ node => this.isSimpleGamesystem(node)? []: (node as ProductGamesystem).innerGamesystems
+ );
+
+ dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
+ selectedGamesystem: FlatNode | undefined;
+
+ constructor(private electronService: ElectronService) {
+
+ }
+
+ hasChild = (_: number, node: FlatNode) => node.expandable;
+
+
+ isSimpleGamesystem(gamesystem: Gamesystem, Transition>) {
+ return gamesystem instanceof SimpleGamesystem;
+ }
+
+ isProductGamesystem(gamesystem: Gamesystem, Transition>) {
+ return gamesystem instanceof ProductGamesystem;
+ }
+
+ onSelectGamesystem(node: FlatNode) {
+ this.selectedGamesystem = node;
+ }
+
+ onContextMenu(event: MouseEvent) {
+ this.electronService.ipcRenderer.send('context-menu', {x: event.x, y: event.y});
+ }
+
+ openGamesystemEditor(node: FlatNode) {
+ const gamesystem: Gamesystem, Transition>| undefined= this.gameModel!.findGamesystem(node.name);
+ if(gamesystem != undefined) {
+ gamesystem.unsaved = false;
+ this.openGamesystemEmitter.emit(gamesystem);
+ }
+ }
+
+ get selectedGamesystemName() {
+ if(this.selectedGamesystem == undefined) {
+ return undefined
+ } else {
+ return this.selectedGamesystem!.name
+ }
+ }
+
+ refresh() {
+ this.dataSource.data = this.gameModel!.gamesystems;
+ }
+}
diff --git a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts
index f8621ee..f0d15da 100644
--- a/src/app/side-overviews/script-account-overview/script-account-overview.component.ts
+++ b/src/app/side-overviews/script-account-overview/script-account-overview.component.ts
@@ -14,17 +14,7 @@ export class ScriptAccountOverviewComponent {
selectedScriptAccount: ScriptAccount | undefined
- constructor(private electronService: ElectronService,
- private zone: NgZone) {
- if(electronService.isElectron) {
- this.electronService.ipcRenderer.on('context-menu', (event: any, message: string) => {
- this.zone.run(() => {
- if(message == "new-scriptaccount") {
- this.onCreateNewScriptAccount()
- }
- })
- })
- }
+ constructor() {
}
onOpenScriptAccount(scriptAccount: ScriptAccount) {
@@ -32,12 +22,6 @@ export class ScriptAccountOverviewComponent {
this.openScriptAccountEmitter.emit(scriptAccount);
}
- onCreateNewScriptAccount() {
- const scriptAccount = this.gameModel!.addScriptAccount("New ScriptAccount");
- if(scriptAccount != undefined) {
- this.openScriptAccountEmitter.emit(scriptAccount);
- }
- }
selectScriptAccount(scriptAccount: ScriptAccount) {