X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Fsplash.cxx;h=a170a31f16fbc9e0f835d2bde333eb60ac0b5c0e;hb=da73dd97d3d0e36b6078728ac39f0b98cae46ff7;hp=c0bc348c949208d9639a1702584e4177fbb2a24d;hpb=51353ead72bf98def9da84b18b3f78b40a5b3123;p=flightgear.git diff --git a/src/Main/splash.cxx b/src/Main/splash.cxx index c0bc348c9..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,197 +26,351 @@ # include #endif -#ifdef SG_MATH_EXCEPTION_CLASH -# include -#endif - -#ifdef HAVE_WINDOWS_H -# include -#endif - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include #include -#include SG_GLU_H - #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" -static const int fontsize = 19; -static const char fontname[] = "default.txf"; -static const char *progress_text = 0; - - -static SGTexture splash; -static fntTexFont font; -static fntRenderer info; - - -// Initialize the splash screen -void fgSplashInit ( const char *splash_texture ) { - fgRequestRedraw(); - - SG_LOG( SG_GENERAL, SG_INFO, "Initializing splash screen" ); - - - SGPath fontpath; - char* envp = ::getenv("FG_FONTS"); - if (envp != NULL) { - fontpath.set(envp); +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 { - fontpath.set(globals->get_fg_root()); - fontpath.append("Fonts"); + height = viewportAspect; + width = 1; } - SGPath path(fontpath); - path.append(fontname); - if (!font.load((char *)path.c_str())) { - SG_LOG( SG_GENERAL, SG_ALERT, "Error loading font " << path.str() ); - return; - } + osg::RefMatrix* matrix = new osg::RefMatrix; + matrix->makeOrtho2D(-width, width, -height, height); - info.setFont(&font); - info.setPointSize(fontsize); - - if (!fgGetBool("/sim/startup/splash-screen")) - return; - - splash.bind(); - - SGPath tpath( globals->get_fg_root() ); - if (splash_texture == NULL || !strcmp(splash_texture, "")) { - // load in the texture data - int num = (int)(sg_random() * 5.0 + 1.0); - char num_str[5]; - snprintf(num_str, 4, "%d", num); - - tpath.append( "Textures/Splash" ); - tpath.concat( num_str ); - tpath.concat( ".rgb" ); - } else - tpath.append( splash_texture ); - - 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); - } - } + // 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(); + } +}; - splash.select(); +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; } - -void fgSplashProgress ( const char *s ) +static osg::Node* fgCreateSplashCamera() { - progress_text = s; - fgRequestRedraw(); + 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[5]; + snprintf(num_str, 4, "%d", num); + + tpath.append( "Textures/Splash" ); + tpath.concat( num_str ); + 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 alpha specified from 0.0 to 1.0 -void fgSplashUpdate ( float alpha ) { - int screen_width = fgGetInt("/sim/startup/xsize", 0); - int screen_height = fgGetInt("/sim/startup/ysize", 0); - - if (!screen_width || !screen_height) - return; - - int size = screen_width < (screen_height - 5 * fontsize) - ? screen_width : screen_height - 5 * fontsize; - if (size > 512) - size = 512; - - int xmin, ymin, xmax, ymax; - xmin = (screen_width - size) / 2; - xmax = xmin + size; - - ymin = (screen_height - size) / 2; - ymax = ymin + size; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluOrtho2D(0, screen_width, 0, screen_height); - 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(screen_width, 0.0); - glVertex2f(screen_width, screen_height); - glVertex2f(0.0, screen_height); - glEnd(); - - // now draw the logo - if (fgGetBool("/sim/startup/splash-screen", true)) { - 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(); - } - - if (info.getFont() && progress_text && fgGetBool("/sim/startup/splash-progress", true)) { - glEnable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - glAlphaFunc(GL_GREATER, 0.1f); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - - float left, right, bot, top; - - info.begin(); - glColor4f(1.0, 0.9, 0.0, alpha); - font.getBBox(progress_text, fontsize, 0, &left, &right, &bot, &top); - info.start2f((screen_width - right) / 2.0, 10.0 - bot); - info.puts(progress_text); - - const char *s = fgGetString("/sim/startup/splash-title", ""); - font.getBBox(s, fontsize, 0, &left, &right, &bot, &top); - info.start2f((screen_width - right) / 2.0, screen_height - top - bot - 10.0); - info.puts(s); - info.end(); - } - - 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); +}