Ticket #3403: 3403_charts.patch
File 3403_charts.patch, 18.3 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/gui/summary/summary.js
35 35 var g_GameData; 36 36 var g_ResourceData = new Resources(); 37 37 38 var g_Charts = ["population", "explored"]; 39 38 40 function selectPanel(panel) 39 41 { 40 42 // TODO: move panel buttons to a custom parent object … … 47 49 48 50 adjustTabDividers(panel.size); 49 51 50 updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]); 52 let generalPanel = Engine.GetGUIObjectByName("generalPanel"); 53 let chartsPanel = Engine.GetGUIObjectByName("chartsPanel"); 54 if (panel.name != "chartsPanelButton") 55 { 56 generalPanel.hidden = false; 57 chartsPanel.hidden = true; 58 updatePanelData(g_ScorePanelsData[panel.name.substr(0, panel.name.length - "PanelButton".length)]); 59 } 60 else 61 { 62 generalPanel.hidden = true; 63 chartsPanel.hidden = false; 64 updateCharts(); 65 } 51 66 } 52 67 68 function initCharts() 69 { 70 let player_colors = []; 71 for (let i = 0; i < g_PlayerCount; ++i) 72 { 73 let playerState = g_GameData.sim.playerStates[i+1]; 74 player_colors.push( 75 Math.floor(playerState.color.r * 255) + " " + 76 Math.floor(playerState.color.g * 255) + " " + 77 Math.floor(playerState.color.b * 255) 78 ); 79 } 80 for (let i = 0; i < g_Charts.length; ++i) 81 { 82 let chart = Engine.GetGUIObjectByName(g_Charts[i] + "Chart"); 83 chart.list_color = player_colors; 84 } 85 } 86 87 function updateCharts() 88 { 89 for (let i = 0; i < g_Charts.length; ++i) 90 { 91 let chart = Engine.GetGUIObjectByName(g_Charts[i] + "Chart"); 92 let table_x = []; 93 let table_y = []; 94 for (let j = 0; j < g_PlayerCount; ++j) 95 { 96 let playerState = g_GameData.sim.playerStates[j+1]; 97 let list_x = []; 98 let list_y = []; 99 for (let k = 0; k < playerState.statistics.sequences[g_Charts[i]].length; ++k) 100 { 101 list_x.push(playerState.statistics.sequences[g_Charts[i]][k][0]); 102 list_y.push(playerState.statistics.sequences[g_Charts[i]][k][1]); 103 } 104 table_x.push(list_x); 105 table_y.push(list_y); 106 } 107 chart.table_x = table_x; 108 chart.table_y = table_y; 109 } 110 } 111 53 112 function adjustTabDividers(tabSize) 54 113 { 55 114 let leftSpacer = Engine.GetGUIObjectByName("tabDividerLeft"); … … 266 325 g_WithoutTeam -= g_Teams[i] ? g_Teams[i] : 0; 267 326 } 268 327 328 initCharts(); 329 269 330 selectPanel(Engine.GetGUIObjectByName("scorePanelButton")); 270 331 } -
binaries/data/mods/public/gui/summary/summary.xml
98 98 </object> 99 99 </object> 100 100 101 <object name="chartsPanelButton" type="button" sprite="BackgroundTab" style="TabButton" size="762 92 880 120"> 102 <action on="Press">selectPanel(this);</action> 103 <object type="text" style="ModernLabelText" ghost="true"> 104 <translatableAttribute id="caption">Charts</translatableAttribute> 105 </object> 106 </object> 107 101 108 <object name="generalPanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-54"> 102 109 <object size="0 0 100% 100%-50"> 103 110 <object name="playerNameHeading" type="text" style="ModernLeftTabLabelText"> … … 151 158 </repeat> 152 159 </object> 153 160 </object> 161 162 <object name="chartsPanel" type="image" sprite="ForegroundBody" size="20 120 100%-20 100%-54"> 163 <object 164 name="populationChartCaption" 165 type="text" 166 style="ModernTabLabelText" 167 size="20 20 50%-20 40" 168 > 169 <translatableAttribute id="caption">Population</translatableAttribute> 170 </object> 171 <object 172 name="populationChart" 173 type="chart" 174 ghost="true" 175 size="20 60 50%-20 50%-20" 176 /> 177 <object 178 name="exploredChartCaption" 179 type="text" 180 style="ModernTabLabelText" 181 size="50%+20 20 100%-20 40" 182 > 183 <translatableAttribute id="caption">Explored</translatableAttribute> 184 </object> 185 <object 186 name="exploredChart" 187 type="chart" 188 ghost="true" 189 size="50%+20 60 100%-20 50%-20" 190 /> 191 </object> 154 192 155 193 <object type="button" name="replayButton" style="ModernButtonRed" size="100%-310 100%-48 100%-170 100%-20"> 156 194 <translatableAttribute id="caption">Replay</translatableAttribute> -
binaries/data/mods/public/simulation/components/StatisticsTracker.js
1 1 function StatisticsTracker() {} 2 2 3 const UPDATE_SEQUENCE_INTERVAL = 30000; // 30 seconds 4 3 5 StatisticsTracker.prototype.Schema = 4 6 "<a:component type='system'/><empty/>"; 5 7 … … 142 144 this.lootCollected = 0; 143 145 this.peakPercentMapControlled = 0; 144 146 this.teamPeakPercentMapControlled = 0; 147 148 this.sequences = { 149 "population": [], 150 "explored": [] 151 }; 152 153 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 154 if (!cmpTimer) 155 return; 156 this.updateTimer = cmpTimer.SetInterval( 157 this.entity, IID_StatisticsTracker, "updateSequneces", 0, UPDATE_SEQUENCE_INTERVAL, { 158 "startTime": cmpTimer.GetTime() 159 } 160 ); 145 161 }; 146 162 147 163 /** … … 191 207 "percentMapControlled": this.GetPercentMapControlled(), 192 208 "teamPercentMapControlled": this.GetTeamPercentMapControlled(), 193 209 "peakPercentMapControlled": this.peakPercentMapControlled, 194 "teamPeakPercentMapControlled": this.teamPeakPercentMapControlled 210 "teamPeakPercentMapControlled": this.teamPeakPercentMapControlled, 211 "sequences": this.sequences 195 212 }; 196 213 }; 197 214 … … 492 509 this.teamPeakPercentMapControlled = newPercent; 493 510 }; 494 511 512 StatisticsTracker.prototype.updateSequneces = function(data) 513 { 514 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 515 if (!cmpTimer) 516 return; 517 let deltaTime = (cmpTimer.GetTime() - data["startTime"]) / 1000; 518 519 let cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); 520 if (!cmpPlayer) 521 return; 522 this.sequences.population.push([deltaTime, cmpPlayer.GetPopulationCount()]); 523 524 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 525 if (!cmpRangeManager) 526 return; 527 this.sequences.explored.push([ 528 deltaTime, 529 cmpRangeManager.GetPercentMapExplored(cmpPlayer.GetPlayerID()) 530 ]); 531 } 532 495 533 Engine.RegisterComponentType(IID_StatisticsTracker, "StatisticsTracker", StatisticsTracker); -
source/gui/CChart.cpp
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 #include "CChart.h" 20 21 #include "graphics/ShaderManager.h" 22 #include "lib/ogl.h" 23 #include "ps/CLogger.h" 24 #include "renderer/Renderer.h" 25 26 #include <cmath> 27 28 CChart::CChart() 29 { 30 AddSetting(GUIST_CGUIList, "list_color"); 31 AddSetting(GUIST_CGUITable, "table_x"); 32 AddSetting(GUIST_CGUITable, "table_y"); 33 } 34 35 CChart::~CChart() 36 { 37 } 38 39 void CChart::HandleMessage(SGUIMessage& Message) 40 { 41 // TODO: implement zoom 42 } 43 44 void CChart::Draw() 45 { 46 PROFILE3("render chart"); 47 48 if (!GetGUI()) 49 return; 50 51 UpdateItems(); 52 53 const float bz = GetBufferedZ(); 54 CRect rect = GetChartRect(); 55 const float width = rect.GetWidth(); 56 const float height = rect.GetHeight(); 57 58 if (m_Items.empty()) 59 return; 60 61 // Disable depth updates to prevent apparent z-fighting-related issues 62 // with some drivers causing units to get drawn behind the texture. 63 glDepthMask(0); 64 65 // Setup the render state 66 CMatrix3D transform = GetDefaultGuiMatrix(); 67 CShaderDefines lineDefines; 68 CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid, g_Renderer.GetSystemShaderDefines(), lineDefines); 69 tech->BeginPass(); 70 CShaderProgramPtr shader = tech->GetShader(); 71 shader->Uniform(str_transform, transform); 72 73 CVector2D leftBottom, rightTop; 74 leftBottom = rightTop = m_Items[0].m_Points[0]; 75 for (const CChartItem& item : m_Items) 76 for (const CVector2D& point : item.m_Points) 77 { 78 if (point.X < leftBottom.X) 79 leftBottom.X = point.X; 80 if (point.Y < leftBottom.Y) 81 leftBottom.Y = point.Y; 82 83 if (point.X > rightTop.X) 84 rightTop.X = point.X; 85 if (point.Y > rightTop.Y) 86 rightTop.Y = point.Y; 87 } 88 89 CVector2D scale(width / (rightTop.X - leftBottom.X), height / (rightTop.Y - leftBottom.Y)); 90 91 for (const CChartItem& item : m_Items) 92 { 93 if (item.m_Points.empty()) 94 continue; 95 96 std::vector<float> vertices; 97 for (const CVector2D& point : item.m_Points) 98 { 99 vertices.push_back(rect.left + (point.X - leftBottom.X) * scale.X); 100 vertices.push_back(rect.bottom - (point.Y - leftBottom.Y) * scale.Y); 101 vertices.push_back(bz + 0.5f); 102 } 103 shader->Uniform(str_color, item.m_Color); 104 shader->VertexPointer(3, GL_FLOAT, 0, &vertices[0]); 105 shader->AssertPointersBound(); 106 107 glEnable(GL_LINE_SMOOTH); 108 glLineWidth(1.1f); 109 if (!g_Renderer.m_SkipSubmit) 110 glDrawArrays(GL_LINE_STRIP, 0, vertices.size() / 3); 111 glLineWidth(1.0f); 112 glDisable(GL_LINE_SMOOTH); 113 } 114 115 tech->EndPass(); 116 117 // Reset depth mask 118 glDepthMask(1); 119 } 120 121 CRect CChart::GetChartRect() const 122 { 123 return m_CachedActualSize; 124 } 125 126 void CChart::UpdateItems() 127 { 128 CGUITable* pTableX; 129 CGUITable* pTableY; 130 GUI<CGUITable>::GetSettingPointer(this, "table_x", pTableX); 131 GUI<CGUITable>::GetSettingPointer(this, "table_y", pTableY); 132 133 CGUIList* pListColor; 134 GUI<CGUIList>::GetSettingPointer(this, "list_color", pListColor); 135 136 m_Items.clear(); 137 for (size_t i = 0; i < std::min(pTableX->m_Items.size(), pTableY->m_Items.size()); ++i) 138 { 139 m_Items.resize(m_Items.size() + 1); 140 CChartItem& item = m_Items.back(); 141 142 if (i < pListColor->m_Items.size() && !GUI<int>::ParseColor(pListColor->m_Items[i].GetOriginalString(), item.m_Color, 0)) 143 LOGWARNING("GUI: Error parsing 'list_color' (\"%s\")", utf8_from_wstring(pListColor->m_Items[i].GetOriginalString())); 144 145 for (size_t j = 0; j < std::min(pTableX->m_Items[i].size(), pTableY->m_Items[i].size()); ++j) 146 { 147 item.m_Points.push_back(CVector2D( 148 pTableX->m_Items[i][j].GetOriginalString().ToFloat(), 149 pTableY->m_Items[i][j].GetOriginalString().ToFloat() 150 )); 151 } 152 } 153 } -
source/gui/CChart.h
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_CCHART 19 #define INCLUDED_CCHART 20 21 #include "GUI.h" 22 #include "graphics/Color.h" 23 #include "maths/Vector2D.h" 24 #include <vector> 25 26 /** 27 * Represents an item of chart. 28 */ 29 struct CChartItem 30 { 31 CStr m_Id; 32 CColor m_Color; 33 std::vector<CVector2D> m_Points; 34 }; 35 36 /** 37 * Chart for a data visualization 38 * 39 * @see IGUIObject 40 */ 41 class CChart : public IGUIObject 42 { 43 GUI_OBJECT(CChart) 44 45 public: 46 CChart(); 47 virtual ~CChart(); 48 49 protected: 50 /** 51 * @see IGUIObject#HandleMessage() 52 */ 53 virtual void HandleMessage(SGUIMessage& Message); 54 55 /** 56 * Draws the Chart 57 */ 58 virtual void Draw(); 59 60 virtual CRect GetChartRect() const; 61 62 void UpdateItems(); 63 64 std::vector<CChartItem> m_Items; 65 }; 66 67 #endif // INCLUDED_CCHART -
source/gui/CGUI.cpp
24 24 25 25 // Types - when including them into the engine. 26 26 #include "CButton.h" 27 #include "CChart.h" 27 28 #include "CCheckBox.h" 28 29 #include "CDropDown.h" 29 30 #include "CImage.h" … … 312 313 AddObjectType("olist", &COList::ConstructObject); 313 314 AddObjectType("dropdown", &CDropDown::ConstructObject); 314 315 AddObjectType("tooltip", &CTooltip::ConstructObject); 316 AddObjectType("chart", &CChart::ConstructObject); 315 317 } 316 318 317 319 void CGUI::Draw() -
source/gui/CGUITable.h
1 /* Copyright (C) 2016 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19 #ifndef INCLUDED_CGUITABLE 20 #define INCLUDED_CGUITABLE 21 22 #include "GUItext.h" 23 24 class CGUITable 25 { 26 public: 27 /** 28 * List of items (as text), the post-processed result is stored in 29 * the IGUITextOwner structure of this class. 30 */ 31 std::vector<std::vector<CGUIString>> m_Items; 32 }; 33 34 #endif -
source/gui/GUI.h
40 40 #include "ps/CStr.h" 41 41 42 42 #include "CGUIList.h" 43 #include "CGUITable.h" 43 44 #include "GUIbase.h" 44 45 #include "GUItext.h" 45 46 #include "GUIutil.h" -
source/gui/GUItypes.h
1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 40 40 TYPE(EVAlign) 41 41 TYPE(CPos) 42 42 TYPE(CGUIList) 43 TYPE(CGUITable) -
source/gui/GUIutil.cpp
253 253 return false; 254 254 } 255 255 256 template <> 257 bool __ParseString<CGUITable>(const CStrW& UNUSED(Value), CGUITable& UNUSED(Output)) 258 { 259 return false; 260 } 256 261 257 262 //-------------------------------------------------------- 258 263 -
source/gui/scripting/JSInterface_IGUIObject.cpp
1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 298 298 break; 299 299 } 300 300 301 case GUIST_CGUITable: 302 { 303 CGUITable value; 304 GUI<CGUITable>::GetSetting(e, propName, value); 305 306 JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty())); 307 vp.setObject(*obj); 308 309 for (u32 i = 0; i < value.m_Items.size(); ++i) 310 { 311 JS::RootedObject inner_obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty())); 312 for (u32 j = 0; j < value.m_Items[i].size(); ++j) 313 { 314 JS::RootedValue val(cx); 315 ScriptInterface::ToJSVal(cx, &val, value.m_Items[i][j].GetOriginalString()); 316 JS_SetElement(cx, inner_obj, j, val); 317 } 318 JS_SetElement(cx, obj, i, inner_obj); 319 } 320 321 break; 322 } 323 301 324 default: 302 325 JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str()); 303 326 DEBUG_WARN_ERR(ERR::LOGIC); … … 588 611 break; 589 612 } 590 613 614 case GUIST_CGUITable: 615 { 616 u32 row_length; 617 if (!vp.isObject() || !JS_GetArrayLength(cx, vpObj, &row_length)) 618 { 619 JS_ReportError(cx, "Table only accepts a GUITable object"); 620 return false; 621 } 622 623 CGUITable table; 624 table.m_Items.resize(row_length); 625 for (u32 i = 0; i < row_length; ++i) 626 { 627 JS::RootedValue column_value(cx); 628 if (!JS_GetElement(cx, vpObj, i, &column_value)) 629 { 630 JS_ReportError(cx, "Failed to get table column"); 631 return false; 632 } 633 JS::RootedObject column(cx, column_value.toObjectOrNull()); 634 u32 column_length; 635 if (!JS_GetArrayLength(cx, column, &column_length)) 636 { 637 JS_ReportError(cx, "Table row only accepts a table column"); 638 return false; 639 } 640 641 table.m_Items[i].resize(column_length); 642 for (u32 j = 0; j < column_length; ++j) 643 { 644 JS::RootedValue element(cx); 645 if (!JS_GetElement(cx, column, j, &element)) 646 { 647 JS_ReportError(cx, "Failed to get list element"); 648 return false; 649 } 650 651 std::wstring value; 652 if (!ScriptInterface::FromJSVal(cx, element, value)) 653 return false; 654 655 table.m_Items[i][j].SetValue(value); 656 } 657 } 658 659 GUI<CGUITable>::SetSetting(e, propName, table); 660 break; 661 } 662 591 663 default: 592 664 JS_ReportError(cx, "Setting '%s' uses an unimplemented type", propName.c_str()); 593 665 break;