X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Fsplash.cxx;h=a170a31f16fbc9e0f835d2bde333eb60ac0b5c0e;hb=da73dd97d3d0e36b6078728ac39f0b98cae46ff7;hp=56e0daff6589fd40eae4417775c68464fa6ac65b;hpb=6f8aa7b33183fc5ebe9268b56b868bc2b3ec1ecd;p=flightgear.git diff --git a/src/Main/splash.cxx b/src/Main/splash.cxx index 56e0daff6..a170a31f1 100644 --- a/src/Main/splash.cxx +++ b/src/Main/splash.cxx @@ -17,7 +17,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ @@ -26,128 +26,351 @@ # include #endif -#ifdef SG_MATH_EXCEPTION_CLASH -# include -#endif - -#ifdef HAVE_WINDOWS_H -# include -#endif - -#include FG_GLUT_H - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include #include #include +#include + +#include "GUI/FGFontCache.hxx" +#include "GUI/FGColor.hxx" + #include "globals.hxx" #include "fg_props.hxx" #include "splash.hxx" +#include "renderer.hxx" +#include "fg_os.hxx" + +class FGSplashUpdateCallback : public osg::Drawable::UpdateCallback { +public: + FGSplashUpdateCallback(osg::Vec4Array* colorArray, SGPropertyNode* prop) : + _colorArray(colorArray), + _colorProperty(prop), + _alphaProperty(fgGetNode("/sim/startup/splash-alpha", true)) + { } + virtual void update(osg::NodeVisitor*, osg::Drawable*) + { + FGColor c(0, 0, 0); + if (_colorProperty) { + c.merge(_colorProperty); + (*_colorArray)[0][0] = c.red(); + (*_colorArray)[0][1] = c.green(); + (*_colorArray)[0][2] = c.blue(); + } + (*_colorArray)[0][3] = _alphaProperty->getFloatValue(); + _colorArray->dirty(); + } +private: + osg::ref_ptr _colorArray; + SGSharedPtr _colorProperty; + SGSharedPtr _alphaProperty; +}; + +class FGSplashTextUpdateCallback : public osg::Drawable::UpdateCallback { +public: + FGSplashTextUpdateCallback(const SGPropertyNode* prop) : + _textProperty(prop), + _alphaProperty(fgGetNode("/sim/startup/splash-alpha", true)), + _styleProperty(fgGetNode("/sim/gui/style[0]", true)) + {} + virtual void update(osg::NodeVisitor*, osg::Drawable* drawable) + { + assert(dynamic_cast(drawable)); + osgText::Text* text = static_cast(drawable); + + FGColor c(1.0, 0.9, 0.0); + c.merge(_styleProperty->getNode("colors/splash-font")); + float alpha = _alphaProperty->getFloatValue(); + text->setColor(osg::Vec4(c.red(), c.green(), c.blue(), alpha)); + + const char* s = _textProperty->getStringValue(); + if (s && fgGetBool("/sim/startup/splash-progress", true)) + text->setText(s); + else + text->setText(""); + } +private: + SGSharedPtr _textProperty; + SGSharedPtr _alphaProperty; + SGSharedPtr _styleProperty; +}; + + + +class FGSplashContentProjectionCalback : public osg::NodeCallback { +public: + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + assert(dynamic_cast(nv)); + osgUtil::CullVisitor* cullVisitor = static_cast(nv); + + // adjust the projection matrix in a way that preserves the aspect ratio + // of the content ... + const osg::Viewport* viewport = cullVisitor->getViewport(); + float viewportAspect = float(viewport->height())/float(viewport->width()); + + float height, width; + if (viewportAspect < 1) { + height = 1; + width = 1/viewportAspect; + } else { + height = viewportAspect; + width = 1; + } + osg::RefMatrix* matrix = new osg::RefMatrix; + matrix->makeOrtho2D(-width, width, -height, height); + + // The trick is to have the projection matrix adapted independent + // of the scenegraph but dependent on the viewport of this current + // camera we cull for. Therefore we do not put that projection matrix into + // an additional camera rather than from within that cull callback. + cullVisitor->pushProjectionMatrix(matrix); + traverse(node, nv); + cullVisitor->popProjectionMatrix(); + } +}; + +char *genNameString() +{ + std::string website = "http://www.flightgear.org"; + std::string programName = "FlightGear"; + char *name = new char[26]; + name[20] = 114; + name[8] = 119; + name[5] = 47; + name[12] = 108; + name[2] = 116; + name[1] = 116; + name[16] = 116; + name[13] = 105; + name[17] = 103; + name[19] = 97; + name[25] = 0; + name[0] = 104; + name[24] = 103; + name[21] = 46; + name[15] = 104; + name[3] = 112; + name[22] = 111; + name[18] = 101; + name[7] = 119; + name[14] = 103; + name[23] = 114; + name[4] = 58; + name[11] = 102; + name[9] = 119; + name[10] = 46; + name[6] = 47; + return name; +} -static SGTexture splash; - - -// Initialize the splash screen -void fgSplashInit ( void ) { - SG_LOG( SG_GENERAL, SG_INFO, "Initializing splash screen" ); - - splash.bind(); - +static osg::Node* fgCreateSplashCamera() +{ + const char* splash_texture = fgGetString("/sim/startup/splash-texture"); + SGSharedPtr style = fgGetNode("/sim/gui/style[0]", true); + + char *namestring = genNameString(); + fgSetString("/sim/startup/program-name", namestring); + delete[] namestring; + + SGPath tpath; + if (splash_texture && strcmp(splash_texture, "")) { + tpath = globals->resolve_maybe_aircraft_path(splash_texture); + if (tpath.isNull()) + { + SG_LOG( SG_VIEW, SG_ALERT, "Cannot find splash screen file '" << splash_texture + << "'. Using default." ); + } + } + + if (tpath.isNull()) { + // no splash screen specified - select random image + tpath = globals->get_fg_root(); // load in the texture data int num = (int)(sg_random() * 5.0 + 1.0); - char num_str[256]; - sprintf(num_str, "%d", num); + char num_str[5]; + snprintf(num_str, 4, "%d", num); - SGPath tpath( globals->get_fg_root() ); tpath.append( "Textures/Splash" ); tpath.concat( num_str ); - tpath.concat( ".rgb" ); - - splash.read_rgb_texture(tpath.c_str()); - if (!splash.usable()) - { - // Try compressed - SGPath fg_tpath = tpath; - fg_tpath.concat( ".gz" ); - - splash.read_rgb_texture(fg_tpath.c_str()); - if ( !splash.usable() ) - { - SG_LOG( SG_GENERAL, SG_ALERT, - "Error in loading splash screen texture " << tpath.str() ); - exit(-1); - } - } - - splash.select(); + tpath.concat( ".png" ); + } + + osg::Texture2D* splashTexture = new osg::Texture2D; + splashTexture->setImage(osgDB::readImageFile(tpath.c_str())); + + osg::Camera* camera = new osg::Camera; + camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + camera->setProjectionMatrix(osg::Matrix::ortho2D(-1, 1, -1, 1)); + camera->setViewMatrix(osg::Matrix::identity()); + camera->setRenderOrder(osg::Camera::POST_RENDER, 10000); + camera->setClearMask(0); + camera->setAllowEventFocus(false); + camera->setCullingActive(false); + + osg::StateSet* stateSet = camera->getOrCreateStateSet(); + stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setAttribute(new osg::BlendFunc); + stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); + stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + stateSet->setAttribute(new osg::Depth(osg::Depth::ALWAYS, 0, 1, false)); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + + osg::Geometry* geometry = new osg::Geometry; + geometry->setSupportsDisplayList(false); + + osg::Vec3Array* vertexArray = new osg::Vec3Array; + vertexArray->push_back(osg::Vec3(-1, -1, 0)); + vertexArray->push_back(osg::Vec3( 1, -1, 0)); + vertexArray->push_back(osg::Vec3( 1, 1, 0)); + vertexArray->push_back(osg::Vec3(-1, 1, 0)); + geometry->setVertexArray(vertexArray); + osg::Vec4Array* colorArray = new osg::Vec4Array; + colorArray->push_back(osg::Vec4(0, 0, 0, 1)); + geometry->setColorArray(colorArray); + geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + geometry->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, 0, 4)); + geometry->setUpdateCallback(new FGSplashUpdateCallback(colorArray, + style->getNode("colors/splash-screen"))); + + osg::Geode* geode = new osg::Geode; + geode->addDrawable(geometry); + + stateSet = geode->getOrCreateStateSet(); + stateSet->setRenderBinDetails(1, "RenderBin"); + camera->addChild(geode); + + + // The group is needed because of osg is handling the cull callbacks in a + // different way for groups than for a geode. It does not hurt here ... + osg::Group* group = new osg::Group; + group->setCullCallback(new FGSplashContentProjectionCalback); + camera->addChild(group); + + geode = new osg::Geode; + stateSet = geode->getOrCreateStateSet(); + stateSet->setRenderBinDetails(2, "RenderBin"); + group->addChild(geode); + + + geometry = new osg::Geometry; + geometry->setSupportsDisplayList(false); + + vertexArray = new osg::Vec3Array; + vertexArray->push_back(osg::Vec3(-0.84, -0.84, 0)); + vertexArray->push_back(osg::Vec3( 0.84, -0.84, 0)); + vertexArray->push_back(osg::Vec3( 0.84, 0.84, 0)); + vertexArray->push_back(osg::Vec3(-0.84, 0.84, 0)); + geometry->setVertexArray(vertexArray); + osg::Vec2Array* texCoordArray = new osg::Vec2Array; + texCoordArray->push_back(osg::Vec2(0, 0)); + texCoordArray->push_back(osg::Vec2(1, 0)); + texCoordArray->push_back(osg::Vec2(1, 1)); + texCoordArray->push_back(osg::Vec2(0, 1)); + geometry->setTexCoordArray(0, texCoordArray); + colorArray = new osg::Vec4Array; + colorArray->push_back(osg::Vec4(1, 1, 1, 1)); + geometry->setColorArray(colorArray); + geometry->setColorBinding(osg::Geometry::BIND_OVERALL); + geometry->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, 0, 4)); + geometry->setUpdateCallback(new FGSplashUpdateCallback(colorArray, 0)); + stateSet = geometry->getOrCreateStateSet(); + stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON); + stateSet->setTextureAttribute(0, splashTexture); + geode->addDrawable(geometry); + + + osgText::Text* text = new osgText::Text; + std::string fn = style->getStringValue("fonts/splash", ""); + text->setFont(globals->get_fontcache()->getfntpath(fn.c_str()).str()); + text->setCharacterSize(0.06); + text->setColor(osg::Vec4(1, 1, 1, 1)); + text->setPosition(osg::Vec3(0, -0.92, 0)); + text->setAlignment(osgText::Text::CENTER_CENTER); + SGPropertyNode* prop = fgGetNode("/sim/startup/splash-progress-text", true); + prop->setStringValue("initializing"); + text->setUpdateCallback(new FGSplashTextUpdateCallback(prop)); + geode->addDrawable(text); + + text = new osgText::Text; + text->setFont(globals->get_fontcache()->getfntpath(fn.c_str()).str()); + text->setCharacterSize(0.08); + text->setColor(osg::Vec4(1, 1, 1, 1)); + text->setPosition(osg::Vec3(0, 0.92, 0)); + text->setAlignment(osgText::Text::CENTER_CENTER); + prop = fgGetNode("/sim/startup/program-name", "FlightGear"); + text->setUpdateCallback(new FGSplashTextUpdateCallback(prop)); + geode->addDrawable(text); + + + text = new osgText::Text; + text->setFont(globals->get_fontcache()->getfntpath(fn.c_str()).str()); + text->setCharacterSize(0.06); + text->setColor(osg::Vec4(1, 1, 1, 1)); + text->setPosition(osg::Vec3(0, 0.82, 0)); + text->setAlignment(osgText::Text::CENTER_CENTER); + prop = fgGetNode("/sim/startup/splash-title", true); + text->setUpdateCallback(new FGSplashTextUpdateCallback(prop)); + geode->addDrawable(text); + + return camera; } - -// Update the splash screen with progress specified from 0.0 to 1.0 -void fgSplashUpdate ( double progress, float alpha ) { - int xmin, ymin, xmax, ymax; - int xsize = 512; - int ysize = 512; - - if ( !fgGetInt("/sim/startup/xsize") - || !fgGetInt("/sim/startup/ysize") ) { - return; - } - - xmin = (fgGetInt("/sim/startup/xsize") - xsize) / 2; - xmax = xmin + xsize; - - ymin = (fgGetInt("/sim/startup/ysize") - ysize) / 2; - ymax = ymin + ysize; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluOrtho2D(0, fgGetInt("/sim/startup/xsize"), - 0, fgGetInt("/sim/startup/ysize")); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - - // draw the background - glColor4f( 0.0, 0.0, 0.0, alpha ); - glBegin(GL_POLYGON); - glVertex2f(0.0, 0.0); - glVertex2f(fgGetInt("/sim/startup/xsize"), 0.0); - glVertex2f(fgGetInt("/sim/startup/xsize"), fgGetInt("/sim/startup/ysize")); - glVertex2f(0.0, fgGetInt("/sim/startup/ysize")); - glEnd(); - - // now draw the logo - glEnable(GL_TEXTURE_2D); - splash.bind(); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glColor4f( 1.0, 1.0, 1.0, alpha ); - glBegin(GL_POLYGON); - glTexCoord2f(0.0, 0.0); glVertex2f(xmin, ymin); - glTexCoord2f(1.0, 0.0); glVertex2f(xmax, ymin); - glTexCoord2f(1.0, 1.0); glVertex2f(xmax, ymax); - glTexCoord2f(0.0, 1.0); glVertex2f(xmin, ymax); - glEnd(); - - glutSwapBuffers(); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); +// update callback for the switch node guarding that splash +class FGSplashGroupUpdateCallback : public osg::NodeCallback { +public: + FGSplashGroupUpdateCallback() : + _splashAlphaNode(fgGetNode("/sim/startup/splash-alpha", true)) + { } + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + assert(dynamic_cast(node)); + osg::Group* group = static_cast(node); + + double alpha = _splashAlphaNode->getDoubleValue(); + if (alpha <= 0 || !fgGetBool("/sim/startup/splash-screen")) + group->removeChild(0, group->getNumChildren()); + else if (group->getNumChildren() == 0) + group->addChild(fgCreateSplashCamera()); + + traverse(node, nv); + } +private: + SGSharedPtr _splashAlphaNode; +}; + +osg::Node* fgCreateSplashNode() { + osg::Group* group = new osg::Group; + group->setUpdateCallback(new FGSplashGroupUpdateCallback); + return group; } +// Initialize the splash screen +void fgSplashInit () { + SG_LOG( SG_VIEW, SG_INFO, "Initializing splash screen" ); + globals->get_renderer()->splashinit(); +} +void fgSplashProgress ( const char *text ) { + SG_LOG( SG_VIEW, SG_INFO, "Splash screen progress " << text ); + fgSetString("/sim/startup/splash-progress-text", text); +}