tge/engine/gui/editor/guiGraphCtrl.cc
2017-04-17 06:17:10 -06:00

350 lines
9.5 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/console.h"
#include "console/consoleTypes.h"
#include "dgl/dgl.h"
#include "gui/editor/guiGraphCtrl.h"
IMPLEMENT_CONOBJECT(GuiGraphCtrl);
GuiGraphCtrl::GuiGraphCtrl()
{
for(int i = 0; i < MaxPlots; i++)
{
mPlots[i].mAutoPlot = NULL;
mPlots[i].mAutoPlotDelay = 0;
mPlots[i].mGraphColor = ColorF(1.0, 1.0, 1.0);
VECTOR_SET_ASSOCIATION(mPlots[i].mGraphData);
mPlots[i].mGraphMax = 1;
mPlots[i].mGraphType = Polyline;
for(int j = 0; j < MaxDataPoints; j++)
mPlots[i].mGraphData.push_front(0.0);
}
AssertWarn(MaxPlots == 6, "Only 6 plot colors initialized. Update following code if you change MaxPlots.");
mPlots[0].mGraphColor = ColorF(1.0, 1.0, 1.0);
mPlots[1].mGraphColor = ColorF(1.0, 0.0, 0.0);
mPlots[2].mGraphColor = ColorF(0.0, 1.0, 0.0);
mPlots[3].mGraphColor = ColorF(0.0, 0.0, 1.0);
mPlots[4].mGraphColor = ColorF(0.0, 1.0, 1.0);
mPlots[5].mGraphColor = ColorF(0.0, 0.0, 0.0);
}
static EnumTable::Enums enumGraphTypes[] = {
{ GuiGraphCtrl::Bar, "bar" },
{ GuiGraphCtrl::Filled, "filled" },
{ GuiGraphCtrl::Point, "point" },
{ GuiGraphCtrl::Polyline , "polyline" },
};
static EnumTable gGraphTypeTable( 4, &enumGraphTypes[0] );
bool GuiGraphCtrl::onWake()
{
if (! Parent::onWake())
return false;
setActive(true);
return true;
}
void GuiGraphCtrl::onRender(Point2I offset, const RectI &updateRect)
{
if (mProfile->mBorder)
{
RectI rect(offset.x, offset.y, mBounds.extent.x, mBounds.extent.y);
dglDrawRect(rect, mProfile->mBorderColor);
}
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
glEnable(GL_BLEND);
ColorF color(1.0, 1.0, 1.0, 0.5);
dglDrawRectFill(updateRect, color);
glDisable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ZERO);
for (int k = 0; k < MaxPlots; k++)
{
// Check if there is an autoplot and the proper amount of time has passed, if so add datum.
if((mPlots[k].mAutoPlot!=NULL) &&
(mPlots[k].mAutoPlotDelay < (Sim::getCurrentTime() - mPlots[k].mAutoPlotLastDisplay)))
{
mPlots[k].mAutoPlotLastDisplay = Sim::getCurrentTime();
addDatum(k, Con::getFloatVariable(mPlots[k].mAutoPlot));
Con::setIntVariable(mPlots[k].mAutoPlot, 0);
}
// Adjust scale to max value + 5% so we can see high values
F32 Scale = (F32(getExtent().y) / (F32(mPlots[k].mGraphMax*1.05)));
// Nothing to graph
if (mPlots[k].mGraphData.size() == 0)
continue;
// Bar graph
if(mPlots[k].mGraphType == Bar)
{
glBegin(GL_QUADS);
glColor3fv(mPlots[k].mGraphColor);
S32 temp1,temp2;
temp1 = 0;
for (S32 sample = 0; sample < getExtent().x; sample++)
{
if(mPlots[k].mGraphData.size() >= getExtent().x)
temp2 = sample;
else
temp2 = (S32)(((F32)getExtent().x / (F32)mPlots[k].mGraphData.size()) * (F32)sample);
glVertex2i(getPosition().x + temp1,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
glVertex2i(getPosition().x + temp2,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
glVertex2i(getPosition().x + temp2,
getPosition().y + getExtent().y);
glVertex2i(getPosition().x + temp1,
getPosition().y + getExtent().y);
temp1 = temp2;
}
glEnd();
}
// Filled graph
else if(mPlots[k].mGraphType == Filled)
{
glBegin(GL_QUADS);
glColor3fv(mPlots[k].mGraphColor);
S32 temp1,temp2;
temp1 = 0;
for (S32 sample = 0; sample < (getExtent().x-1); sample++)
{
if(mPlots[k].mGraphData.size() >= getExtent().x)
temp2 = sample;
else
temp2 = (S32)(((F32)getExtent().x / (F32)mPlots[k].mGraphData.size()) * (F32)sample);
glVertex2i(getPosition().x + temp1,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
glVertex2i(getPosition().x + temp2,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample+1) * Scale));
glVertex2i(getPosition().x + temp2,
getPosition().y + getExtent().y);
glVertex2i(getPosition().x + temp1,
getPosition().y + getExtent().y);
temp1 = temp2;
}
// last point
S32 sample = getExtent().x;
if(mPlots[k].mGraphData.size() >= getExtent().x)
temp2 = sample;
else
temp2 = (S32)(((F32)getExtent().x / (F32)mPlots[k].mGraphData.size()) * (F32)sample);
glVertex2i(getPosition().x + temp1,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
glVertex2i(getPosition().x + temp2,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
glVertex2i(getPosition().x + temp2,
getPosition().y + getExtent().y);
glVertex2i(getPosition().x + temp1,
getPosition().y + getExtent().y);
glEnd();
}
// Point or Polyline graph
else if((mPlots[k].mGraphType == Point) || (mPlots[k].mGraphType == Polyline))
{
if(mPlots[k].mGraphType == Point)
glBegin(GL_POINTS);
else
glBegin(GL_LINE_STRIP);
glColor3fv(mPlots[k].mGraphColor);
for (S32 sample = 0; sample < getExtent().x; sample++)
{
S32 temp;
if(mPlots[k].mGraphData.size() >= getExtent().x)
temp = sample;
else
temp = (S32)(((F32)getExtent().x / (F32)mPlots[k].mGraphData.size()) * (F32)sample);
glVertex2i(getPosition().x + temp,
(getPosition().y + getExtent().y) - (S32)(getDatum(k, sample) * Scale));
}
glEnd();
}
}
}
void GuiGraphCtrl::addDatum(S32 plotID, F32 v)
{
AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!");
// Add the data and trim the vector...
mPlots[plotID].mGraphData.push_front( v );
if(mPlots[plotID].mGraphData.size() > MaxDataPoints)
mPlots[plotID].mGraphData.pop_back();
// Keep record of maximum data value for scaling purposes.
if(v > mPlots[plotID].mGraphMax)
mPlots[plotID].mGraphMax = v;
}
float GuiGraphCtrl::getDatum( int plotID, int sample)
{
AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!");
AssertFatal(sample > -1 && sample < MaxDataPoints, "Invalid sample specified!");
return mPlots[plotID].mGraphData[sample];
}
void GuiGraphCtrl::addAutoPlot(S32 plotID, const char *variable, S32 update)
{
mPlots[plotID].mAutoPlot = StringTable->insert(variable);
mPlots[plotID].mAutoPlotDelay = update;
Con::setIntVariable(mPlots[plotID].mAutoPlot, 0);
}
void GuiGraphCtrl::removeAutoPlot(S32 plotID)
{
mPlots[plotID].mAutoPlot = NULL;
}
void GuiGraphCtrl::setGraphType(S32 plotID, const char *graphType)
{
AssertFatal(plotID > -1 && plotID < MaxPlots, "Invalid plot specified!");
if(!dStricmp(graphType,"Bar"))
mPlots[plotID].mGraphType = Bar;
else if(!dStricmp(graphType,"Filled"))
mPlots[plotID].mGraphType = Filled;
else if(!dStricmp(graphType,"Point"))
mPlots[plotID].mGraphType = Point;
else if(!dStricmp(graphType,"Polyline"))
mPlots[plotID].mGraphType = Polyline;
else AssertWarn(true, "Invalid graph type!");
}
ConsoleMethod(GuiGraphCtrl, addDatum, void, 4, 4, "(int plotID, float v)"
"Add a data point to the given plot.")
{
S32 plotID = dAtoi(argv[2]);
if(plotID > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return;
}
object->addDatum( plotID, dAtof(argv[3]));
}
ConsoleMethod(GuiGraphCtrl, getDatum, F32, 4, 4, "(int plotID, int samples)"
"Get a data point from the plot specified, samples from the start of the graph.")
{
S32 plotID = dAtoi(argv[2]);
S32 samples = dAtoi(argv[3]);
if(plotID > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return -1;
}
if(samples > object->MaxDataPoints)
{
Con::errorf("Invalid sample.");
return -1;
}
return object->getDatum(plotID, samples);
}
ConsoleMethod(GuiGraphCtrl, addAutoPlot, void, 5, 5, "(int plotID, string variable, int update)"
"Adds a data point with value variable, every update ms.")
{
S32 plotID = dAtoi(argv[2]);
if(plotID > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return;
}
object->addAutoPlot(plotID,argv[3],dAtoi(argv[4]));
}
ConsoleMethod(GuiGraphCtrl, removeAutoPlot, void, 3, 3, "(int plotID)"
"Stops automatic pointing over set interval.")
{
S32 plotID = dAtoi(argv[2]);
if(plotID > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return;
}
object->removeAutoPlot(plotID);
}
ConsoleMethod(GuiGraphCtrl, setGraphType, void, 4, 4, "(int plotID, string graphType)"
"Change GraphType of plot plotID.")
{
S32 plotID = dAtoi(argv[2]);
if(plotID > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return;
}
object->setGraphType(dAtoi(argv[2]), argv[3]);
}
ConsoleMethod(GuiGraphCtrl, matchScale, void, 3, GuiGraphCtrl::MaxPlots+2, "(int plotID, int plotID, ...)"
"Sets the scale of all specified plots to the maximum scale among them.")
{
F32 Max = 0;
for(int i=0; i < (argc-2); i++)
{
if(dAtoi(argv[2+i]) > object->MaxPlots)
{
Con::errorf("Invalid plotID.");
return;
}
if (object->mPlots[dAtoi(argv[2+i])].mGraphMax > Max)
Max = object->mPlots[dAtoi(argv[2+i])].mGraphMax;
}
for(int i=0; i < (argc-2); i++)
object->mPlots[dAtoi(argv[2+i])].mGraphMax = Max;
}