From 685270bd4fc8c33412c7fa6711ac36aad78be749 Mon Sep 17 00:00:00 2001 From: sebastian Date: Mon, 17 Jun 2024 21:57:35 +0200 Subject: [PATCH] Add Implementation of Sequence Editor --- src/app/app.module.ts | 9 +- ...haracter-interaction-editor.component.html | 4 +- ...interaction-sequence-editor.component.html | 141 ++++++++++++++++++ ...interaction-sequence-editor.component.scss | 0 ...eraction-sequence-editor.component.spec.ts | 23 +++ .../interaction-sequence-editor.component.ts | 99 ++++++++++++ .../interactions/InteractionSequences.ts | 21 +++ 7 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.html create mode 100644 src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.scss create mode 100644 src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.spec.ts create mode 100644 src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 097fd05..59925e7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -120,6 +120,9 @@ import { ItemSelectorComponent } from "./editor/interaction-editor/conditions/item-condition-editor/item-selector/item-selector.component"; import {ItemActionEditorComponent} from "./editor/interaction-editor/item-action-editor/item-action-editor.component"; +import { + InteractionSequenceEditorComponent +} from "./editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component"; // AoT requires an exported function for factories const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json'); @@ -159,7 +162,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl GamesystemConditionEditorComponent, ItemConditionEditorComponent, ItemSelectorComponent, - ItemActionEditorComponent + ItemActionEditorComponent, + InteractionSequenceEditorComponent ], imports: [ BrowserModule, @@ -226,7 +230,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl MatExpansionPanelDescription, MatAutocomplete, MatAutocompleteTrigger, - MatNoDataRow + MatNoDataRow, + InteractionSequenceEditorComponent ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/editor/character-editor/character-interaction-editor/character-interaction-editor.component.html b/src/app/editor/character-editor/character-interaction-editor/character-interaction-editor.component.html index 83f1ef2..e6b1ead 100644 --- a/src/app/editor/character-editor/character-interaction-editor/character-interaction-editor.component.html +++ b/src/app/editor/character-editor/character-interaction-editor/character-interaction-editor.component.html @@ -138,11 +138,11 @@ - + Sequence Elements - + diff --git a/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.html b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.html new file mode 100644 index 0000000..0630ad4 --- /dev/null +++ b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.html @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Source + @if(interaction != editedElement) { + {{interaction.sourceCharacter.componentName}} + } @else { + + Source Character + + {{character.componentName}} + + + } + Target + @if(interaction != editedElement) { + @if(interaction.targetCharacter != undefined) { + {{interaction!.targetCharacter!.componentName}} + } @else { +

UNKNOWN CHARACTER

