Add minimap position and scale configuration options and expanded mode toggle

- 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.
This commit is contained in:
guerringuerrin 2026-06-19 15:02:00 -03:00
parent 6ffc251114
commit a55f3ae0dc
19 changed files with 400 additions and 29 deletions

View file

@ -527,6 +527,11 @@ icons.sizescale = 1.0
entityradiusscale = 1.0
blinkduration = 1.7 ; The blink duration while pinging
pingduration = 50.0 ; The duration for which an entity will be pinged after an attack notification
position = panel-left ; Set minimap position (panel-left, screen-left)
size = 1 ; Size of the minimap. 1 (small) to 5 (huge). Each value is 15% bigger
shape = square ; Shape of the minimap
expand.toggle = "Alt+C" ; Expand minimap
[gui.session.notifications]
attack = true ; Show a chat notification if you are attacked by another player

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5460d4fe38fc4f4d0ab8532cfb63e4b53c574c2e14e08d572f101a843c72a398
size 6709

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:90d1cba3ebcf5683baf022d1a21be361840c5a7c7203d622583770ae16fe1914
size 6270

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7f58a4a6e3a45eaa8ad7056640a22ab46fd2a820cc55f59435910a7048e38f0c
size 6677

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ef0fc7b741ae84795a64b95bdc85e2d2cda4f3a3cd2ef9e3c0341fa1aa3f964
size 6298

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8e5aa1c6e722029cb1115e3d7b35dd5e51af56c20d2470f3b7a2c9d8c42a2d85
size 4364

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b3aaf6a3a4a3debe1a41e9a1b829161a0f0011a42efc2454046d8928c687a1cb
size 6038

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:08f6bb87c4da438a0d9f0ee3940c95a042e8171adfdaa57fdadcb05dd617a023
size 5563

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:682c4075d5bf1fafa96b0a22a5ec56781fbdbc0e6ed8231ed1ab6d110cc08c3d
size 4252

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8b8a44793a609b25c9d2f8e295d58e7cda7662fcb402e196bc3f64ff130b4fa8
size 6305

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:679fbf447256c7046b29bffe6c5ea140b9bcaa0e43369fe393a6dcc12151697b
size 6144

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:436878aaa7be80c0846a133337af7a0c86371edaf3d4acd5397a8fa20ff0853e
size 18266

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b9b2bbdec7c2586c7ac2fc86769f305e43656dacd76985253ad2326496180eeb
size 16981

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:582b6b10793ae3bcf286d1db8ee46192d79cb475c0847916994921f8ecbc200a
size 51092

View file

