diff --git a/src/scenes/UIScene.ts b/src/scenes/UIScene.ts index bcd8fb5..b34f428 100644 --- a/src/scenes/UIScene.ts +++ b/src/scenes/UIScene.ts @@ -22,6 +22,10 @@ export class UIScene extends Phaser.Scene { private farmToolText!: Phaser.GameObjects.Text private coordsText!: Phaser.GameObjects.Text private popText!: Phaser.GameObjects.Text + private contextMenuGroup!: Phaser.GameObjects.Group + private contextMenuVisible = false + private inBuildMode = false + private inFarmMode = false constructor() { super({ key: 'UI' }) } @@ -47,6 +51,22 @@ export class UIScene extends Phaser.Scene { .on('down', () => this.toggleVillagerPanel()) this.scale.on('resize', () => this.repositionUI()) + + this.input.mouse!.disableContextMenu() + this.contextMenuGroup = this.add.group() + + this.input.on('pointerdown', (ptr: Phaser.Input.Pointer) => { + if (ptr.rightButtonDown()) { + if (!this.inBuildMode && !this.inFarmMode && !this.buildMenuVisible && !this.villagerPanelVisible) { + this.showContextMenu(ptr.x, ptr.y) + } + } else if (this.contextMenuVisible) { + this.hideContextMenu() + } + }) + + this.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.ESC) + .on('down', () => this.hideContextMenu()) } update(_t: number, delta: number): void { @@ -248,6 +268,7 @@ export class UIScene extends Phaser.Scene { this.buildModeText = this.add.text(10, 10, '', { fontSize: '13px', color: '#ffff00', fontFamily: 'monospace', backgroundColor: '#00000099', padding: { x: 8, y: 4 } }).setScrollFactor(0).setDepth(100).setVisible(false) } private onBuildModeChanged(active: boolean, building: BuildingType): void { + this.inBuildMode = active this.buildModeText.setText(active ? `🏗 BUILD: ${building.toUpperCase()} [RMB/ESC cancel]` : '').setVisible(active) } @@ -257,6 +278,7 @@ export class UIScene extends Phaser.Scene { this.farmToolText = this.add.text(10, 44, '', { fontSize: '13px', color: '#aaffaa', fontFamily: 'monospace', backgroundColor: '#00000099', padding: { x: 8, y: 4 } }).setScrollFactor(0).setDepth(100).setVisible(false) } private onFarmToolChanged(tool: FarmingTool, label: string): void { + this.inFarmMode = tool !== 'none' this.farmToolText.setText(tool === 'none' ? '' : `[F] Farm: ${label} [RMB cancel]`).setVisible(tool !== 'none') } @@ -272,6 +294,69 @@ export class UIScene extends Phaser.Scene { this.coordsText.setText(`Tile: ${pos.tileX}, ${pos.tileY}`) } + // ─── Context Menu ───────────────────────────────────────────────────────── + + /** + * Shows the right-click context menu at the given screen coordinates. + * Any previously open context menu is closed first. + * @param x - Screen x position of the pointer + * @param y - Screen y position of the pointer + */ + private showContextMenu(x: number, y: number): void { + this.hideContextMenu() + + const menuW = 150 + const btnH = 32 + const menuH = 8 + 2 * (btnH + 6) - 6 + 8 + + const mx = Math.min(x, this.scale.width - menuW - 4) + const my = Math.min(y, this.scale.height - menuH - 4) + + const bg = this.add.rectangle(mx, my, menuW, menuH, 0x000000, 0.88) + .setOrigin(0, 0).setScrollFactor(0).setDepth(300) + this.contextMenuGroup.add(bg) + + const entries: { label: string; action: () => void }[] = [ + { + label: '🏗 Build', + action: () => { this.hideContextMenu(); this.scene.get('Game').events.emit('uiRequestBuildMenu') }, + }, + { + label: '👥 Folks', + action: () => { this.hideContextMenu(); this.toggleVillagerPanel() }, + }, + ] + + entries.forEach((entry, i) => { + const by = my + 8 + i * (btnH + 6) + const btn = this.add.rectangle(mx + 8, by, menuW - 16, btnH, 0x1a3a1a, 0.9) + .setOrigin(0, 0).setScrollFactor(0).setDepth(301).setInteractive() + btn.on('pointerover', () => btn.setFillStyle(0x2d6a4f, 0.9)) + btn.on('pointerout', () => btn.setFillStyle(0x1a3a1a, 0.9)) + btn.on('pointerdown', entry.action) + this.contextMenuGroup.add(btn) + this.contextMenuGroup.add( + this.add.text(mx + 16, by + btnH / 2, entry.label, { + fontSize: '13px', color: '#ffffff', fontFamily: 'monospace', + }).setOrigin(0, 0.5).setScrollFactor(0).setDepth(302) + ) + }) + + this.contextMenuVisible = true + this.scene.get('Game').events.emit('uiMenuOpen') + } + + /** + * Closes and destroys the context menu if it is currently visible. + */ + private hideContextMenu(): void { + if (!this.contextMenuVisible) return + this.contextMenuGroup.destroy(true) + this.contextMenuGroup = this.add.group() + this.contextMenuVisible = false + this.scene.get('Game').events.emit('uiMenuClose') + } + // ─── Resize ─────────────────────────────────────────────────────────────── private repositionUI(): void {