723 lines
24 KiB
C++
723 lines
24 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#include <sstream>
|
|
#include <iomanip>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <osg/io_utils>
|
|
#include <osg/NodeVisitor>
|
|
|
|
#include <osg/MatrixTransform>
|
|
#include <osgViewer/Renderer>
|
|
#include <osgAnimation/StatsHandler>
|
|
#include <osgAnimation/EaseMotion>
|
|
#include <osgAnimation/StatsVisitor>
|
|
#include <osgViewer/ViewerEventHandlers>
|
|
#include <osgViewer/Renderer>
|
|
#include <osgAnimation/TimelineAnimationManager>
|
|
|
|
#include <osg/PolygonMode>
|
|
#include <osg/Geometry>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
|
|
static unsigned int getRandomValueinRange(unsigned int v)
|
|
{
|
|
return static_cast<unsigned int>((rand() * 1.0 * v)/(RAND_MAX-1));
|
|
}
|
|
|
|
|
|
namespace osgAnimation
|
|
{
|
|
|
|
|
|
osg::Geometry* createBackgroundRectangle(const osg::Vec3& pos, const float width, const float height, osg::Vec4& color)
|
|
{
|
|
osg::StateSet *ss = new osg::StateSet;
|
|
osg::Geometry* geometry = new osg::Geometry;
|
|
|
|
geometry->setUseDisplayList(false);
|
|
geometry->setStateSet(ss);
|
|
|
|
osg::Vec3Array* vertices = new osg::Vec3Array;
|
|
geometry->setVertexArray(vertices);
|
|
|
|
vertices->push_back(osg::Vec3(pos.x(), pos.y(), 0));
|
|
vertices->push_back(osg::Vec3(pos.x(), pos.y()-height,0));
|
|
vertices->push_back(osg::Vec3(pos.x()+width, pos.y()-height,0));
|
|
vertices->push_back(osg::Vec3(pos.x()+width, pos.y(),0));
|
|
|
|
osg::Vec4Array* colors = new osg::Vec4Array;
|
|
colors->push_back(color);
|
|
geometry->setColorArray(colors);
|
|
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
|
|
|
osg::DrawElementsUInt *base = new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS,0);
|
|
base->push_back(0);
|
|
base->push_back(1);
|
|
base->push_back(2);
|
|
base->push_back(3);
|
|
|
|
geometry->addPrimitiveSet(base);
|
|
|
|
return geometry;
|
|
}
|
|
|
|
struct StatsGraph : public osg::MatrixTransform
|
|
{
|
|
StatsGraph(osg::Vec3 pos, float width, float height)
|
|
: _pos(pos), _width(width), _height(height),
|
|
_statsGraphGeode(new osg::Geode)
|
|
{
|
|
_pos = pos - osg::Vec3(0, _height, 0.1);
|
|
setMatrix(osg::Matrix::translate(_pos));
|
|
setDataVariance(osg::Object::DYNAMIC);
|
|
addChild(_statsGraphGeode.get());
|
|
_statsGraphGeode->setCullingActive(false);
|
|
}
|
|
|
|
void changeYposition(float y)
|
|
{
|
|
osg::Vec3 _pos = getMatrix().getTrans();
|
|
_pos[1] = y - _height;
|
|
setMatrix(osg::Matrix::translate(_pos));
|
|
}
|
|
|
|
void addStatGraph(osg::Stats* viewerStats, osg::Stats* stats, const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
|
{
|
|
_statsGraphGeode->addDrawable(new Graph(_width, _height, viewerStats, stats, color, max, nameBegin, nameEnd));
|
|
}
|
|
|
|
osg::Vec3 _pos;
|
|
float _width;
|
|
float _height;
|
|
|
|
osg::ref_ptr<osg::Geode> _statsGraphGeode;
|
|
|
|
struct NeverCull : public osg::Drawable::CullCallback
|
|
{
|
|
NeverCull() {}
|
|
bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const { return false;}
|
|
};
|
|
|
|
|
|
struct Graph : public osg::Geometry
|
|
{
|
|
Graph(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
|
|
const osg::Vec4& color, float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
|
{
|
|
setDataVariance(osg::Object::DYNAMIC);
|
|
setUseDisplayList(false);
|
|
|
|
setVertexArray(new osg::Vec3Array);
|
|
getVertexArray()->setDataVariance(osg::Object::DYNAMIC);
|
|
setColor(color);
|
|
|
|
setUpdateCallback(new GraphUpdateCallback(width, height, viewerStats, stats, max, nameBegin, nameEnd));
|
|
setCullCallback(new NeverCull);
|
|
}
|
|
|
|
void setColor(const osg::Vec4& color) {
|
|
osg::Vec4Array* colors = new osg::Vec4Array;
|
|
colors->push_back(color);
|
|
setColorArray(colors);
|
|
setColorBinding(osg::Geometry::BIND_OVERALL);
|
|
}
|
|
};
|
|
|
|
|
|
struct GraphUpdateCallback : public osg::Drawable::UpdateCallback
|
|
{
|
|
|
|
const unsigned int _width;
|
|
const unsigned int _height;
|
|
mutable unsigned int _curX;
|
|
osg::Stats* _viewerStats;
|
|
osg::Stats* _stats;
|
|
const float _max;
|
|
const std::string _nameBegin;
|
|
const std::string _nameEnd;
|
|
mutable unsigned int _frameNumber;
|
|
|
|
GraphUpdateCallback(float width, float height, osg::Stats* viewerStats, osg::Stats* stats,
|
|
float max, const std::string& nameBegin, const std::string& nameEnd = "")
|
|
: _width((unsigned int)width), _height((unsigned int)height), _curX(0),
|
|
_viewerStats(viewerStats), _stats(stats), _max(max), _nameBegin(nameBegin), _nameEnd(nameEnd), _frameNumber(0)
|
|
{
|
|
}
|
|
virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable)
|
|
{
|
|
if (nv->getVisitorType() != osg::NodeVisitor::UPDATE_VISITOR)
|
|
return;
|
|
|
|
osg::Geometry* geometry = const_cast<osg::Geometry*>(drawable->asGeometry());
|
|
if (!geometry) return;
|
|
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
|
|
if (!vertices) return;
|
|
|
|
unsigned int frameNumber = nv->getFrameStamp()->getFrameNumber();
|
|
if (frameNumber == _frameNumber)
|
|
return;
|
|
|
|
|
|
// Get stats
|
|
double value;
|
|
if (_nameEnd.empty())
|
|
{
|
|
if (!_stats->getAttribute(_stats->getLatestFrameNumber(), _nameBegin, value ))
|
|
{
|
|
value = 0.0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double beginValue, endValue;
|
|
if (_stats->getAttribute( frameNumber, _nameBegin, beginValue) &&
|
|
_stats->getAttribute( frameNumber, _nameEnd, endValue) )
|
|
{
|
|
value = endValue - beginValue;
|
|
}
|
|
else
|
|
{
|
|
value = 0.0;
|
|
}
|
|
}
|
|
// Add new vertex for this frame.
|
|
value = osg::clampTo(value, 0.0, double(_max));
|
|
|
|
if (!vertices->size()) {
|
|
for (int i = 0; i < (int)_width; i++)
|
|
vertices->push_back(osg::Vec3(float(_curX++), 0, 0));
|
|
// Create primitive set if none exists.
|
|
if (geometry->getNumPrimitiveSets() == 0)
|
|
geometry->addPrimitiveSet(new osg::DrawArrays(GL_LINE_STRIP, 0, 0));
|
|
osg::DrawArrays* drawArrays = dynamic_cast<osg::DrawArrays*>(geometry->getPrimitiveSet(0));
|
|
drawArrays->setFirst(0);
|
|
drawArrays->setCount(vertices->size());
|
|
}
|
|
vertices->push_back(osg::Vec3(float(_curX), float(_height) / _max * value, 0));
|
|
|
|
unsigned int excedent = vertices->size() - _width;
|
|
vertices->erase(vertices->begin(), vertices->begin() + excedent);
|
|
|
|
// Make the graph scroll when there is enough data.
|
|
// Note: We check the frame number so that even if we have
|
|
// many graphs, the transform is translated only once per
|
|
// frame.
|
|
static const float increment = -1.0;
|
|
if (_frameNumber != frameNumber)
|
|
{
|
|
// We know the exact layout of this part of the scene
|
|
// graph, so this is OK...
|
|
osg::MatrixTransform* transform =
|
|
geometry->getParent(0)->getParent(0)->asTransform()->asMatrixTransform();
|
|
if (transform)
|
|
{
|
|
transform->setMatrix(transform->getMatrix() * osg::Matrix::translate(osg::Vec3(increment, 0, 0)));
|
|
}
|
|
}
|
|
|
|
_curX++;
|
|
_frameNumber = frameNumber;
|
|
|
|
geometry->dirtyBound();
|
|
}
|
|
};
|
|
};
|
|
|
|
// Drawcallback to draw averaged attribute
|
|
struct ValueTextDrawCallback : public virtual osg::Drawable::DrawCallback
|
|
{
|
|
ValueTextDrawCallback(osg::Stats* stats, const std::string& name):
|
|
_stats(stats),
|
|
_attributeName(name),
|
|
_frameNumber(0)
|
|
{
|
|
}
|
|
|
|
/** do customized draw code.*/
|
|
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
|
|
{
|
|
osgText::Text* text = (osgText::Text*)drawable;
|
|
|
|
unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber();
|
|
if (frameNumber == _frameNumber) {
|
|
text->drawImplementation(renderInfo);
|
|
return;
|
|
}
|
|
|
|
double value;
|
|
if (_stats->getAttribute(_stats->getLatestFrameNumber(), _attributeName, value))
|
|
{
|
|
sprintf(_tmpText,"%4.2f",value);
|
|
text->setText(_tmpText);
|
|
}
|
|
else
|
|
{
|
|
text->setText("");
|
|
}
|
|
_frameNumber = frameNumber;
|
|
text->drawImplementation(renderInfo);
|
|
}
|
|
|
|
osg::ref_ptr<osg::Stats> _stats;
|
|
std::string _attributeName;
|
|
mutable char _tmpText[128];
|
|
mutable unsigned int _frameNumber;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct StatAction
|
|
{
|
|
double _lastTime;
|
|
std::string _name;
|
|
osg::ref_ptr<osg::Group> _group;
|
|
osg::ref_ptr<osg::Geode> _label;
|
|
osg::ref_ptr<osg::MatrixTransform> _graph;
|
|
osg::ref_ptr<osgText::Text> _textLabel;
|
|
osgAnimation::OutCubicMotion _fade;
|
|
|
|
StatAction() { _lastTime = 0; _fade = osgAnimation::OutCubicMotion(0,5); }
|
|
void init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float heigh, const osg::Vec4& color);
|
|
void setPosition(const osg::Vec3& pos);
|
|
#if 0
|
|
void touch()
|
|
{
|
|
_lastTime = osg::Timer::instance()->time_s();
|
|
float a = 1.0 - _fade.getValueAt(0.0);
|
|
setAlpha(a);
|
|
}
|
|
bool update() {
|
|
double t = osg::Timer::instance()->time_s();
|
|
float alpha = 1.0 - _fade.getValueAt(t-_lastTime);
|
|
if (t - _lastTime > _fade.getDuration())
|
|
return true;
|
|
setAlpha(alpha);
|
|
return false;
|
|
}
|
|
#endif
|
|
void setAlpha(float v);
|
|
};
|
|
|
|
|
|
struct StatsTimeline : public osg::NodeCallback
|
|
{
|
|
static float _statsHeight;
|
|
static float _statsWidth;
|
|
|
|
osg::ref_ptr<osg::Geometry> _background;
|
|
osg::ref_ptr<osgAnimation::Timeline> _timeline;
|
|
osg::ref_ptr<osg::MatrixTransform> _group;
|
|
std::map<std::string, StatAction > _actions;
|
|
|
|
StatsTimeline()
|
|
{
|
|
_statsHeight = 1024;
|
|
_statsWidth = 1280;
|
|
}
|
|
osg::MatrixTransform* createStatsForTimeline(osgAnimation::Timeline* timeline)
|
|
{
|
|
_timeline = timeline;
|
|
|
|
std::string font("fonts/arial.ttf");
|
|
|
|
float leftPos = 10.0f;
|
|
float startBlocks = 150.0f;
|
|
float characterSize = 20.0f;
|
|
|
|
|
|
osg::Vec4 backgroundColor(0.0, 0.0, 0.0f, 0.3);
|
|
float backgroundMargin = 5;
|
|
//float backgroundSpacing = 3;
|
|
|
|
osg::Vec4 color(1.0, 1.0, 1.0, 1.0);
|
|
|
|
_group = new osg::MatrixTransform;
|
|
_group->setDataVariance(osg::Object::DYNAMIC);
|
|
|
|
{
|
|
osg::Vec3 pos(leftPos, _statsHeight-24.0f,0.0f);
|
|
//float topOfViewerStats = pos.y() + characterSize;
|
|
osg::ref_ptr<osg::Stats> stats = _timeline->getStats();
|
|
pos.y() -= characterSize + backgroundMargin;
|
|
|
|
{
|
|
osg::Geode* geode = new osg::Geode();
|
|
_group->addChild(geode);
|
|
osg::ref_ptr<osgText::Text> timeLabel = new osgText::Text;
|
|
geode->addDrawable( timeLabel.get() );
|
|
|
|
timeLabel->setColor(color);
|
|
timeLabel->setFont(font);
|
|
timeLabel->setCharacterSize(characterSize);
|
|
timeLabel->setPosition(pos);
|
|
timeLabel->setText("Time: ");
|
|
|
|
osg::ref_ptr<osgText::Text> timeLabelValue = new osgText::Text;
|
|
geode->addDrawable( timeLabelValue.get() );
|
|
|
|
timeLabelValue->setColor(color);
|
|
timeLabelValue->setFont(font);
|
|
timeLabelValue->setCharacterSize(characterSize);
|
|
timeLabelValue->setPosition(pos + osg::Vec3(startBlocks, 0,0));
|
|
timeLabelValue->setText("0.0");
|
|
|
|
timeLabelValue->setDrawCallback(new ValueTextDrawCallback(stats.get(),"Timeline"));
|
|
}
|
|
}
|
|
{
|
|
osg::Vec3 pos(leftPos, _statsHeight - 24.0f ,0.0f);
|
|
//float topOfViewerStats = pos.y();
|
|
osg::Geode* geode = new osg::Geode;
|
|
_background = createBackgroundRectangle(
|
|
pos + osg::Vec3(-backgroundMargin, backgroundMargin, 0),
|
|
_statsWidth - 2 * backgroundMargin,
|
|
(3 + 4.5 * 1) * characterSize + 2 * backgroundMargin,
|
|
backgroundColor);
|
|
geode->addDrawable(_background.get());
|
|
_group->addChild(geode);
|
|
}
|
|
|
|
return _group.get();
|
|
}
|
|
|
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
|
{
|
|
if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR) {
|
|
updateGraph();
|
|
}
|
|
traverse(node,nv);
|
|
}
|
|
|
|
void updateGraph()
|
|
{
|
|
osgAnimation::StatsActionVisitor* visitor = _timeline->getStatsVisitor();
|
|
if (!visitor)
|
|
return;
|
|
|
|
std::string font("fonts/arial.ttf");
|
|
float leftPos = 10.0f;
|
|
float characterSize = 20.0f;
|
|
|
|
float backgroundMargin = 5;
|
|
//float backgroundSpacing = 3;
|
|
float graphSpacing = 5;
|
|
|
|
float width = _statsWidth - 4 * backgroundMargin;
|
|
float height = characterSize;
|
|
osg::Vec3 pos(leftPos, _statsHeight-24.0f,0.0f);
|
|
pos.y() -= characterSize *2 + backgroundMargin;
|
|
|
|
for (std::map<std::string, StatAction >::iterator it = _actions.begin(); it != _actions.end(); ++it) {
|
|
(*it).second._group->setNodeMask(~osg::Node::NodeMask(1));
|
|
}
|
|
|
|
const std::vector<std::string>& channels = visitor->getChannels();
|
|
std::map<std::string,int> size;
|
|
for (int i = 0; i < (int)channels.size(); i++) {
|
|
std::string name = channels[i];
|
|
if (_actions.find(name) == _actions.end()) {
|
|
osg::Vec4 color(getRandomValueinRange(255)/255.0, getRandomValueinRange(255)/255.0, getRandomValueinRange(255)/255.0, 1.0);
|
|
_actions[name].init(visitor->getStats(), name, pos, width, height, color);
|
|
_group->addChild(_actions[name]._group.get());
|
|
//_actions[name].touch();
|
|
} else {
|
|
_actions[name].setPosition(pos);
|
|
//_actions[name].touch();
|
|
}
|
|
_actions[name]._group->setNodeMask(~osg::Node::NodeMask(0x0));
|
|
size[name] = 0;
|
|
pos.y() -= characterSize + graphSpacing;
|
|
}
|
|
|
|
pos.y() -= backgroundMargin;
|
|
osg::Vec3Array* array = dynamic_cast<osg::Vec3Array*>(_background->getVertexArray());
|
|
float y = (*array)[0][1];
|
|
y = y - (pos.y() + backgroundMargin); //(2 * backgroundMargin + (size.size() * (characterSize + graphSpacing)));
|
|
(*array)[1][1] = pos.y();
|
|
(*array)[2][1] = pos.y();
|
|
array->dirty();
|
|
_background->dirtyBound();
|
|
}
|
|
};
|
|
float StatsTimeline::_statsHeight;
|
|
float StatsTimeline::_statsWidth;
|
|
|
|
|
|
|
|
struct FindTimelineStats : public osg::NodeVisitor
|
|
{
|
|
std::vector<osg::ref_ptr<osgAnimation::Timeline> > _timelines;
|
|
|
|
FindTimelineStats() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
|
|
|
|
void apply(osg::Node& node) {
|
|
osg::NodeCallback* cb = node.getUpdateCallback();
|
|
while (cb) {
|
|
osgAnimation::TimelineAnimationManager* tam = dynamic_cast<osgAnimation::TimelineAnimationManager*>(cb);
|
|
if (tam)
|
|
_timelines.push_back(tam->getTimeline());
|
|
cb = cb->getNestedCallback();
|
|
}
|
|
traverse(node);
|
|
}
|
|
};
|
|
|
|
|
|
StatsHandler::StatsHandler():
|
|
_keyEventTogglesOnScreenStats('a'),
|
|
_keyEventPrintsOutStats('A'),
|
|
_statsType(NO_STATS),
|
|
_initialized(false),
|
|
_statsWidth(1280.0f),
|
|
_statsHeight(1024.0f)
|
|
{
|
|
_camera = new osg::Camera;
|
|
_camera->setRenderer(new osgViewer::Renderer(_camera.get()));
|
|
_camera->setProjectionResizePolicy(osg::Camera::FIXED);
|
|
}
|
|
|
|
bool StatsHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
|
|
{
|
|
osgViewer::View* myview = dynamic_cast<osgViewer::View*>(&aa);
|
|
if (!myview) return false;
|
|
|
|
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(myview->getViewerBase());
|
|
|
|
if (!viewer->getSceneData())
|
|
return false;
|
|
if (ea.getHandled()) return false;
|
|
|
|
switch(ea.getEventType())
|
|
{
|
|
case(osgGA::GUIEventAdapter::KEYDOWN):
|
|
{
|
|
if (ea.getKey()==_keyEventTogglesOnScreenStats)
|
|
{
|
|
if (viewer->getViewerStats())
|
|
{
|
|
|
|
if (!_switch.get()) {
|
|
FindTimelineStats finder;
|
|
viewer->getSceneData()->accept(finder);
|
|
if (finder._timelines.empty())
|
|
return false;
|
|
}
|
|
|
|
if (!_initialized)
|
|
{
|
|
setUpHUDCamera(viewer);
|
|
setUpScene(dynamic_cast<osgViewer::Viewer*>(viewer));
|
|
}
|
|
|
|
++_statsType;
|
|
|
|
if (_statsType==LAST) _statsType = NO_STATS;
|
|
|
|
|
|
switch(_statsType)
|
|
{
|
|
case(NO_STATS):
|
|
{
|
|
_camera->setNodeMask(0x0);
|
|
_switch->setAllChildrenOff();
|
|
break;
|
|
}
|
|
case(FRAME_RATE):
|
|
{
|
|
_camera->setNodeMask(0xffffffff);
|
|
_switch->setAllChildrenOn();
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
}
|
|
return true;
|
|
}
|
|
if (ea.getKey()==_keyEventPrintsOutStats)
|
|
{
|
|
FindTimelineStats finder;
|
|
viewer->getSceneData()->accept(finder);
|
|
if (!finder._timelines.empty()) {
|
|
OSG_NOTICE<<std::endl<<"Stats report:"<<std::endl;
|
|
typedef std::vector<osg::Stats*> StatsList;
|
|
StatsList statsList;
|
|
|
|
for (unsigned int i = 0; i < finder._timelines.size(); i++)
|
|
statsList.push_back(finder._timelines[i]->getStats());
|
|
|
|
for(unsigned int i = statsList[0]->getEarliestFrameNumber(); i< statsList[0]->getLatestFrameNumber(); ++i)
|
|
{
|
|
for(StatsList::iterator itr = statsList.begin();
|
|
itr != statsList.end();
|
|
++itr)
|
|
{
|
|
if (itr==statsList.begin()) (*itr)->report(osg::notify(osg::NOTICE), i);
|
|
else (*itr)->report(osg::notify(osg::NOTICE), i, " ");
|
|
}
|
|
OSG_NOTICE<<std::endl;
|
|
}
|
|
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
default: break;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void StatsHandler::reset()
|
|
{
|
|
_initialized = false;
|
|
_camera->setGraphicsContext(0);
|
|
_camera->removeChildren( 0, _camera->getNumChildren() );
|
|
}
|
|
|
|
void StatsHandler::setUpHUDCamera(osgViewer::ViewerBase* viewer)
|
|
{
|
|
osgViewer::GraphicsWindow* window = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
|
|
|
|
if (!window)
|
|
{
|
|
osgViewer::Viewer::Windows windows;
|
|
viewer->getWindows(windows);
|
|
|
|
if (windows.empty()) return;
|
|
|
|
window = windows.front();
|
|
}
|
|
|
|
_camera->setGraphicsContext(window);
|
|
|
|
_camera->setViewport(0, 0, window->getTraits()->width, window->getTraits()->height);
|
|
|
|
_camera->setRenderOrder(osg::Camera::POST_RENDER, 10);
|
|
|
|
_camera->setProjectionMatrix(osg::Matrix::ortho2D(0.0,_statsWidth,0.0,_statsHeight));
|
|
_camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
|
|
_camera->setViewMatrix(osg::Matrix::identity());
|
|
|
|
// only clear the depth buffer
|
|
_camera->setClearMask(0); //GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //-1);
|
|
_camera->setAllowEventFocus(false);
|
|
_camera->setCullMask(0x1);
|
|
osgViewer::Viewer* v = dynamic_cast<osgViewer::Viewer*>(viewer);
|
|
v->getSceneData()->asGroup()->addChild(_camera.get());
|
|
_initialized = true;
|
|
}
|
|
|
|
void StatsHandler::setUpScene(osgViewer::Viewer* viewer)
|
|
{
|
|
if (!viewer->getSceneData())
|
|
return;
|
|
|
|
FindTimelineStats finder;
|
|
viewer->getSceneData()->accept(finder);
|
|
if (finder._timelines.empty())
|
|
return;
|
|
|
|
_switch = new osg::Switch;
|
|
osg::StateSet* stateset = _switch->getOrCreateStateSet();
|
|
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
|
|
stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
|
|
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
|
|
stateset->setAttribute(new osg::PolygonMode(), osg::StateAttribute::PROTECTED);
|
|
|
|
_group = new osg::Group;
|
|
_camera->addChild(_switch.get());
|
|
_switch->addChild(_group.get());
|
|
|
|
for (int i = 0; i < (int)finder._timelines.size(); i++) {
|
|
StatsTimeline* s = new StatsTimeline;
|
|
osg::MatrixTransform* m = s->createStatsForTimeline(finder._timelines[i].get());
|
|
m->setUpdateCallback(s);
|
|
m->setMatrix(osg::Matrix::translate(0, -i * 100, 0));
|
|
_group->addChild(m);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void StatAction::init(osg::Stats* stats, const std::string& name, const osg::Vec3& pos, float width, float height, const osg::Vec4& color)
|
|
{
|
|
std::string font("fonts/arial.ttf");
|
|
float characterSize = 20.0f;
|
|
float startBlocks = 150.0f;
|
|
|
|
_name = name;
|
|
_group = new osg::Group;
|
|
|
|
_label = new osg::Geode;
|
|
_textLabel = new osgText::Text;
|
|
_label->addDrawable(_textLabel.get());
|
|
_textLabel->setDataVariance(osg::Object::DYNAMIC);
|
|
_textLabel->setColor(color);
|
|
_textLabel->setFont(font);
|
|
_textLabel->setCharacterSize(characterSize);
|
|
_textLabel->setPosition(pos - osg::Vec3(0, height, 0));
|
|
_textLabel->setText(name);
|
|
|
|
StatsGraph* graph = new StatsGraph(pos + osg::Vec3(startBlocks, 0,0) , width-startBlocks, height);
|
|
graph->setCullingActive(false);
|
|
graph->addStatGraph(stats, stats, color, 1.0, name);
|
|
_graph = graph;
|
|
|
|
_group->addChild(_label.get());
|
|
_group->addChild(_graph.get());
|
|
}
|
|
void StatAction::setAlpha(float v)
|
|
{
|
|
std::cout << this << " color alpha " << v << std::endl;
|
|
StatsGraph* gfx = dynamic_cast<StatsGraph*>(_graph.get());
|
|
osg::Vec4 color = _textLabel->getColor();
|
|
color[3] = v;
|
|
_textLabel->setColor(color);
|
|
for (int i = 0; i < (int) gfx->_statsGraphGeode->getNumDrawables(); i++) {
|
|
StatsGraph::Graph* g = dynamic_cast<StatsGraph::Graph*>(gfx->_statsGraphGeode->getDrawable(0));
|
|
g->setColor(color);
|
|
}
|
|
}
|
|
|
|
void StatAction::setPosition(const osg::Vec3& pos)
|
|
{
|
|
float characterSize = 20.0f;
|
|
StatsGraph* gfx = dynamic_cast<StatsGraph*>(_graph.get());
|
|
gfx->changeYposition(pos[1]);
|
|
_textLabel->setPosition(pos - osg::Vec3(0, characterSize,0));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
void StatsHandler::getUsage(osg::ApplicationUsage& usage) const
|
|
{
|
|
usage.addKeyboardMouseBinding("s","On screen stats.");
|
|
usage.addKeyboardMouseBinding("S","Output stats to console.");
|
|
}
|
|
|
|
}
|