+ } + } @else { + + Target Character + + {{character.componentName}} + + + } +
Label + @if(interaction != editedElement) { + {{interaction.interactionLabel}} + } @else { + + Label + + + } + + + + + + + + + + +
+ + + + Conditions + + + + + + + + + + + + + + + + + + + + Actions + + + + + + + + + + + + + + +
+
diff --git a/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.scss b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.spec.ts b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.spec.ts new file mode 100644 index 0000000..cd9c0fb --- /dev/null +++ b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { InteractionSequenceEditorComponent } from './interaction-sequence-editor.component'; + +describe('InteractionSequenceEditorComponent', () => { + let component: InteractionSequenceEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [InteractionSequenceEditorComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(InteractionSequenceEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.ts b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.ts new file mode 100644 index 0000000..333742b --- /dev/null +++ b/src/app/editor/interaction-editor/interaction-sequence-editor/interaction-sequence-editor.component.ts @@ -0,0 +1,99 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {InteractionSequences} from "../../../project/game-model/interactions/InteractionSequences"; +import {Interaction} from "../../../project/game-model/interactions/Interaction"; +import {MatTableDataSource} from "@angular/material/table"; +import {GameModel} from "../../../project/game-model/GameModel"; +import {Character} from "../../../project/game-model/characters/Character"; +import {MatSnackBar} from "@angular/material/snack-bar"; +import {AbstractInteraction} from "../../../project/game-model/interactions/AbstractInteraction"; +import {ScriptAccountCondition} from "../../../project/game-model/gamesystems/conditions/ScriptAccountCondition"; +import {ScriptAccountAction} from "../../../project/game-model/gamesystems/actions/ScriptAccountAction"; + +@Component({ + selector: 'app-interaction-sequence-editor', + templateUrl: './interaction-sequence-editor.component.html', + styleUrl: './interaction-sequence-editor.component.scss' +}) +export class InteractionSequenceEditorComponent implements OnInit{ + @Input() interactionSequence: InteractionSequences | undefined; + @Input() gameModel: GameModel | undefined + @Input() character: Character | undefined + currentInteractionNode: Interaction | undefined; + + sequenceDatasource = new MatTableDataSource() + displayedColumns: string[] = ['source', 'target', 'label', 'edit', 'delete'] + columnsToDisplayWithExpand = [... this.displayedColumns, 'expand']; + expandedElement: AbstractInteraction | null = null; + editedElement: Interaction | undefined + + constructor(private snackbar: MatSnackBar) { + } + ngOnInit() { + if(this.interactionSequence != undefined) { + this.assignData(); + } + } + + private assignData() { + if(this.currentInteractionNode != undefined) { + this.sequenceDatasource.data = this.interactionSequence!.findInteraction(this.currentInteractionNode)!.children.map(node => node.root); + } else { + this.sequenceDatasource.data = [this.interactionSequence!.rootInteraction.root]; + } + } + + editInteraction(interaction: Interaction) { + this.editedElement = interaction; + } + + submitInteraction() { + if(this.editedElement == undefined) { + return; + } + + if(this.editedElement!.validate(this.character!)) { + this.gameModel!.addCharacterInteraction(this.editedElement); + this.editedElement = undefined; + } else { + this.snackbar.open("Invalid Interaction", "", {duration: 2000}); + } + } + + deleteInteraction(interaction: Interaction) { + if(this.currentInteractionNode != undefined) { + const node = this.interactionSequence?.findInteraction(this.currentInteractionNode); + if(node != undefined) { + node.removeChildInteraction(interaction); + this.assignData(); + } + } + } + + addInteraction() { + const interaction = new Interaction(this.character!, undefined, "") + this.editedElement = interaction; + + const interactions = this.sequenceDatasource.data; + interactions.push(interaction); + this.sequenceDatasource.data = interactions; + } + + onAddCondition(interaction: AbstractInteraction, condition: ScriptAccountCondition) { + interaction!.addConditon(condition); + } + + onDeleteCondition(interaction: AbstractInteraction, condition: ScriptAccountCondition) { + interaction!.removeCondition(condition); + } + + onAddAction(interaction: AbstractInteraction, action: ScriptAccountAction) { + if(interaction instanceof Interaction) { + interaction.addAction(action); + } + } + onRemoveAction(interaction: AbstractInteraction, action: ScriptAccountAction) { + if(interaction instanceof Interaction) { + interaction.removeAction(action); + } + } +} diff --git a/src/app/project/game-model/interactions/InteractionSequences.ts b/src/app/project/game-model/interactions/InteractionSequences.ts index 3670d48..e6bd11d 100644 --- a/src/app/project/game-model/interactions/InteractionSequences.ts +++ b/src/app/project/game-model/interactions/InteractionSequences.ts @@ -34,6 +34,23 @@ export class InteractionSequences extends AbstractInteraction { return validCharacters && validLabel && validSequenceTree; } + findInteraction(currentInteraction: Interaction) { + if(this.rootInteraction.root === currentInteraction) { + return this.rootInteraction; + } else { + let interactionQueue: InteractionSequenceNode[] = this.rootInteraction.children.concat(); + while(interactionQueue.length > 0) { + const currentInteractionNode = interactionQueue.shift()!; + if(currentInteractionNode.root == currentInteraction) { + return currentInteractionNode; + } + interactionQueue = interactionQueue.concat(currentInteractionNode.children); + } + + return undefined; + } + } + } @@ -68,4 +85,8 @@ class InteractionSequenceNode { this.root = root; this.children = children; } + + removeChildInteraction(interaction: Interaction) { + this.children = this.children.filter(child => child.root !== interaction); + } }