From b6261bb420751ee414887222723f0e6b1da004db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Wed, 6 Jun 2018 19:09:31 +0200 Subject: [PATCH] Fixed map screen not being interactive --- TODO.md | 1 + src/ui/battle/LogProcessor.ts | 3 +- src/ui/common/UIBuilder.ts | 9 ++ src/ui/common/UIComponent.ts | 7 +- src/ui/common/UIContainer.ts | 12 ++ src/ui/common/UIConversation.ts | 147 +++++++++++++++-------- src/ui/common/UIOverlay.ts | 21 ++++ src/ui/intro/IntroSteps.ts | 7 +- src/ui/map/MissionConversationDisplay.ts | 4 +- src/ui/map/UniverseMapView.ts | 3 +- 10 files changed, 153 insertions(+), 61 deletions(-) create mode 100644 src/ui/common/UIOverlay.ts diff --git a/TODO.md b/TODO.md index 2847146..d372cfe 100644 --- a/TODO.md +++ b/TODO.md @@ -8,6 +8,7 @@ Phaser 3 migration * Fit the game in window size * Fix top-right messages positions * Fix valuebar requiring to be in root display list +* Restore unit tests about boundaries (in UITools) Menu/settings/saves ------------------- diff --git a/src/ui/battle/LogProcessor.ts b/src/ui/battle/LogProcessor.ts index 55149ca..27708f1 100644 --- a/src/ui/battle/LogProcessor.ts +++ b/src/ui/battle/LogProcessor.ts @@ -225,7 +225,8 @@ module TK.SpaceTac.UI { return { foreground: async () => { if (reaction instanceof PersonalityReactionConversation) { - let conversation = UIConversation.newFromPieces(this.view, reaction.messages); + let builder = new UIBuilder(this.view, this.view.layer_overlay); + let conversation = UIConversation.newFromPieces(builder, reaction.messages); await conversation.waitEnd(); } else { console.warn("[LogProcessor] Unknown personality reaction type", reaction); diff --git a/src/ui/common/UIBuilder.ts b/src/ui/common/UIBuilder.ts index 5361adf..6fe1891 100644 --- a/src/ui/common/UIBuilder.ts +++ b/src/ui/common/UIBuilder.ts @@ -226,6 +226,15 @@ module TK.SpaceTac.UI { return result; } + /** + * Add a full-view capturing overlay + */ + overlay(options: UIOverlayOptions): UIOverlay { + let result = new UIOverlay(this.view, options); + this.add(result); + return result; + } + /** * Change the content of an component * diff --git a/src/ui/common/UIComponent.ts b/src/ui/common/UIComponent.ts index 2217458..2628c9c 100644 --- a/src/ui/common/UIComponent.ts +++ b/src/ui/common/UIComponent.ts @@ -68,7 +68,7 @@ module TK.SpaceTac.UI { /** * Draw a background */ - drawBackground(fill: number, border?: number, border_width = 0, alpha = 1, mouse_capture?: Function) { + drawBackground(fill: number, border?: number, border_width = 0, alpha = 1) { if (this.background) { this.background.destroy(); } @@ -76,11 +76,6 @@ module TK.SpaceTac.UI { let rect = new Phaser.Geom.Rectangle(0, 0, this.width, this.height); this.background = this.addInternalChild(new UIGraphics(this.view, "background")); this.background.addRectangle(rect, fill, border_width, border, alpha); - - if (mouse_capture) { - this.background.setInteractive(rect, Phaser.Geom.Rectangle.Contains); - this.background.on("pointerup", () => mouse_capture()); - } } /** diff --git a/src/ui/common/UIContainer.ts b/src/ui/common/UIContainer.ts index 1e04018..3f91bc7 100644 --- a/src/ui/common/UIContainer.ts +++ b/src/ui/common/UIContainer.ts @@ -27,5 +27,17 @@ module TK.SpaceTac.UI { output.setTo(result.x, result.y, result.width, result.height); return output; } + + /** + * Overload of setVisible, with fading support + */ + setVisible(visible: boolean, duration = 0): this { + if (duration) { + (this.scene).animations.setVisible(this, visible, duration); + } else { + super.setVisible(visible); + } + return this; + } } } diff --git a/src/ui/common/UIConversation.ts b/src/ui/common/UIConversation.ts index 45af7f2..207d286 100644 --- a/src/ui/common/UIConversation.ts +++ b/src/ui/common/UIConversation.ts @@ -39,64 +39,98 @@ module TK.SpaceTac.UI { /** * Rectangle to display a message that may appear progressively, as in conversations */ - export class UIConversationMessage extends UIComponent { - constructor(parent: BaseView | UIComponent, width: number, height: number, message: string, style = new UIConversationStyle()) { - super(parent, width, height); + export class UIConversationMessage { + private container: UIContainer - this.drawBackground(style.background, style.border, style.border_width, style.alpha); + constructor(private builder: UIBuilder, private width: number, private height: number, message: string, style = new UIConversationStyle(), forward?: Function) { + this.container = builder.container("conversation-message"); - let builder = this.builder.styled(style.text); - if (!style.center) { - builder = builder.styled({ center: false, vcenter: false }); - } - - let offset = 0; - if (style.image_size && style.image) { - offset = style.image_size + style.padding; - width -= offset; - - let ioffset = style.padding + Math.floor(style.image_size / 2); - builder.image(style.image, ioffset, ioffset, true); - - if (style.image_caption) { - let text_size = Math.ceil(style.text.size ? style.text.size * 0.6 : 16); - builder.text(style.image_caption, ioffset, style.padding + style.image_size + text_size, { - size: text_size, - center: true - }); + builder.styled(style.text).in(this.container, builder => { + if (!style.center) { + builder = builder.styled({ center: false, vcenter: false }); } - } - let text = builder.text(message, offset + (style.center ? width / 2 : style.padding), style.center ? height / 2 : style.padding, { - width: width - style.padding * 2 + builder.graphics("background").addRectangle({ x: 0, y: 0, width: width, height: height }, + style.background, style.border_width, style.border, style.alpha); + + let offset = 0; + if (style.image_size && style.image) { + offset = style.image_size + style.padding; + width -= offset; + + let ioffset = style.padding + Math.floor(style.image_size / 2); + builder.image(style.image, ioffset, ioffset, true); + + if (style.image_caption) { + let text_size = Math.ceil(style.text.size ? style.text.size * 0.6 : 16); + builder.text(style.image_caption, ioffset, style.padding + style.image_size + text_size, { + size: text_size, + center: true + }); + } + } + + let text = builder.text(message, offset + (style.center ? width / 2 : style.padding), style.center ? height / 2 : style.padding, { + width: width - style.padding * 2 + }); + + /*let i = 0; + let colorchar = () => { + text.clearColors(); + if (i < message.length) { + text.addColor("transparent", i); + i++; + this.view.timer.schedule(10, colorchar); + } + } + colorchar();*/ + + if (forward) { + builder.button("common-arrow", this.width - 30, this.height - 30, forward, "Next", undefined, { center: true }); + } }); + } - /*let i = 0; - let colorchar = () => { - text.clearColors(); - if (i < message.length) { - text.addColor("transparent", i); - i++; - this.view.timer.schedule(10, colorchar); - } - } - colorchar();*/ + destroy() { + this.container.destroy(); + } + + positionRelative(relx: number, rely: number) { + let view = this.builder.view; + let rx = (view.getWidth() - this.width) * relx; + let ry = (view.getHeight() - this.height) * rely; + this.container.setPosition(Math.round(rx), Math.round(ry)); + } + + setVisible(visible: boolean, duration = 0): void { + this.container.setVisible(visible, duration); } } /** * Display of an active conversation (sequence of messages) */ - export class UIConversation extends UIComponent { + export class UIConversation { + private view: BaseView + private builder: UIBuilder + private container: UIContainer + private overlay: UIOverlay + private message?: UIConversationMessage private step = -1 private on_step: UIConversationCallback private ended = false private on_end = new Phaser.Events.EventEmitter() - constructor(parent: BaseView, on_step: UIConversationCallback) { - super(parent, parent.getWidth(), parent.getHeight()); + constructor(builder: UIBuilder, on_step: UIConversationCallback) { + this.view = builder.view; - this.drawBackground(0x404450, undefined, undefined, 0.7, () => this.forward()); + this.container = builder.container("conversation"); + this.builder = builder.in(this.container); + this.overlay = this.builder.overlay({ + color: 0x404450, + alpha: 0.7, + on_click: () => this.forward() + }); this.setVisible(false); this.on_step = on_step; @@ -104,13 +138,33 @@ module TK.SpaceTac.UI { this.forward(); } + /** + * Clear the content of previous message, if any + */ + clearContent(): void { + if (this.message) { + this.message.destroy(); + this.message = undefined; + } + } + + /** + * Set the global visibility + */ + setVisible(visible: boolean, duration = 0): void { + this.container.setVisible(visible, duration); + } + + /** + * Destroy the conversation handler + */ destroy() { if (!this.ended) { this.ended = true; this.on_end.emit("done"); } - super.destroy(); + this.container.destroy(); } /** @@ -132,9 +186,8 @@ module TK.SpaceTac.UI { setCurrentMessage(style: UIConversationStyle, content: string, width: number, height: number, relx: number, rely: number): void { this.clearContent(); - let message = new UIConversationMessage(this, width, height, content, style); - message.addButton(width - 60, height - 60, () => this.forward(), "common-arrow"); - message.setPositionInsideParent(relx, rely); + this.message = new UIConversationMessage(this.builder, width, height, content, style, () => this.forward()); + this.message.positionRelative(relx, rely); this.setVisible(true, 700); } @@ -151,7 +204,7 @@ module TK.SpaceTac.UI { style.image_size = 256; let own = this.view.gameui.session.player.is(ship.fleet.player); - this.setCurrentMessage(style, content, 900, 300, own ? 0.1 : 0.9, own ? 0.2 : 0.8); + this.setCurrentMessage(style, content, 900, 310, own ? 0.1 : 0.9, own ? 0.2 : 0.8); } /** @@ -167,8 +220,8 @@ module TK.SpaceTac.UI { /** * Convenience to create a conversation from a list of pieces */ - static newFromPieces(view: BaseView, pieces: UIConversationPiece[]): UIConversation { - let result = new UIConversation(view, (conversation, step) => { + static newFromPieces(builder: UIBuilder, pieces: UIConversationPiece[]): UIConversation { + let result = new UIConversation(builder, (conversation, step) => { if (step >= pieces.length) { return false; } else { diff --git a/src/ui/common/UIOverlay.ts b/src/ui/common/UIOverlay.ts new file mode 100644 index 0000000..e62f1bb --- /dev/null +++ b/src/ui/common/UIOverlay.ts @@ -0,0 +1,21 @@ +module TK.SpaceTac.UI { + export interface UIOverlayOptions { + color: number, + alpha?: number, + on_click?: Function + } + + /** + * UI component to display a semi-transparent overlay that fills the whole view and captures inputs + */ + export class UIOverlay extends UIGraphics { + constructor(view: BaseView, options: UIOverlayOptions) { + super(view, "overlay"); + + let rect = { x: 0, y: 0, width: view.getWidth(), height: view.getHeight() }; + this.addRectangle(rect, options.color, undefined, undefined, options.alpha); + this.setInteractive(rect, (rect: Phaser.Geom.Rectangle, x: number, y: number) => Phaser.Geom.Rectangle.Contains(rect, x, y) && UITools.isVisible(this)); + this.on("pointerup", options.on_click || nop); + } + } +} diff --git a/src/ui/intro/IntroSteps.ts b/src/ui/intro/IntroSteps.ts index ec092b8..818c6de 100644 --- a/src/ui/intro/IntroSteps.ts +++ b/src/ui/intro/IntroSteps.ts @@ -152,9 +152,10 @@ module TK.SpaceTac.UI { return () => { let style = new UIConversationStyle(); style.center = true; - let display = new UIConversationMessage(this.view, 900, 200, message, style); - display.setPositionInsideParent(0.5, 0.9); - display.moveToLayer(this.getLayer(layer, clear)); + let parent = this.getLayer(layer, clear); + let builder = new UIBuilder(this.view, parent); + let display = new UIConversationMessage(builder, 900, 200, message, style); + display.positionRelative(0.5, 0.9); display.setVisible(false); display.setVisible(true, 500); } diff --git a/src/ui/map/MissionConversationDisplay.ts b/src/ui/map/MissionConversationDisplay.ts index 9cf7509..5aee3c9 100644 --- a/src/ui/map/MissionConversationDisplay.ts +++ b/src/ui/map/MissionConversationDisplay.ts @@ -8,8 +8,8 @@ module TK.SpaceTac.UI { dialog: MissionPartConversation | null = null on_ended: Function | null = null - constructor(parent: BaseView) { - super(parent, () => true); + constructor(builder: UIBuilder) { + super(builder, () => true); } /** diff --git a/src/ui/map/UniverseMapView.ts b/src/ui/map/UniverseMapView.ts index 7772aee..01bffe5 100644 --- a/src/ui/map/UniverseMapView.ts +++ b/src/ui/map/UniverseMapView.ts @@ -116,8 +116,7 @@ module TK.SpaceTac.UI { this.character_sheet = new CharacterSheet(this, CharacterSheetMode.EDITION); this.character_sheet.moveToLayer(this.layer_overlay); - this.conversation = new MissionConversationDisplay(this); - this.conversation.moveToLayer(this.layer_overlay); + this.conversation = new MissionConversationDisplay(builder.in(this.layer_overlay)); this.audio.startMusic("spring-thaw");