guiGraphCtrl.cpp
Engine/source/gui/editor/guiGraphCtrl.cpp
Public Variables
Public Functions
ConsoleDocClass(GuiGraphCtrl , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that plots one or more curves in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">chart.\n\n</a>" "Up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 6 individual curves can be plotted in the graph. Each plotted curve can have its own display style including its " "own charting style (#plotType) and color (#plotColor).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "The data points on each curve can be added in one of two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ways:\n\n</a>" "- Manually by calling addDatum(). This causes <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the left end of the plotting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">curve.\n</a>" "- Automatically by letting the graph plot the values of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> variable over time. This is achieved by calling addAutoPlot " "and specifying the variable and update <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">frequency.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> graph that plots <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> red polyline graph of the FPS counter in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 1 second (1000 milliseconds) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">interval.\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigraphctrl/">GuiGraphCtrl</a>( FPSGraph )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " plotType[ 0 ] = \"PolyLine\";\n" " plotColor[ 0 ] = \"1 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " plotVariable[ 0 ] = \"fps::real\";\n" " plotInterval[ 0 ] = 1000;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@note Each curve has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> maximum number of 200 data points it can have at any one time. Adding more data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> curve " "will cause older data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">removed.\n\n</a>" "@ingroup GuiValues" )
DefineEngineMethod(GuiGraphCtrl , addAutoPlot , void , (S32 plotId, const char *variable, S32 updateFrequency) )
DefineEngineMethod(GuiGraphCtrl , addDatum , void , (S32 plotId, F32 value) )
DefineEngineMethod(GuiGraphCtrl , getDatum , F32 , (S32 plotId, S32 index) )
DefineEngineMethod(GuiGraphCtrl , removeAutoPlot , void , (S32 plotId) )
DefineEngineMethod(GuiGraphCtrl , setGraphType , void , (S32 plotId, GuiGraphType graphType) )
DefineEngineStringlyVariadicMethod(GuiGraphCtrl , matchScale , void , 3 , GuiGraphCtrl::MaxPlots+ 2, "( int plotID1, int plotID2, ... ) " "Set the scale of all specified plots <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the maximum scale among <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">them.\n\n</a>" "@param plotID1 Index of plotting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">curve.\n</a>" "@param plotID2 Index of plotting curve." )
ImplementEnumType(GuiGraphType , "The charting style of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single plotting curve in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGraphCtrl.\n\n</a>" "@ingroup GuiValues" )
Detailed Description
Public Variables
EndImplementEnumType
Public Functions
ConsoleDocClass(GuiGraphCtrl , "@brief A <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> that plots one or more curves in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">chart.\n\n</a>" "Up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 6 individual curves can be plotted in the graph. Each plotted curve can have its own display style including its " "own charting style (#plotType) and color (#plotColor).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "The data points on each curve can be added in one of two <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ways:\n\n</a>" "- Manually by calling addDatum(). This causes <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the left end of the plotting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">curve.\n</a>" "- Automatically by letting the graph plot the values of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> variable over time. This is achieved by calling addAutoPlot " "and specifying the variable and update <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">frequency.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> graph that plots <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> red polyline graph of the FPS counter in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 1 second (1000 milliseconds) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">interval.\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigraphctrl/">GuiGraphCtrl</a>( FPSGraph )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " plotType[ 0 ] = \"PolyLine\";\n" " plotColor[ 0 ] = \"1 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " plotVariable[ 0 ] = \"fps::real\";\n" " plotInterval[ 0 ] = 1000;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@note Each curve has <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> maximum number of 200 data points it can have at any one time. Adding more data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> curve " "will cause older data points <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">removed.\n\n</a>" "@ingroup GuiValues" )
DefineEngineMethod(GuiGraphCtrl , addAutoPlot , void , (S32 plotId, const char *variable, S32 updateFrequency) )
DefineEngineMethod(GuiGraphCtrl , addDatum , void , (S32 plotId, F32 value) )
DefineEngineMethod(GuiGraphCtrl , getDatum , F32 , (S32 plotId, S32 index) )
DefineEngineMethod(GuiGraphCtrl , removeAutoPlot , void , (S32 plotId) )
DefineEngineMethod(GuiGraphCtrl , setGraphType , void , (S32 plotId, GuiGraphType graphType) )
DefineEngineStringlyVariadicMethod(GuiGraphCtrl , matchScale , void , 3 , GuiGraphCtrl::MaxPlots+ 2, "( int plotID1, int plotID2, ... ) " "Set the scale of all specified plots <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the maximum scale among <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">them.\n\n</a>" "@param plotID1 Index of plotting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">curve.\n</a>" "@param plotID2 Index of plotting curve." )
IMPLEMENT_CONOBJECT(GuiGraphCtrl )
ImplementEnumType(GuiGraphType , "The charting style of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> single plotting curve in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGraphCtrl.\n\n</a>" "@ingroup GuiValues" )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gui/editor/guiGraphCtrl.h" 26 27#include "console/console.h" 28#include "console/consoleTypes.h" 29#include "console/engineAPI.h" 30#include "gfx/gfxDevice.h" 31#include "gfx/gfxDrawUtil.h" 32#include "gfx/primBuilder.h" 33 34 35IMPLEMENT_CONOBJECT( GuiGraphCtrl ); 36 37ConsoleDocClass( GuiGraphCtrl, 38 "@brief A control that plots one or more curves in a chart.\n\n" 39 40 "Up to 6 individual curves can be plotted in the graph. Each plotted curve can have its own display style including its " 41 "own charting style (#plotType) and color (#plotColor).\n\n" 42 43 "The data points on each curve can be added in one of two ways:\n\n" 44 45 "- Manually by calling addDatum(). This causes new data points to be added to the left end of the plotting curve.\n" 46 "- Automatically by letting the graph plot the values of a variable over time. This is achieved by calling addAutoPlot " 47 "and specifying the variable and update frequency.\n\n" 48 49 "@tsexample\n" 50 "// Create a graph that plots a red polyline graph of the FPS counter in a 1 second (1000 milliseconds) interval.\n" 51 "new GuiGraphCtrl( FPSGraph )\n" 52 "{\n" 53 " plotType[ 0 ] = \"PolyLine\";\n" 54 " plotColor[ 0 ] = \"1 0 0\";\n" 55 " plotVariable[ 0 ] = \"fps::real\";\n" 56 " plotInterval[ 0 ] = 1000;\n" 57 "};\n" 58 "@endtsexample\n\n" 59 60 "@note Each curve has a maximum number of 200 data points it can have at any one time. Adding more data points to a curve " 61 "will cause older data points to be removed.\n\n" 62 63 "@ingroup GuiValues" 64); 65 66ImplementEnumType( GuiGraphType, 67 "The charting style of a single plotting curve in a GuiGraphCtrl.\n\n" 68 "@ingroup GuiValues" ) 69 { GuiGraphCtrl::Bar, "Bar", "Plot the curve as a bar chart." }, 70 { GuiGraphCtrl::Filled, "Filled", "Plot a filled poly graph that connects the data points on the curve." }, 71 { GuiGraphCtrl::Point, "Point", "Plot each data point on the curve as a single dot." }, 72 { GuiGraphCtrl::Polyline , "PolyLine", "Plot straight lines through the data points of the curve." }, 73EndImplementEnumType; 74 75 76//----------------------------------------------------------------------------- 77 78GuiGraphCtrl::GuiGraphCtrl() 79 : mCenterY( 1.f ) 80{ 81 dMemset( mAutoPlot, 0, sizeof( mAutoPlot ) ); 82 dMemset( mAutoPlotDelay, 0, sizeof( mAutoPlotDelay ) ); 83 dMemset( mGraphMax, 0, sizeof( mGraphMax ) ); 84 85 for( S32 i = 0; i < MaxPlots; ++ i ) 86 { 87 mGraphType[ i ] = Polyline; 88 89 VECTOR_SET_ASSOCIATION( mGraphData[ i ] ); 90 } 91 92 AssertWarn( MaxPlots == 6, "Only 6 plot colors initialized. Update following code if you change MaxPlots." ); 93 94 mGraphColor[ 0 ] = LinearColorF( 1.0, 1.0, 1.0 ); 95 mGraphColor[ 1 ] = LinearColorF( 1.0, 0.0, 0.0 ); 96 mGraphColor[ 2 ] = LinearColorF( 0.0, 1.0, 0.0 ); 97 mGraphColor[ 3 ] = LinearColorF( 0.0, 0.0, 1.0 ); 98 mGraphColor[ 4 ] = LinearColorF( 0.0, 1.0, 1.0 ); 99 mGraphColor[ 5 ] = LinearColorF( 0.0, 0.0, 0.0 ); 100} 101 102//----------------------------------------------------------------------------- 103 104void GuiGraphCtrl::initPersistFields() 105{ 106 addGroup( "Graph" ); 107 108 addField( "centerY", TypeF32, Offset( mCenterY, GuiGraphCtrl ), 109 "Ratio of where to place the center coordinate of the graph on the Y axis. 0.5=middle height of control.\n\n" 110 "This allows to account for graphs that have only positive or only negative data points, for example." ); 111 112 addField( "plotColor", TypeColorF, Offset( mGraphColor, GuiGraphCtrl ), MaxPlots, 113 "Color to use for the plotting curves in the graph." ); 114 115 addField( "plotType", TYPEID< GuiGraphType >(), Offset( mGraphType, GuiGraphCtrl ), MaxPlots, 116 "Charting type of the plotting curves." ); 117 118 addField( "plotVariable", TypeString, Offset( mAutoPlot, GuiGraphCtrl ), MaxPlots, 119 "Name of the variable to automatically plot on the curves. If empty, auto-plotting " 120 "is disabled for the respective curve." ); 121 122 addField( "plotInterval", TypeS32, Offset( mAutoPlotDelay, GuiGraphCtrl ), MaxPlots, 123 "Interval between auto-plots of #plotVariable for the respective curve (in milliseconds)." ); 124 125 endGroup( "Graph" ); 126 127 Parent::initPersistFields(); 128} 129 130//----------------------------------------------------------------------------- 131 132void GuiGraphCtrl::onRender(Point2I offset, const RectI &updateRect) 133{ 134 if (mBlendSB.isNull()) 135 { 136 GFXStateBlockDesc desc; 137 138 desc.setBlend(true, GFXBlendSrcColor, GFXBlendInvSrcColor); 139 mBlendSB = GFX->createStateBlock(desc); 140 141 desc.setBlend(false, GFXBlendOne, GFXBlendZero); 142 mSolidSB = GFX->createStateBlock(desc); 143 144 } 145 146 GFX->setStateBlock( mBlendSB ); 147 148 GFX->getDrawUtil()->drawRectFill( updateRect, mProfile->mFillColor ); 149 150 GFX->setStateBlock( mSolidSB ); 151 152 const Point2I globalPos = getGlobalBounds().point; 153 const F32 midPointY = F32( globalPos.y ) + F32( getExtent().y ) * mCenterY; 154 155 for( S32 k = 0; k < MaxPlots; ++ k ) 156 { 157 // Check if there is an autoplot and the proper amount of time has passed, if so add datum. 158 if( mAutoPlot[ k ] && mAutoPlotDelay[ k ] < (Sim::getCurrentTime() - mAutoPlotLastDisplay[ k ] ) ) 159 { 160 mAutoPlotLastDisplay[ k ] = Sim::getCurrentTime(); 161 addDatum( k, Con::getFloatVariable( mAutoPlot[ k ] ) ); 162 } 163 164 // Nothing to graph 165 if( mGraphData[ k ].size() == 0 ) 166 continue; 167 168 // Adjust scale to max value + 5% so we can see high values 169 F32 Scale = F32( getExtent().y ) / F32( mGraphMax[ k ] * 1.05 ); 170 171 const S32 numSamples = mGraphData[ k ].size(); 172 F32 graphOffset; 173 switch( mGraphType[ k ] ) 174 { 175 case Bar: 176 { 177 F32 prevOffset = 0; 178 179 for( S32 sample = 0; sample < numSamples; ++ sample ) 180 { 181 PrimBuild::begin( GFXTriangleStrip, 4 ); 182 PrimBuild::color( mGraphColor[ k ] ); 183 184 graphOffset = F32( getExtent().x ) / F32( MaxDataPoints ) * F32( sample + 1 ); 185 186 PrimBuild::vertex2f( globalPos.x + prevOffset, 187 midPointY - ( getDatum( k, sample ) * Scale ) ); 188 189 PrimBuild::vertex2f( globalPos.x + graphOffset, 190 midPointY - ( getDatum( k, sample ) * Scale ) ); 191 192 PrimBuild::vertex2f( globalPos.x + graphOffset, 193 midPointY ); 194 195 PrimBuild::vertex2f( globalPos.x + prevOffset, 196 midPointY ); 197 198 prevOffset = graphOffset; 199 200 PrimBuild::end(); 201 } 202 203 break; 204 } 205 206 case Filled: 207 { 208 PrimBuild::begin( GFXTriangleStrip, numSamples * 2 ); // Max size correct? -pw 209 PrimBuild::color( mGraphColor[ k ] ); 210 211 for( S32 sample = 0; sample < numSamples; ++ sample ) 212 { 213 graphOffset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample ); 214 215 PrimBuild::vertex2f( globalPos.x + graphOffset, 216 midPointY ); 217 218 PrimBuild::vertex2f( globalPos.x + graphOffset, 219 midPointY - ( getDatum( k, sample ) * Scale ) ); 220 } 221 222 PrimBuild::end(); 223 break; 224 } 225 226 case Point: 227 case Polyline: 228 { 229 if( mGraphType[ k ] == Point ) 230 PrimBuild::begin( GFXPointList, numSamples ); // Max size correct? -pw 231 else 232 PrimBuild::begin( GFXLineStrip, numSamples ); 233 234 PrimBuild::color( mGraphColor[ k ] ); 235 236 for( S32 sample = 0; sample < numSamples; ++ sample ) 237 { 238 graphOffset = F32( getExtent().x ) / F32( MaxDataPoints - 1 ) * F32( sample ); 239 240 PrimBuild::vertex2f( globalPos.x + graphOffset, 241 midPointY - ( getDatum( k, sample ) * Scale ) ); 242 } 243 244 PrimBuild::end(); 245 break; 246 } 247 } 248 } 249 250 if( mProfile->mBorder ) 251 { 252 RectI rect( offset.x, offset.y, getWidth(), getHeight() ); 253 GFX->getDrawUtil()->drawRect( rect, mProfile->mBorderColor ); 254 } 255 256 renderChildControls( offset, updateRect ); 257} 258 259//----------------------------------------------------------------------------- 260 261void GuiGraphCtrl::addDatum(S32 plotID, F32 v) 262{ 263 AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!"); 264 265 // Add the data and trim the vector... 266 mGraphData[ plotID ].push_front( v ); 267 268 if( mGraphData[ plotID ].size() > MaxDataPoints ) 269 mGraphData[ plotID ].pop_back(); 270 271 // Keep record of maximum data value for scaling purposes. 272 if( v > mGraphMax[ plotID ] ) 273 mGraphMax[ plotID ] = v; 274} 275 276//----------------------------------------------------------------------------- 277 278F32 GuiGraphCtrl::getDatum( S32 plotID, S32 sample) 279{ 280 AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!"); 281 AssertFatal(sample > -1 && sample < MaxDataPoints, "Invalid sample specified!"); 282 return mGraphData[ plotID ][sample]; 283} 284 285//----------------------------------------------------------------------------- 286 287void GuiGraphCtrl::addAutoPlot( S32 plotID, const char* variable, S32 update ) 288{ 289 mAutoPlot[ plotID ] = StringTable->insert( variable ); 290 mAutoPlotDelay[ plotID ] = update; 291} 292 293//----------------------------------------------------------------------------- 294 295void GuiGraphCtrl::removeAutoPlot( S32 plotID ) 296{ 297 mAutoPlot[ plotID ] = NULL; 298} 299 300//----------------------------------------------------------------------------- 301 302void GuiGraphCtrl::setGraphType( S32 plotID, GraphType graphType ) 303{ 304 AssertFatal( plotID > -1 && plotID < MaxPlots, "Invalid plot specified!" ); 305 mGraphType[ plotID ] = graphType; 306} 307 308//============================================================================= 309// Console Methods. 310//============================================================================= 311// MARK: ---- Console Methods ---- 312 313//----------------------------------------------------------------------------- 314 315DefineEngineMethod( GuiGraphCtrl, addDatum, void, ( S32 plotId, F32 value ),, 316 "Add a data point to the plot's curve.\n\n" 317 "@param plotId Index of the plotting curve to which to add the data point. Must be 0<=plotId<6.\n" 318 "@param value Value of the data point to add to the curve.\n\n" 319 "@note Data values are added to the @b left end of the plotting curve.\n\n" 320 "@note A maximum number of 200 data points can be added to any single plotting curve at any one time. If " 321 "this limit is exceeded, data points on the right end of the curve are culled." ) 322{ 323 if( plotId > object->MaxPlots ) 324 { 325 Con::errorf( "GuiGraphCtrl::addDatum - 'plotId' out of range: %i", plotId ); 326 return; 327 } 328 329 object->addDatum( plotId, value ); 330} 331 332//----------------------------------------------------------------------------- 333 334DefineEngineMethod( GuiGraphCtrl, getDatum, F32, ( S32 plotId, S32 index ),, 335 "Get a data point on the given plotting curve.\n\n" 336 "@param plotId Index of the plotting curve from which to fetch the data point. Must be 0<=plotId<6.\n" 337 "@param index Index of the data point on the curve.\n" 338 "@return The value of the data point or -1 if @a plotId or @a index are out of range." ) 339{ 340 if( plotId > object->MaxPlots ) 341 { 342 Con::errorf( "GuiGraphCtrl::getDatum - 'plotId' out of range: %i", plotId ); 343 return -1.f; 344 } 345 346 if( index > object->MaxDataPoints) 347 { 348 Con::errorf( "GuiGraphCtrl::getDatum - Data point index out of range: %i", index ); 349 return -1.f; 350 } 351 352 return object->getDatum( plotId, index ); 353} 354 355//----------------------------------------------------------------------------- 356 357DefineEngineMethod( GuiGraphCtrl, addAutoPlot, void, ( S32 plotId, const char* variable, S32 updateFrequency ),, 358 "Sets up the given plotting curve to automatically plot the value of the @a variable with a " 359 "frequency of @a updateFrequency.\n" 360 "@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n" 361 "@param variable Name of the global variable.\n" 362 "@param updateFrequency Frequency with which to add new data points to the plotting curve (in milliseconds).\n" 363 "@tsexample\n" 364 "// Plot FPS counter at 1 second intervals.\n" 365 "%graph.addAutoPlot( 0, \"fps::real\", 1000 );\n" 366 "@endtsexample" ) 367{ 368 if( plotId > object->MaxPlots ) 369 { 370 Con::errorf( "GuiGraphCtrl::removeAutoPlot - 'plotId' out of range: %i", plotId ); 371 return; 372 } 373 374 object->addAutoPlot( plotId, variable, updateFrequency ); 375} 376 377//----------------------------------------------------------------------------- 378 379DefineEngineMethod( GuiGraphCtrl, removeAutoPlot, void, ( S32 plotId ),, 380 "Stop automatic variable plotting for the given curve.\n" 381 "@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n" ) 382{ 383 if( plotId > object->MaxPlots ) 384 { 385 Con::errorf( "GuiGraphCtrl::removeAutoPlot - 'plotId' out of range: %i", plotId ); 386 return; 387 } 388 389 object->removeAutoPlot( plotId ); 390} 391 392//----------------------------------------------------------------------------- 393 394DefineEngineMethod( GuiGraphCtrl, setGraphType, void, ( S32 plotId, GuiGraphType graphType ),, 395 "Change the charting type of the given plotting curve.\n" 396 "@param plotId Index of the plotting curve. Must be 0<=plotId<6.\n" 397 "@param graphType Charting type to use for the curve.\n" 398 "@note Instead of calling this method, you can directly assign to #plotType." ) 399{ 400 if( plotId > object->MaxPlots ) 401 { 402 Con::errorf( "GuiGraphCtrl::setGraphType - 'plotId' out of range: %i", plotId ); 403 return; 404 } 405 406 object->setGraphType( plotId, graphType ); 407} 408 409//----------------------------------------------------------------------------- 410 411DefineEngineStringlyVariadicMethod( GuiGraphCtrl, matchScale, void, 3, GuiGraphCtrl::MaxPlots + 2, "( int plotID1, int plotID2, ... ) " 412 "Set the scale of all specified plots to the maximum scale among them.\n\n" 413 "@param plotID1 Index of plotting curve.\n" 414 "@param plotID2 Index of plotting curve." ) 415{ 416 F32 max = 0; 417 for( S32 i = 0; i < ( argc - 2 ); ++ i ) 418 { 419 S32 plotID = dAtoi( argv[ 2 + i ] ); 420 if( plotID > object->MaxPlots ) 421 { 422 Con::errorf( "GuiGraphCtrl::matchScale - Plot ID out of range: %i", plotID ); 423 return; 424 } 425 426 max = getMax( object->getMax( plotID ), max ); 427 } 428 429 for( S32 i = 0; i < ( argc - 2 ); ++ i ) 430 object->setMax( dAtoi( argv[ 2 + i ] ), max ); 431} 432