]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/splash.cxx
Clean-up cmake (linker) dependencies.
[flightgear.git] / src / Main / splash.cxx
index b9444f52816f8b19e74d7881f305f8da0bef6f79..a170a31f16fbc9e0f835d2bde333eb60ac0b5c0e 100644 (file)
@@ -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$
 
 #  include <config.h>
 #endif
 
-#ifdef FG_MATH_EXCEPTION_CLASH
-#  include <math.h>
-#endif
-
-#ifdef HAVE_WINDOWS_H          
-#  include <windows.h>
-#endif
-
-#include <GL/glut.h>
-#include <simgear/xgl/xgl.h>
-
-#include <string.h>
+#include <osg/BlendFunc>
+#include <osg/Camera>
+#include <osg/Depth>
+#include <osg/Geometry>
+#include <osg/Node>
+#include <osg/NodeCallback>
+#include <osg/NodeVisitor>
+#include <osg/StateSet>
+#include <osg/Switch>
+#include <osg/Texture2D>
+#include <osgUtil/CullVisitor>
+#include <osgText/Text>
+#include <osgDB/ReadFile>
+
+#include <simgear/compiler.h>
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/math/sg_random.h>
-#include <simgear/misc/fgpath.hxx>
+#include <simgear/misc/sg_path.hxx>
+
+#include <plib/fnt.h>
 
-#include <Objects/texload.h>
+#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<osg::Vec4Array> _colorArray;
+  SGSharedPtr<const SGPropertyNode> _colorProperty;
+  SGSharedPtr<const SGPropertyNode> _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<osgText::Text*>(drawable));
+    osgText::Text* text = static_cast<osgText::Text*>(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<const SGPropertyNode> _textProperty;
+  SGSharedPtr<const SGPropertyNode> _alphaProperty;
+  SGSharedPtr<const SGPropertyNode> _styleProperty;
+};
+
+
+
+class FGSplashContentProjectionCalback : public osg::NodeCallback {
+public:
+  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+  { 
+    assert(dynamic_cast<osgUtil::CullVisitor*>(nv));
+    osgUtil::CullVisitor* cullVisitor = static_cast<osgUtil::CullVisitor*>(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 GLuint splash_texid;
-static GLubyte *splash_texbuf;
-
-
-// Initialize the splash screen
-void fgSplashInit ( void ) {
-    int width, height;
-
-    FG_LOG( FG_GENERAL, FG_INFO, "Initializing splash screen" );
-#ifdef GL_VERSION_1_1
-    xglGenTextures(1, &splash_texid);
-    xglBindTexture(GL_TEXTURE_2D, splash_texid);
-#elif GL_EXT_texture_object
-    xglGenTexturesEXT(1, &splash_texid);
-    xglBindTextureEXT(GL_TEXTURE_2D, splash_texid);
-#else
-#  error port me
-#endif
-
-    xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);   
-    xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    xglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
+static osg::Node* fgCreateSplashCamera()
+{
+  const char* splash_texture = fgGetString("/sim/startup/splash-texture");
+  SGSharedPtr<SGPropertyNode> 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() * 4.0 + 1.0);
-    char num_str[256];
-    sprintf(num_str, "%d", num);
+    int num = (int)(sg_random() * 5.0 + 1.0);
+    char num_str[5];
+    snprintf(num_str, 4, "%d", num);
 
-    FGPath tpath( globals->get_options()->get_fg_root() );
     tpath.append( "Textures/Splash" );
     tpath.concat( num_str );
-    tpath.concat( ".rgb" );
-
-    if ( (splash_texbuf = 
-         read_rgb_texture(tpath.c_str(), &width, &height)) == NULL )
-    {
-       // Try compressed
-       FGPath fg_tpath = tpath;
-       fg_tpath.concat( ".gz" );
-       if ( (splash_texbuf = 
-             read_rgb_texture(fg_tpath.c_str(), &width, &height)) == NULL )
-       {
-           FG_LOG( FG_GENERAL, FG_ALERT, 
-                   "Error in loading splash screen texture " << tpath.str() );
-           exit(-1);
-       } 
-    } 
-
-    xglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
-                  GL_UNSIGNED_BYTE, (GLvoid *)(splash_texbuf) );
+    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 ) {
-    int xmin, ymin, xmax, ymax;
-    int xsize = 480;
-    int ysize = 380;
-
-    if ( !globals->get_options()->get_xsize()
-        || !globals->get_options()->get_ysize() ) {
-       return;
-    }
-
-    xmin = (globals->get_options()->get_xsize() - xsize) / 2;
-    xmax = xmin + xsize;
-
-    ymin = (globals->get_options()->get_ysize() - ysize) / 2;
-    ymax = ymin + ysize;
-
-    // first clear the screen;
-    xglClearColor(0.0, 0.0, 0.0, 1.0);
-    xglClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
-
-    // now draw the logo
-    xglMatrixMode(GL_PROJECTION);
-    xglPushMatrix();
-    xglLoadIdentity();
-    gluOrtho2D(0, globals->get_options()->get_xsize(),
-              0, globals->get_options()->get_ysize());
-    xglMatrixMode(GL_MODELVIEW);
-    xglPushMatrix();
-    xglLoadIdentity();
-
-    xglDisable(GL_DEPTH_TEST);
-    xglDisable(GL_LIGHTING);
-    xglEnable(GL_TEXTURE_2D);
-#ifdef GL_VERSION_1_1
-    xglBindTexture(GL_TEXTURE_2D, splash_texid);
-#elif GL_EXT_texture_object
-    xglBindTextureEXT(GL_TEXTURE_2D, splash_texid);
-#else
-#  error port me
-#endif
-    xglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-
-    xglBegin(GL_POLYGON);
-    xglTexCoord2f(0.0, 0.0); glVertex2f(xmin, ymin);
-    xglTexCoord2f(1.0, 0.0); glVertex2f(xmax, ymin);
-    xglTexCoord2f(1.0, 1.0); glVertex2f(xmax, ymax);
-    xglTexCoord2f(0.0, 1.0); glVertex2f(xmin, ymax); 
-    xglEnd();
-
-    xglutSwapBuffers();
-
-    xglEnable(GL_DEPTH_TEST);
-    xglEnable(GL_LIGHTING);
-    xglDisable(GL_TEXTURE_2D);
-
-    xglMatrixMode(GL_PROJECTION);
-    xglPopMatrix();
-    xglMatrixMode(GL_MODELVIEW);
-    xglPopMatrix();
+// 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<osg::Group*>(node));
+    osg::Group* group = static_cast<osg::Group*>(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<const SGPropertyNode> _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);
+}