|
|
|
|
@@ -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 {
|
|
|
|
|
|