Get the index of the hovered element in GUI lists and use it to display item-specific tooltips in the gamesetup for the victory condition, maptype and starting resources.

Differential Revision: https://code.wildfiregames.com/D316
Fixes #3699
Patch By: Vladislav
This was SVN commit r19588.
This commit is contained in:
elexis 2017-05-15 21:49:10 +00:00
parent aa302dcb2d
commit 2599d0374e
4 changed files with 100 additions and 54 deletions

View file

@ -186,15 +186,18 @@ function loadMapTypes()
{
"Name": "skirmish",
"Title": translateWithContext("map", "Skirmish"),
"Description": translate("A map with a predefined landscape and number of players. Freely select the other gamesettings."),
"Default": true
},
{
"Name": "random",
"Title": translateWithContext("map", "Random")
"Title": translateWithContext("map", "Random"),
"Description": translate("Create a unique map with a different resource distribution each time. Freely chose the number of players and teams.")
},
{
"Name": "scenario",
"Title": translateWithContext("map", "Scenario")
"Title": translateWithContext("map", "Scenario"),
"Description": translate("A map with a predefined landscape and matchsettings.")
}
];
}

View file

@ -358,7 +358,7 @@ var g_OptionOrderInit = {
*
* GUI
* title - The caption shown in the label.
* tooltip - A description shown when hovering the option.
* tooltip - A description shown when hovering the dropdown or a specific item.
* labels - Array of translated strings selectable for this dropdown.
* colors - Optional array of colors to tint the according dropdown items with.
* hidden - If hidden, both the label and dropdown won't be visible. (default: false)
@ -369,7 +369,7 @@ var g_OptionOrderInit = {
var g_Dropdowns = {
"mapType": {
"title": () => translate("Map Type"),
"tooltip": () => translate("Select a map type."),
"tooltip": (hoverIdx) => g_MapTypes.Description[hoverIdx] || translate("Select a map type."),
"labels": () => g_MapTypes.Title,
"ids": () => g_MapTypes.Name,
"default": () => g_MapTypes.Default,
@ -392,7 +392,7 @@ var g_Dropdowns = {
},
"mapFilter": {
"title": () => translate("Map Filter"),
"tooltip": () => translate("Select a map filter."),
"tooltip": (hoverIdx) => translate("Select a map filter."),
"labels": () => g_MapFilterList.name,
"ids": () => g_MapFilterList.id,
"default": () => g_MapFilterList.Default,
@ -407,7 +407,7 @@ var g_Dropdowns = {
},
"mapSelection": {
"title": () => translate("Select Map"),
"tooltip": () => translate("Select a map to play on."),
"tooltip": (hoverIdx) => translate("Select a map to play on."),
"labels": () => g_MapSelectionList.name,
"colors": () => g_MapSelectionList.color,
"ids": () => g_MapSelectionList.file,
@ -421,7 +421,7 @@ var g_Dropdowns = {
},
"mapSize": {
"title": () => translate("Map Size"),
"tooltip": () => translate("Select map size. (Larger sizes may reduce performance.)"),
"tooltip": (hoverIdx) => translate("Select map size. (Larger sizes may reduce performance.)"),
"labels": () => g_MapSizes.Name,
"ids": () => g_MapSizes.Tiles,
"default": () => g_MapSizes.Default,
@ -435,7 +435,7 @@ var g_Dropdowns = {
},
"numPlayers": {
"title": () => translate("Number of Players"),
"tooltip": () => translate("Select number of players."),
"tooltip": (hoverIdx) => translate("Select number of players."),
"labels": () => g_NumPlayersList,
"ids": () => g_NumPlayersList,
"default": () => g_MaxPlayers - 1,
@ -455,7 +455,7 @@ var g_Dropdowns = {
},
"populationCap": {
"title": () => translate("Population Cap"),
"tooltip": () => translate("Select population cap."),
"tooltip": (hoverIdx) => translate("Select population cap."),
"labels": () => g_PopulationCapacities.Title,
"ids": () => g_PopulationCapacities.Population,
"default": () => g_PopulationCapacities.Default,
@ -468,7 +468,13 @@ var g_Dropdowns = {
},
"startingResources": {
"title": () => translate("Starting Resources"),
"tooltip": () => translate("Select the game's starting resources."),
"tooltip": (hoverIdx) => {
return hoverIdx >= 0 ?
sprintf(translate("Initial amount of each resource: %(resources)s."), {
"resources": g_StartingResources.Resources[hoverIdx]
}) :
translate("Select the game's starting resources.");
},
"labels": () => g_StartingResources.Title,
"ids": () => g_StartingResources.Resources,
"default": () => g_StartingResources.Default,
@ -482,7 +488,7 @@ var g_Dropdowns = {
},
"ceasefire": {
"title": () => translate("Ceasefire"),
"tooltip": () => translate("Set time where no attacks are possible."),
"tooltip": (hoverIdx) => translate("Set time where no attacks are possible."),
"labels": () => g_Ceasefire.Title,
"ids": () => g_Ceasefire.Duration,
"default": () => g_Ceasefire.Default,
@ -495,7 +501,7 @@ var g_Dropdowns = {
},
"victoryCondition": {
"title": () => translate("Victory Condition"),
"tooltip": () => translate("Select victory condition."),
"tooltip": (hoverIdx) => g_VictoryConditions.Description[hoverIdx] || translate("Select victory condition."),
"labels": () => g_VictoryConditions.Title,
"ids": () => g_VictoryConditions.Name,
"default": () => g_VictoryConditions.Default,
@ -510,7 +516,7 @@ var g_Dropdowns = {
},
"relicCount": {
"title": () => translate("Relic Count"),
"tooltip": () => translate("Total number of relics spawned on the map."),
"tooltip": (hoverIdx) => translate("Total number of relics spawned on the map."),
"labels": () => g_RelicCountList,
"ids": () => g_RelicCountList,
"default": () => g_RelicCountList.indexOf(5),
@ -524,7 +530,7 @@ var g_Dropdowns = {
},
"victoryDuration": {
"title": () => translate("Victory Duration"),
"tooltip": () => translate("Number of minutes until the player has won."),
"tooltip": (hoverIdx) => translate("Number of minutes until the player has won."),
"labels": () => g_VictoryDurations.Title,
"ids": () => g_VictoryDurations.Duration,
"default": () => g_VictoryDurations.Default,
@ -540,7 +546,7 @@ var g_Dropdowns = {
},
"gameSpeed": {
"title": () => translate("Game Speed"),
"tooltip": () => translate("Select game speed."),
"tooltip": (hoverIdx) => translate("Select game speed."),
"labels": () => g_GameSpeeds.Title,
"ids": () => g_GameSpeeds.Speed,
"default": () => g_GameSpeeds.Default,
@ -777,7 +783,7 @@ var g_MiscControls = {
"startGame": {
"caption": () =>
g_IsController ? translate("Start game!") : g_ReadyData[g_IsReady].caption,
"tooltip": () =>
"tooltip": (hoverIdx) =>
!g_IsController ?
g_ReadyData[g_IsReady].tooltip :
!g_IsNetworked || Object.keys(g_PlayerAssignments).every(guid =>
@ -1005,6 +1011,11 @@ function initDropdown(name, idx)
supplementDefaults();
updateGameAttributes();
};
if (data.tooltip)
dropdown.onHoverChange = function() {
this.tooltip = data.tooltip(this.hovered);
};
}
function initPlayerDropdowns(name)

View file

@ -45,16 +45,17 @@ CList::CList()
AddSetting(GUIST_CColor, "textcolor");
AddSetting(GUIST_CColor, "textcolor_selected");
AddSetting(GUIST_int, "selected"); // Index selected. -1 is none.
AddSetting(GUIST_int, "hovered");
AddSetting(GUIST_CStrW, "tooltip");
AddSetting(GUIST_CStr, "tooltip_style");
// Each list item has both a name (in 'list') and an associated data string (in 'list_data')
AddSetting(GUIST_CGUIList, "list");
AddSetting(GUIST_CGUIList, "list_data"); // TODO: this should be a list of raw strings, not of CGUIStrings
GUI<bool>::SetSetting(this, "scrollbar", false);
// Nothing is selected as default.
GUI<int>::SetSetting(this, "selected", -1);
GUI<int>::SetSetting(this, "hovered", -1);
// Add scroll-bar
CGUIScrollBarVertical* bar = new CGUIScrollBarVertical();
@ -194,45 +195,46 @@ void CList::HandleMessage(SGUIMessage& Message)
break;
}
bool scrollbar;
CGUIList* pList;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
GUI<CGUIList>::GetSettingPointer(this, "list", pList);
float scroll = 0.f;
if (scrollbar)
scroll = GetScrollBar(0).GetPos();
int hovered = GetHoveredItem();
if (hovered == -1)
break;
GUI<int>::SetSetting(this, "selected", hovered);
UpdateAutoScroll();
CRect rect = GetListRect();
CPos mouse = GetMousePos();
mouse.y += scroll;
int set = -1;
for (int i = 0; i < (int)pList->m_Items.size(); ++i)
{
if (mouse.y >= rect.top + m_ItemsYPositions[i] &&
mouse.y < rect.top + m_ItemsYPositions[i+1] &&
// mouse is not over scroll-bar
(!scrollbar || !GetScrollBar(0).IsVisible() ||
mouse.x < GetScrollBar(0).GetOuterRect().left ||
mouse.x > GetScrollBar(0).GetOuterRect().right))
{
set = i;
}
}
CStrW soundPath;
if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
g_SoundManager->PlayAsUI(soundPath.c_str(), false);
if (set != -1)
{
GUI<int>::SetSetting(this, "selected", set);
UpdateAutoScroll();
if (timer_Time() - m_LastItemClickTime < SELECT_DBLCLICK_RATE && hovered == m_PrevSelectedItem)
this->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, "mouseleftdoubleclickitem");
m_LastItemClickTime = timer_Time();
m_PrevSelectedItem = hovered;
break;
}
CStrW soundPath;
if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty())
g_SoundManager->PlayAsUI(soundPath.c_str(), false);
case GUIM_MOUSE_LEAVE:
{
int hoveredSetting = -1;
GUI<int>::GetSetting(this, "hovered", hoveredSetting);
if (hoveredSetting == -1)
break;
if (timer_Time() - m_LastItemClickTime < SELECT_DBLCLICK_RATE && set == m_PrevSelectedItem)
this->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT_ITEM, "mouseleftdoubleclickitem");
m_LastItemClickTime = timer_Time();
m_PrevSelectedItem = set;
}
GUI<int>::SetSetting(this, "hovered", -1);
ScriptEvent("hoverchange");
break;
}
case GUIM_MOUSE_OVER:
{
int hoveredSetting = -1;
GUI<int>::GetSetting(this, "hovered", hoveredSetting);
int hovered = GetHoveredItem();
if (hovered == hoveredSetting)
break;
GUI<int>::SetSetting(this, "hovered", hovered);
ScriptEvent("hoverchange");
break;
}
@ -515,3 +517,31 @@ void CList::UpdateAutoScroll()
if (m_ItemsYPositions[selected+1]-rect.GetHeight() > scroll)
GetScrollBar(0).SetPos(m_ItemsYPositions[selected+1]-rect.GetHeight());
}
int CList::GetHoveredItem()
{
bool scrollbar;
CGUIList* pList;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
GUI<CGUIList>::GetSettingPointer(this, "list", pList);
float scroll = 0.f;
if (scrollbar)
scroll = GetScrollBar(0).GetPos();
CRect rect = GetListRect();
CPos mouse = GetMousePos();
mouse.y += scroll;
// Mouse is over scrollbar
if (scrollbar && GetScrollBar(0).IsVisible() &&
mouse.x >= GetScrollBar(0).GetOuterRect().left &&
mouse.x <= GetScrollBar(0).GetOuterRect().right)
return -1;
for (size_t i = 0; i < pList->m_Items.size(); ++i)
if (mouse.y >= rect.top + m_ItemsYPositions[i] &&
mouse.y < rect.top + m_ItemsYPositions[i + 1])
return i;
return -1;
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -105,6 +105,8 @@ protected:
*/
std::vector<float> m_ItemsYPositions;
virtual int GetHoveredItem();
private:
// Whether the list's items have been modified since last handling a message.
bool m_Modified;