@ -179,6 +179,10 @@
"name": "Flare (toggle)",
"desc": "Set the cursor to Flare. The hotkey can be released."
},
"session.minimap.expand.toggle": {
"name": "Expand minimap",
"desc": "Toggle minimap expand."
},
"session.calltoarms": {
"name": "Call to arms",
"desc": "Send the selected units on attack move to the specified location after dropping resources."

View file

@ -729,6 +729,50 @@
"tooltip": "Show special icons for some entities on the minimap.",
"config": "gui.session.minimap.icons.enabled"
},
{
"type": "dropdown",
"label": "Minimap position",
"tooltip": "Choose where the minimap is displayed.",
"config": "gui.session.minimap.position",
"list": [
{
"value": "panel-left",
"label": "Panel Left",
"tooltip": "Display the minimap attached to the bottom panel."
},
{
"value": "screen-left",
"label": "Screen Left",
"tooltip": "Display the minimap in the bottom-left corner of the screen."
}
]
},
{
"type": "dropdown",
"label": "Minimap layout",
"tooltip": "Choose between square and round layout",
"config": "gui.session.minimap.shape",
"list": [
{
"value": "square",
"label": "Square",
"tooltip": "Original 0.A.D minimap"
},
{
"value": "round",
"label": "Round",
"tooltip": "Round version"
}
]
},
{
"type": "slider",
"label": "Minimap size",
"tooltip": "Choose the size of the minimap.",
"config": "gui.session.minimap.size",
"min": 1,
"max": 2
},
{
"type": "boolean",
"label": "Rank icon above status bar",

View file

@ -3,13 +3,15 @@
*/
class MiniMapDiplomacyColorsButton
{
constructor(diplomacyColors)
constructor(diplomacyColors, theme)
{
this.theme = theme;
this.diplomacyColors = diplomacyColors;
this.diplomacyColorsButton = Engine.GetGUIObjectByName("diplomacyColorsButton");
this.diplomacyColorsButton.onPress = diplomacyColors.toggle.bind(diplomacyColors);
this.diplomacyColorsButton.mouse_event_mask = this.SpriteMask;
this.diplomacyColorsButton.mouse_event_mask = this.theme.mouse_event_mask;
const initialState = this.diplomacyColors.isEnabled?.() ?? false;
this.onDiplomacyColorsChange(initialState);
diplomacyColors.registerDiplomacyColorsChangeHandler(this.onDiplomacyColorsChange.bind(this));
registerHotkeyChangeHandler(this.onHotkeyChange.bind(this));
}
@ -24,21 +26,11 @@ class MiniMapDiplomacyColorsButton
onDiplomacyColorsChange(enabled)
{
this.diplomacyColorsButton.sprite =
"stretched:" +
(enabled ? this.SpriteEnabled : this.SpriteDisabled);
enabled ? this.theme.sprite_on : this.theme.sprite_off;
this.diplomacyColorsButton.sprite_over =
"stretched:" +
(enabled ? this.SpriteEnabledOver : this.SpriteDisabledOver);
enabled ? this.theme.sprite_on_over : this.theme.sprite_off_over;
}
}
MiniMapDiplomacyColorsButton.prototype.Tooltip = markForTranslation("Toggle Diplomacy Colors");
MiniMapDiplomacyColorsButton.prototype.SpriteEnabled = "session/minimap-diplomacy-on.png";
MiniMapDiplomacyColorsButton.prototype.SpriteDisabled = "session/minimap-diplomacy-off.png";
MiniMapDiplomacyColorsButton.prototype.SpriteEnabledOver = "session/minimap-diplomacy-on-highlight.png";
MiniMapDiplomacyColorsButton.prototype.SpriteDisabledOver = "session/minimap-diplomacy-off-highlight.png";
MiniMapDiplomacyColorsButton.prototype.SpriteMask = "texture:session/minimap-diplomacy-on.png";

View file

@ -18,16 +18,6 @@ class MiniMapFlareButton
rebuild()
{
if (g_IsObserver)
{
this.flareButton.sprite = "stretched:session/minimap-observer-flare.png";
this.flareButton.sprite_over = "stretched:session/minimap-observer-flare-highlight.png";
}
else
{
this.flareButton.sprite = "stretched:session/minimap-player-flare.png";
this.flareButton.sprite_over = "stretched:session/minimap-player-flare-highlight.png";
}
this.updateTooltip();
}

View file

@ -5,12 +5,309 @@ class MiniMapPanel
{
constructor(playerViewControl, diplomacyColors, idleWorkerClasses)
{
this.diplomacyColorsButton = new MiniMapDiplomacyColorsButton(diplomacyColors);
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)
@ -25,13 +322,13 @@ class MiniMapPanel
rebuild()
{
this.applyLayout();
this.setCivBackgroundTexture();
}
setCivBackgroundTexture()
{
const playerCiv = g_ViewedPlayer > 0 ? g_Players[g_ViewedPlayer].civ : "gaia";
const backgroundObject = Engine.GetGUIObjectByName("minimapBackgroundTexture");
backgroundObject.sprite = `stretched:session/icons/bkg/background_circle_${playerCiv}.png`;
this.minimapBackgroundTexture.sprite = `stretched:session/icons/bkg/background_circle_${playerCiv}.png`;
}
}