mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-16 16:04:11 +00:00
create basic radial menu
This commit is contained in:
@@ -3,12 +3,12 @@ import {NameLayer} from "./layers/NameLayer";
|
||||
import {TerrainLayer} from "./layers/TerrainLayer";
|
||||
import {TerritoryLayer} from "./layers/TerritoryLayer";
|
||||
import {ClientID} from "../../core/Schemas";
|
||||
import {createCanvas} from "./Utils";
|
||||
import {UILayer} from "./layers/UILayer";
|
||||
import {EventBus} from "../../core/EventBus";
|
||||
import {TransformHandler} from "./TransformHandler";
|
||||
import {Layer} from "./layers/Layer";
|
||||
import {EventsDisplay} from "./layers/EventsDisplay";
|
||||
import {RadialMenu} from "./layers/RadialMenu";
|
||||
|
||||
|
||||
export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus: EventBus, clientID: ClientID): GameRenderer {
|
||||
@@ -19,7 +19,8 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
|
||||
new TerritoryLayer(game, eventBus),
|
||||
new NameLayer(game, game.config().theme(), transformHandler, clientID),
|
||||
new UILayer(eventBus, game, clientID, transformHandler),
|
||||
new EventsDisplay(eventBus, game, clientID)
|
||||
new EventsDisplay(eventBus, game, clientID),
|
||||
new RadialMenu(eventBus),
|
||||
]
|
||||
|
||||
return new GameRenderer(game, eventBus, canvas, transformHandler, layers)
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import {EventBus} from "../../../core/EventBus";
|
||||
import {ContextMenuEvent} from "../../InputHandler";
|
||||
import {Layer} from "./Layer";
|
||||
import * as d3 from 'd3';
|
||||
|
||||
export class RadialMenu implements Layer {
|
||||
private menuElement: d3.Selection<HTMLDivElement, unknown, null, undefined>;
|
||||
private isVisible: boolean = false;
|
||||
private readonly menuItems = [
|
||||
{name: "sub", color: "#3498db"},
|
||||
{name: "color", color: "#e74c3c"},
|
||||
{name: "shape", color: "#2ecc71"},
|
||||
{name: "font", color: "#f39c12"},
|
||||
{name: "stroke", color: "#9b59b6"}
|
||||
];
|
||||
private readonly menuSize = 300; // Increased size
|
||||
private readonly centerButtonSize = 60;
|
||||
|
||||
constructor(private eventBus: EventBus) { }
|
||||
|
||||
init() {
|
||||
this.eventBus.on(ContextMenuEvent, e => this.onContextMenu(e))
|
||||
this.createMenuElement();
|
||||
}
|
||||
|
||||
private createMenuElement() {
|
||||
this.menuElement = d3.select(document.body)
|
||||
.append('div')
|
||||
.style('position', 'fixed')
|
||||
.style('display', 'none')
|
||||
.style('z-index', '9999')
|
||||
.style('touch-action', 'none'); // Prevent default touch actions
|
||||
|
||||
const svg = this.menuElement.append('svg')
|
||||
.attr('width', this.menuSize)
|
||||
.attr('height', this.menuSize)
|
||||
.append('g')
|
||||
.attr('transform', `translate(${this.menuSize / 2},${this.menuSize / 2})`);
|
||||
|
||||
const pie = d3.pie<any>()
|
||||
.value(() => 1)
|
||||
.padAngle(0.03);
|
||||
|
||||
const arc = d3.arc<any>()
|
||||
.innerRadius(this.centerButtonSize + 10)
|
||||
.outerRadius(this.menuSize / 2 - 10);
|
||||
|
||||
const arcs = svg.selectAll('path')
|
||||
.data(pie(this.menuItems))
|
||||
.enter()
|
||||
.append('g');
|
||||
|
||||
arcs.append('path')
|
||||
.attr('d', arc)
|
||||
.attr('fill', d => d.data.color)
|
||||
.on('click', (event, d) => this.handleMenuSelection(d.data.name))
|
||||
.on('touchstart', (event, d) => {
|
||||
event.preventDefault();
|
||||
this.handleMenuSelection(d.data.name);
|
||||
});
|
||||
|
||||
arcs.append('text')
|
||||
.attr('transform', d => `translate(${arc.centroid(d)})`)
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('fill', 'white')
|
||||
.style('font-size', '14px')
|
||||
.text(d => d.data.name);
|
||||
|
||||
// Add center button
|
||||
svg.append('circle')
|
||||
.attr('r', this.centerButtonSize)
|
||||
.attr('fill', '#2c3e50')
|
||||
.on('click', () => this.handleCenterButtonClick())
|
||||
.on('touchstart', (event) => {
|
||||
event.preventDefault();
|
||||
this.handleCenterButtonClick();
|
||||
});
|
||||
|
||||
svg.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dy', '0.3em')
|
||||
.attr('fill', 'white')
|
||||
.style('font-size', '14px')
|
||||
.text('Close');
|
||||
}
|
||||
|
||||
tick() {
|
||||
// Update logic if needed
|
||||
}
|
||||
|
||||
render(context: CanvasRenderingContext2D) {
|
||||
// No need to render anything on the canvas
|
||||
}
|
||||
|
||||
shouldTransform(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
private onContextMenu(event: ContextMenuEvent) {
|
||||
console.log('on context menu')
|
||||
|
||||
if (this.isVisible) {
|
||||
this.hideRadialMenu()
|
||||
} else {
|
||||
this.showRadialMenu(event.x, event.y);
|
||||
}
|
||||
}
|
||||
|
||||
private showRadialMenu(x: number, y: number) {
|
||||
this.menuElement
|
||||
.style('left', `${x - this.menuSize / 2}px`)
|
||||
.style('top', `${y - this.menuSize / 2}px`)
|
||||
.style('display', 'block');
|
||||
this.isVisible = true;
|
||||
}
|
||||
|
||||
private hideRadialMenu() {
|
||||
this.menuElement.style('display', 'none');
|
||||
this.isVisible = false;
|
||||
}
|
||||
|
||||
private handleMenuSelection(action: string) {
|
||||
console.log(`Selected action: ${action}`);
|
||||
this.hideRadialMenu();
|
||||
}
|
||||
|
||||
private handleCenterButtonClick() {
|
||||
console.log('Center button clicked');
|
||||
this.hideRadialMenu();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import {EventBus, GameEvent} from "../../../core/EventBus";
|
||||
import {WinEvent} from "../../../core/execution/WinCheckExecution";
|
||||
import {AllianceRequest, AllianceRequestReplyEvent, Game, Player} from "../../../core/game/Game";
|
||||
import {ClientID} from "../../../core/Schemas";
|
||||
import {RightClickEvent} from "../../InputHandler";
|
||||
import {ContextMenuEvent} from "../../InputHandler";
|
||||
import {Layer} from "./Layer";
|
||||
import {TransformHandler} from "../TransformHandler";
|
||||
import {MessageType} from "./EventsDisplay";
|
||||
@@ -74,7 +74,7 @@ export class UILayer implements Layer {
|
||||
this.createWinModal()
|
||||
this.initRightClickMenu()
|
||||
this.eventBus.on(WinEvent, (e) => this.onWinEvent(e))
|
||||
this.eventBus.on(RightClickEvent, (e) => this.onRightClick(e))
|
||||
this.eventBus.on(ContextMenuEvent, (e) => this.onRightClick(e))
|
||||
}
|
||||
|
||||
initRightClickMenu() {
|
||||
@@ -236,7 +236,7 @@ export class UILayer implements Layer {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
private onRightClick(e: RightClickEvent) {
|
||||
private onRightClick(e: ContextMenuEvent) {
|
||||
const cell = this.transformHandler.screenToWorldCoordinates(e.x, e.y)
|
||||
if (!this.game.isOnMap(cell)) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user