mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
- Toggle expanded minimap mode - Choose between round and square minimap shapes - `gui.session.minimap.position`, lets you switch between two positioning modes: panel-left and screen-left - `gui.session.minimap.size`, change size between 1.0 and 2.0, default is 1.0.
334 lines
11 KiB
JavaScript
334 lines
11 KiB
JavaScript
/**
|
|
* This class is concerned with managing the different elements of the minimap panel.
|
|
*/
|
|
class MiniMapPanel
|
|
{
|
|
constructor(playerViewControl, diplomacyColors, idleWorkerClasses)
|
|
{
|
|
this.loadConfig();
|
|
|
|
this.themes = {
|
|
"square": {
|
|
"panelSprite": "mapPanel",
|
|
"circleSprite": "stretched:session/minimap_circle_modern.png",
|
|
"flare": {
|
|
"baseSize": "4 4 113 119",
|
|
"anchors": ["left", "top"],
|
|
"sprite": "stretched:session/minimap-player-flare.png",
|
|
"sprite_over": "stretched:session/minimap-player-flare-highlight.png",
|
|
"sprite_disabled": "stretched:session/minimap-player-flare-disabled.png",
|
|
"mouse_event_mask": "texture:session/minimap-player-flare.png",
|
|
"observer_sprite": "stretched:session/minimap-observer-flare.png",
|
|
"observer_sprite_over": "stretched:session/minimap-observer-flare-highlight.png"
|
|
},
|
|
"diplomacy": {
|
|
"baseSize": "4 100%-121 119 100%-4",
|
|
"anchors": ["left", "bottom"],
|
|
"sprite_on": "stretched:session/minimap-diplomacy-on.png",
|
|
"sprite_off": "stretched:session/minimap-diplomacy-off.png",
|
|
"sprite_on_over": "stretched:session/minimap-diplomacy-on-highlight.png",
|
|
"sprite_off_over": "stretched:session/minimap-diplomacy-off-highlight.png",
|
|
"mouse_event_mask": "texture:session/minimap-diplomacy-on.png"
|
|
},
|
|
"idle": {
|
|
"baseSize": "100%-119 100%-121 100%-4 100%-4",
|
|
"anchors": ["right", "bottom"],
|
|
"sprite": "stretched:session/minimap-idle.png",
|
|
"sprite_over": "stretched:session/minimap-idle-highlight.png",
|
|
"sprite_disabled": "stretched:session/minimap-idle-disabled.png",
|
|
"mouse_event_mask": "texture:session/minimap-idle.png"
|
|
},
|
|
"idleText": {
|
|
"baseSize": "100%-119 100%-121 100%-3 100%-2",
|
|
"anchors": ["right", "bottom"],
|
|
"text_align": "right",
|
|
"text_valign": "bottom"
|
|
}
|
|
},
|
|
"round": {
|
|
"panelSprite": "",
|
|
"mapOffset": -10,
|
|
"circleSprite": "stretched:session/minimap_expanded_circle.png",
|
|
"flare": {
|
|
"baseSize": "100%-48 100%-28 100%-24 100%-4",
|
|
"sprite": "stretched:session/minimap-round-flare.png",
|
|
"sprite_over": "stretched:session/minimap-round-flare-highlight.png",
|
|
"sprite_disabled": "stretched:session/minimap-round-flare-disabled.png",
|
|
"mouse_event_mask": "texture:session/minimap-round-flare.png",
|
|
"observer_sprite": "stretched:session/minimap-round-observer-flare.png",
|
|
"observer_sprite_over": "stretched:session/minimap-round-observer-flare-highlight.png"
|
|
},
|
|
"diplomacy": {
|
|
"baseSize": "22 100%-28 46 100%-4",
|
|
"sprite_on": "stretched:session/minimap-round-diplomacy-on.png",
|
|
"sprite_off": "stretched:session/minimap-round-diplomacy-off.png",
|
|
"sprite_on_over": "stretched:session/minimap-round-diplomacy-on-highlight.png",
|
|
"sprite_off_over": "stretched:session/minimap-round-diplomacy-off-highlight.png",
|
|
"mouse_event_mask": "texture:session/minimap-round-diplomacy-off.png"
|
|
},
|
|
"idle": {
|
|
"baseSize": "100%-28 100%-46 100%-4 100%-22",
|
|
"sprite": "stretched:session/minimap-round-idle.png",
|
|
"sprite_over": "stretched:session/minimap-round-idle-highlight.png",
|
|
"sprite_disabled": "stretched:session/minimap-round-idle-disabled.png",
|
|
"mouse_event_mask": "texture:session/minimap-round-idle.png"
|
|
},
|
|
"idleText": {
|
|
"baseSize": "100%-28 100%-46 100%-4 100%-22",
|
|
"text_align": "center",
|
|
"text_valign": "center"
|
|
}
|
|
}
|
|
};
|
|
|
|
this.expandedState = {
|
|
"panelSprite": "",
|
|
"hideButtons": true,
|
|
"circleSprite": "stretched:session/minimap_expanded_circle.png",
|
|
"computeLayout": this.computeExpandedLayout.bind(this)
|
|
};
|
|
|
|
this.panel = Engine.GetGUIObjectByName("minimapPanel");
|
|
this.minimapCircle = Engine.GetGUIObjectByName("minimapCircle");
|
|
this.minimapMap = Engine.GetGUIObjectByName("minimap");
|
|
this.minimapBackgroundTexture = Engine.GetGUIObjectByName("minimapBackgroundTexture");
|
|
this.session = Engine.GetGUIObjectByName("session");
|
|
this.supplementalPanel = Engine.GetGUIObjectByName("supplementalSelectionDetails");
|
|
this.idleWorkerButton = new MiniMapIdleWorkerButton(playerViewControl, idleWorkerClasses);
|
|
this.totalNumberIdleWorkers = Engine.GetGUIObjectByName("totalNumberIdleWorkers");
|
|
this.flareButton = new MiniMapFlareButton(playerViewControl);
|
|
this.miniMap = new MiniMap();
|
|
this.diplomacyColors = diplomacyColors;
|
|
this.diplomacyColorsButton = new MiniMapDiplomacyColorsButton(diplomacyColors, this.themes[this.shape].diplomacy);
|
|
const panelRect = this.panel.getComputedSize();
|
|
this.defaultPanelWidth = panelRect.right - panelRect.left;
|
|
this.defaultPanelHeight = panelRect.bottom - panelRect.top;
|
|
playerViewControl.registerViewedPlayerChangeHandler(this.rebuild.bind(this));
|
|
registerHotkeyChangeHandler(this.rebuild.bind(this));
|
|
registerConfigChangeHandler(this.onConfigChange.bind(this));
|
|
Engine.SetGlobalHotkey("session.minimap.expand.toggle", "Press", this.toggleExpanded.bind(this));
|
|
this.expanded = false;
|
|
this.applyLayout();
|
|
}
|
|
|
|
loadConfig()
|
|
{
|
|
this.position = Engine.ConfigDB_GetValue("user", "gui.session.minimap.position");
|
|
this.sizeScale = Engine.ConfigDB_GetValue("user", "gui.session.minimap.size");
|
|
this.shape = Engine.ConfigDB_GetValue("user", "gui.session.minimap.shape") || "square";
|
|
}
|
|
|
|
get currentTheme()
|
|
{
|
|
if (this.expanded)
|
|
return this.expandedState;
|
|
|
|
return {
|
|
...this.themes[this.shape],
|
|
"hideButtons": false,
|
|
"computeLayout": this.computeNormalLayout.bind(this)
|
|
};
|
|
}
|
|
|
|
isObserver()
|
|
{
|
|
return g_IsObserver;
|
|
}
|
|
|
|
toggleExpanded()
|
|
{
|
|
this.expanded = !this.expanded;
|
|
this.applyLayout();
|
|
}
|
|
|
|
onConfigChange(changes)
|
|
{
|
|
if (![...changes].some(change =>
|
|
change == "gui.session.minimap.position" ||
|
|
change == "gui.session.minimap.size" ||
|
|
change == "gui.session.minimap.shape"))
|
|
return;
|
|
this.loadConfig();
|
|
this.applyLayout();
|
|
}
|
|
|
|
applyLayout()
|
|
{
|
|
const theme = this.currentTheme;
|
|
|
|
this.panel.size = theme.computeLayout();
|
|
this.panel.sprite = theme.panelSprite;
|
|
this.minimapCircle.sprite = theme.circleSprite;
|
|
this.minimapCircle.hidden = false;
|
|
const offset = theme.mapOffset ?? 0;
|
|
this.minimapBackgroundTexture.size = `4 ${4 + offset} 100%-4 100%-${4 - offset}`;
|
|
this.minimapCircle.size = `4 ${4 + offset} 100%-4 100%-${4 - offset}`;
|
|
this.minimapMap.size = `8 ${8 + offset} 100%-8 100%-${8 - offset}`;
|
|
this.refreshButtons(theme);
|
|
}
|
|
|
|
refreshButtons(theme)
|
|
{
|
|
const hidden = theme.hideButtons;
|
|
this.flareButton.flareButton.hidden = hidden;
|
|
this.idleWorkerButton.idleWorkerButton.hidden = hidden;
|
|
this.idleWorkerButton.totalNumberIdleWorkers.hidden = hidden;
|
|
this.diplomacyColorsButton.diplomacyColorsButton.hidden = hidden;
|
|
if (hidden)
|
|
return;
|
|
const scale = parseFloat(this.sizeScale) || 1.0;
|
|
const flareConfig = this.isObserver() && theme.flare?.observer_sprite ?
|
|
{ ...theme.flare, "sprite": theme.flare.observer_sprite, "sprite_over": theme.flare.observer_sprite_over } :
|
|
theme.flare;
|
|
this.applyButtonSprites(this.flareButton.flareButton, flareConfig);
|
|
this.applyScaledSize(this.flareButton.flareButton, theme.flare, scale);
|
|
this.applyButtonSprites(this.idleWorkerButton.idleWorkerButton, theme.idle);
|
|
this.applyScaledSize(this.idleWorkerButton.idleWorkerButton, theme.idle, scale);
|
|
this.applyScaledSize(this.totalNumberIdleWorkers, theme.idleText, scale);
|
|
if (theme.idleText.text_align !== undefined)
|
|
this.totalNumberIdleWorkers.text_align = theme.idleText.text_align;
|
|
if (theme.idleText.text_valign !== undefined)
|
|
this.totalNumberIdleWorkers.text_valign = theme.idleText.text_valign;
|
|
this.diplomacyColorsButton.theme = theme.diplomacy;
|
|
this.applyButtonSprites(this.diplomacyColorsButton.diplomacyColorsButton, theme.diplomacy);
|
|
this.diplomacyColorsButton.onDiplomacyColorsChange(this.diplomacyColors.isEnabled?.() ?? false);
|
|
this.applyScaledSize(this.diplomacyColorsButton.diplomacyColorsButton, theme.diplomacy, scale);
|
|
}
|
|
|
|
applyButtonSprites(button, config)
|
|
{
|
|
if (!config)
|
|
return;
|
|
if (config.mouse_event_mask !== undefined)
|
|
button.mouse_event_mask = config.mouse_event_mask;
|
|
if (!config.sprite)
|
|
return;
|
|
button.sprite = config.sprite;
|
|
if (config.sprite_over !== undefined)
|
|
button.sprite_over = config.sprite_over;
|
|
if (config.sprite_disabled !== undefined)
|
|
button.sprite_disabled = config.sprite_disabled;
|
|
}
|
|
|
|
applyScaledSize(element, cfg, scale)
|
|
{
|
|
if (!cfg)
|
|
return;
|
|
const original = cfg.baseSize.split(/\s+/);
|
|
const parts = original.map(part =>
|
|
{
|
|
const match = part.match(/^100%-(\d+)$/);
|
|
if (match)
|
|
return `100%-${Math.round(+match[1] * scale)}`;
|
|
if (/^-?\d+$/.test(part))
|
|
return `${Math.round(+part * scale)}`;
|
|
return part;
|
|
});
|
|
if (!cfg.anchors)
|
|
{
|
|
element.size = parts.join(" ");
|
|
return;
|
|
}
|
|
const scaled = { "left": parts[0], "top": parts[1], "right": parts[2], "bottom": parts[3] };
|
|
|
|
for (const anchor of cfg.anchors)
|
|
{
|
|
const idx = ["left", "top", "right", "bottom"].indexOf(anchor);
|
|
scaled[anchor] = original[idx];
|
|
}
|
|
element.size = [scaled.left, scaled.top, scaled.right, scaled.bottom].join(" ");
|
|
}
|
|
|
|
computeNormalLayout()
|
|
{
|
|
return this.position === "panel-left" ?
|
|
this.computePanelLeftLayout() :
|
|
this.computeScreenLeftLayout();
|
|
}
|
|
|
|
getScaledPanelSize()
|
|
{
|
|
const scale = parseFloat(this.sizeScale) || 1.0;
|
|
return {
|
|
"width": Math.round(this.defaultPanelWidth * scale),
|
|
"height": Math.round(this.defaultPanelHeight * scale)
|
|
};
|
|
}
|
|
|
|
computePanelLeftLayout()
|
|
{
|
|
const { width, height } = this.getScaledPanelSize();
|
|
const parentRect = this.panel.parent.getComputedSize();
|
|
const parentHeight = parentRect.bottom - parentRect.top;
|
|
return {
|
|
"left": this.defaultPanelWidth - width,
|
|
"top": parentHeight - height,
|
|
"right": this.defaultPanelWidth,
|
|
"bottom": parentHeight
|
|
};
|
|
}
|
|
|
|
computeScreenLeftLayout()
|
|
{
|
|
const { width, height } = this.getScaledPanelSize();
|
|
const windowSize = this.session.getComputedSize();
|
|
const parentRect = this.panel.parent.getComputedSize();
|
|
const screenTop = (windowSize.bottom - windowSize.top) - height;
|
|
const maxRight = this.supplementalPanel.getComputedSize().left;
|
|
let left = 0;
|
|
let right = width;
|
|
if (right > maxRight)
|
|
{
|
|
right = maxRight;
|
|
left = right - width;
|
|
}
|
|
return {
|
|
"left": left - parentRect.left,
|
|
"top": screenTop - parentRect.top,
|
|
"right": right - parentRect.left,
|
|
"bottom": screenTop + height - parentRect.top
|
|
};
|
|
}
|
|
|
|
computeExpandedLayout()
|
|
{
|
|
const windowSize = this.session.getComputedSize();
|
|
const scale = 0.55;
|
|
const marginLeft = 20;
|
|
const verticalOffset = -40;
|
|
const screenHeight = windowSize.bottom - windowSize.top;
|
|
const size = Math.floor(screenHeight * scale);
|
|
const screenTop = Math.floor((screenHeight - size) / 2) + verticalOffset;
|
|
const parentRect = this.panel.parent.getComputedSize();
|
|
const top = screenTop - parentRect.top;
|
|
const left = marginLeft - parentRect.left;
|
|
return {
|
|
"left": left,
|
|
"top": top,
|
|
"right": left + size,
|
|
"bottom": top + size
|
|
};
|
|
}
|
|
|
|
flare(target, playerID)
|
|
{
|
|
return this.miniMap.flare(target, playerID);
|
|
}
|
|
|
|
isMouseOverMiniMap()
|
|
{
|
|
return this.miniMap.isMouseOverMiniMap();
|
|
}
|
|
|
|
rebuild()
|
|
{
|
|
this.applyLayout();
|
|
this.setCivBackgroundTexture();
|
|
}
|
|
|
|
setCivBackgroundTexture()
|
|
{
|
|
const playerCiv = g_ViewedPlayer > 0 ? g_Players[g_ViewedPlayer].civ : "gaia";
|
|
this.minimapBackgroundTexture.sprite = `stretched:session/icons/bkg/background_circle_${playerCiv}.png`;
|
|
}
|
|
}
|