Update FGPanel:
- use OpenGL 2.0 instead of OpenGL 1.0; - port to Raspberry Pi; - remove PLib dependencies.
This commit is contained in:
parent
c9b01b1d69
commit
effca9da5e
48 changed files with 4471 additions and 2835 deletions
69
utils/fgpanel/ApplicationProperties.cxx
Normal file
69
utils/fgpanel/ApplicationProperties.cxx
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Written and (c) Torsten Dreyer - Torsten(at)t3r_dot_de
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "ApplicationProperties.hxx"
|
||||
|
||||
double
|
||||
ApplicationProperties::getDouble (const char *name, const double def) {
|
||||
const SGPropertyNode_ptr n (ApplicationProperties::Properties->getNode (name, false));
|
||||
if (n == NULL) {
|
||||
return def;
|
||||
}
|
||||
return n->getDoubleValue ();
|
||||
}
|
||||
|
||||
SGPath
|
||||
ApplicationProperties::GetCwd () {
|
||||
SGPath path (".");
|
||||
char buf[512];
|
||||
char *cwd (getcwd (buf, 511));
|
||||
buf[511] = '\0';
|
||||
if (cwd) {
|
||||
path = SGPath::fromLocal8Bit (cwd);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
SGPath
|
||||
ApplicationProperties::GetRootPath (const char *sub) {
|
||||
if (sub != NULL) {
|
||||
const SGPath subpath (sub);
|
||||
|
||||
// relative path to current working dir?
|
||||
if (subpath.isRelative ()) {
|
||||
SGPath path (GetCwd ());
|
||||
path.append (sub);
|
||||
if (path.exists ()) {
|
||||
return path;
|
||||
}
|
||||
} else if (subpath.exists ()) {
|
||||
// absolute path
|
||||
return subpath;
|
||||
}
|
||||
}
|
||||
|
||||
// default: relative path to FGROOT
|
||||
SGPath path (ApplicationProperties::root);
|
||||
if (sub != NULL) {
|
||||
path.append (sub);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
string ApplicationProperties::root = ".";
|
||||
SGPropertyNode_ptr ApplicationProperties::Properties = new SGPropertyNode;
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -17,16 +17,19 @@
|
|||
//
|
||||
#ifndef __APPLICATION_PROPERTIES
|
||||
#define __APPLICATION_PROPERTIES
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include "FGFontCache.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ApplicationProperties {
|
||||
public:
|
||||
static double getDouble( const char * name, double def = 0.0 );
|
||||
static SGPath GetRootPath( const char * subDir = NULL );
|
||||
static SGPath GetCwd();
|
||||
static double getDouble (const char *name, const double def = 0.0);
|
||||
static SGPath GetRootPath (const char *subDir = NULL);
|
||||
static SGPath GetCwd ();
|
||||
static SGPropertyNode_ptr Properties;
|
||||
static std::string root;
|
||||
static FGFontCache fontCache;
|
||||
static string root;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,40 +1,103 @@
|
|||
find_package(PNG REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLUT REQUIRED)
|
||||
if(GLUT_FOUND)
|
||||
message(STATUS "found glut")
|
||||
find_path(BCMHOST_INCLUDE_DIR
|
||||
NAMES bcm_host.h
|
||||
PATHS /opt/vc/include
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
add_executable(fgpanel main.cxx
|
||||
ApplicationProperties.hxx
|
||||
FGGLApplication.cxx
|
||||
FGGLApplication.hxx
|
||||
FGPanelApplication.cxx
|
||||
FGPanelApplication.hxx
|
||||
FGPNGTextureLoader.cxx
|
||||
FGPNGTextureLoader.hxx
|
||||
FGRGBTextureLoader.cxx
|
||||
FGRGBTextureLoader.hxx
|
||||
FGPanelProtocol.cxx
|
||||
FGPanelProtocol.hxx
|
||||
FGFontCache.cxx
|
||||
FGFontCache.hxx
|
||||
panel.cxx
|
||||
panel.hxx
|
||||
panel_io.cxx
|
||||
panel_io.hxx
|
||||
)
|
||||
include_directories(
|
||||
/usr/include/freetype2
|
||||
${PNG_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(fgpanel
|
||||
${PNG_LIBRARIES}
|
||||
${GLUT_LIBRARIES}
|
||||
SimGearCore
|
||||
${OPENGL_LIBRARIES}
|
||||
${PLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
include_directories(${PNG_INCLUDE_DIR})
|
||||
|
||||
install(TARGETS fgpanel RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
if(${BCMHOST_INCLUDE_DIR} STREQUAL "BCMHOST_INCLUDE_DIR-NOTFOUND")
|
||||
else()
|
||||
message(STATUS "glut NOT found, can't build fgpanel")
|
||||
# CMAKE > 3.1 : target_sources(fgpanel
|
||||
set(TARGET_SOURCES
|
||||
GLES_utils.cxx
|
||||
GLES_utils.hxx
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(fgpanel
|
||||
main.cxx
|
||||
ApplicationProperties.hxx
|
||||
ApplicationProperties.cxx
|
||||
FGCroppedTexture.hxx
|
||||
FGCroppedTexture.cxx
|
||||
FGDummyTextureLoader.hxx
|
||||
FGDummyTextureLoader.cxx
|
||||
FGFontCache.cxx
|
||||
FGFontCache.hxx
|
||||
FGGLApplication.cxx
|
||||
FGGLApplication.hxx
|
||||
FGGroupLayer.cxx
|
||||
FGGroupLayer.hxx
|
||||
FGInstrumentLayer.cxx
|
||||
FGInstrumentLayer.hxx
|
||||
FGLayeredInstrument.cxx
|
||||
FGLayeredInstrument.hxx
|
||||
FGPanel.cxx
|
||||
FGPanel.hxx
|
||||
FGPanelApplication.cxx
|
||||
FGPanelApplication.hxx
|
||||
FGPanelInstrument.cxx
|
||||
FGPanelInstrument.hxx
|
||||
FGPanelProtocol.cxx
|
||||
FGPanelProtocol.hxx
|
||||
FGPanelTransformation.cxx
|
||||
FGPanelTransformation.hxx
|
||||
FGPNGTextureLoader.cxx
|
||||
FGPNGTextureLoader.hxx
|
||||
FGRGBTextureLoader.cxx
|
||||
FGRGBTextureLoader.hxx
|
||||
FGSwitchLayer.cxx
|
||||
FGSwitchLayer.hxx
|
||||
FGTextLayer.cxx
|
||||
FGTextLayer.hxx
|
||||
FGTexturedLayer.cxx
|
||||
FGTexturedLayer.hxx
|
||||
panel_io.cxx
|
||||
panel_io.hxx
|
||||
GL_utils.cxx
|
||||
GL_utils.hxx
|
||||
${TARGET_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(fgpanel
|
||||
${PNG_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
-lfreetype
|
||||
)
|
||||
|
||||
if(${BCMHOST_INCLUDE_DIR} STREQUAL "BCMHOST_INCLUDE_DIR-NOTFOUND")
|
||||
find_package(GLUT REQUIRED)
|
||||
if(GLUT_FOUND)
|
||||
message(STATUS "found glut")
|
||||
|
||||
target_link_libraries(fgpanel
|
||||
${GLUT_LIBRARIES}
|
||||
-lGLEW ${OPENGL_LIBRARIES}
|
||||
)
|
||||
else(GLUT_FOUND)
|
||||
message(STATUS "glut NOT found, can't build fgpanel")
|
||||
endif(GLUT_FOUND)
|
||||
else()
|
||||
message(STATUS "found Raspberry Pi")
|
||||
|
||||
target_link_libraries(fgpanel
|
||||
-lGLESv2 -lEGL -lm -lbcm_host -L/opt/vc/lib
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${BCMHOST_INCLUDE_DIR}
|
||||
${BCMHOST_INCLUDE_DIR}/interface/vcos/pthreads
|
||||
${BCMHOST_INCLUDE_DIR}/interface/vmcs_host/linux
|
||||
)
|
||||
|
||||
add_definitions(-D_GLES2 -D_RPI)
|
||||
endif()
|
||||
|
||||
install(TARGETS fgpanel RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
|
127
utils/fgpanel/FGCroppedTexture.cxx
Normal file
127
utils/fgpanel/FGCroppedTexture.cxx
Normal file
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "FGCroppedTexture.hxx"
|
||||
|
||||
GLuint FGCroppedTexture::s_current_bound_texture = 0;
|
||||
map <string, GLuint> FGCroppedTexture::s_cache;
|
||||
map <string, FGTextureLoaderInterface*> FGCroppedTexture::s_TextureLoader;
|
||||
FGDummyTextureLoader FGCroppedTexture::s_DummyTextureLoader;
|
||||
|
||||
FGCroppedTexture::FGCroppedTexture (const string &path,
|
||||
const float minX, const float minY,
|
||||
const float maxX, const float maxY) :
|
||||
m_path (path),
|
||||
m_minX (minX), m_minY (minY),
|
||||
m_maxX (maxX), m_maxY (maxY),
|
||||
m_texture(0) {
|
||||
}
|
||||
|
||||
FGCroppedTexture::~FGCroppedTexture () {
|
||||
}
|
||||
|
||||
void
|
||||
FGCroppedTexture::setPath (const string &path) {
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
const string &
|
||||
FGCroppedTexture::getPath () const {
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void
|
||||
FGCroppedTexture::setCrop (const float minX, const float minY, const float maxX, const float maxY) {
|
||||
m_minX = minX; m_minY = minY; m_maxX = maxX; m_maxY = maxY;
|
||||
}
|
||||
|
||||
void
|
||||
FGCroppedTexture::registerTextureLoader (const string &extension,
|
||||
FGTextureLoaderInterface * const loader) {
|
||||
if (s_TextureLoader.count (extension) == 0) {
|
||||
s_TextureLoader[extension] = loader;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
FGCroppedTexture::getMinX () const {
|
||||
return m_minX;
|
||||
}
|
||||
|
||||
float
|
||||
FGCroppedTexture::getMinY () const {
|
||||
return m_minY;
|
||||
}
|
||||
|
||||
float
|
||||
FGCroppedTexture::getMaxX () const {
|
||||
return m_maxX;
|
||||
}
|
||||
|
||||
float
|
||||
FGCroppedTexture::getMaxY () const {
|
||||
return m_maxY;
|
||||
}
|
||||
|
||||
GLuint
|
||||
FGCroppedTexture::getTexture () const {
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
void
|
||||
FGCroppedTexture::bind (const GLint Textured_Layer_Sampler_Loc) {
|
||||
if (m_texture == 0) {
|
||||
SG_LOG (SG_COCKPIT,
|
||||
SG_DEBUG,
|
||||
"First bind of texture " << m_path);
|
||||
if (s_cache.count (m_path) > 0 ) {
|
||||
m_texture = s_cache[m_path];
|
||||
SG_LOG (SG_COCKPIT,
|
||||
SG_DEBUG,
|
||||
"Using texture " << m_path << " from cache (#" << m_texture << ")");
|
||||
} else {
|
||||
const SGPath path (ApplicationProperties::GetRootPath (m_path.c_str ()));
|
||||
const string extension (path.extension ());
|
||||
FGTextureLoaderInterface *loader (&s_DummyTextureLoader);
|
||||
if (s_TextureLoader.count (extension) == 0) {
|
||||
SG_LOG (SG_COCKPIT,
|
||||
SG_ALERT,
|
||||
"Can't handle textures of type " << extension);
|
||||
} else {
|
||||
loader = s_TextureLoader[extension];
|
||||
}
|
||||
|
||||
m_texture = loader->loadTexture (path.local8BitStr ());
|
||||
SG_LOG (SG_COCKPIT,
|
||||
SG_DEBUG,
|
||||
"Texture " << path << " loaded from file as #" << m_texture);
|
||||
s_cache[m_path] = m_texture;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_current_bound_texture != m_texture) {
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, m_texture);
|
||||
glUniform1i (Textured_Layer_Sampler_Loc, 0);
|
||||
s_current_bound_texture = m_texture;
|
||||
}
|
||||
}
|
69
utils/fgpanel/FGCroppedTexture.hxx
Normal file
69
utils/fgpanel/FGCroppedTexture.hxx
Normal file
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
#ifndef FGCROPPEDTEXTURE_HXX
|
||||
#define FGCROPPEDTEXTURE_HXX
|
||||
|
||||
#include <map>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include "FGDummyTextureLoader.hxx"
|
||||
|
||||
/**
|
||||
* Cropped texture (should migrate out into FGFS).
|
||||
*
|
||||
* This structure wraps an SSG texture with cropping information.
|
||||
*/
|
||||
class FGCroppedTexture : public SGReferenced {
|
||||
public:
|
||||
FGCroppedTexture (const string &path,
|
||||
const float minX = 0.0, const float minY = 0.0,
|
||||
const float maxX = 1.0, const float maxY = 1.0);
|
||||
|
||||
virtual ~FGCroppedTexture ();
|
||||
|
||||
virtual void setPath (const string &path);
|
||||
|
||||
virtual const string &getPath () const;
|
||||
|
||||
virtual void setCrop (const float minX, const float minY, const float maxX, const float maxY);
|
||||
|
||||
static void registerTextureLoader (const string &extension,
|
||||
FGTextureLoaderInterface * const loader);
|
||||
|
||||
virtual float getMinX () const;
|
||||
virtual float getMinY () const;
|
||||
virtual float getMaxX () const;
|
||||
virtual float getMaxY () const;
|
||||
GLuint getTexture () const;
|
||||
|
||||
virtual void bind (const GLint Textured_Layer_Sampler_Loc);
|
||||
|
||||
private:
|
||||
string m_path;
|
||||
float m_minX, m_minY, m_maxX, m_maxY;
|
||||
|
||||
GLuint m_texture;
|
||||
static GLuint s_current_bound_texture;
|
||||
static map <string, GLuint> s_cache;
|
||||
static map <string, FGTextureLoaderInterface*> s_TextureLoader;
|
||||
static FGDummyTextureLoader s_DummyTextureLoader;
|
||||
};
|
||||
|
||||
typedef SGSharedPtr <FGCroppedTexture> FGCroppedTexture_ptr;
|
||||
|
||||
#endif
|
41
utils/fgpanel/FGDummyTextureLoader.cxx
Normal file
41
utils/fgpanel/FGDummyTextureLoader.cxx
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "FGDummyTextureLoader.hxx"
|
||||
|
||||
GLuint
|
||||
FGDummyTextureLoader::loadTexture (const string& filename) {
|
||||
GLuint texture;
|
||||
glGenTextures (1, &texture);
|
||||
glBindTexture (GL_TEXTURE_2D, texture);
|
||||
|
||||
GLubyte image[ 2 * 2 * 3 ];
|
||||
|
||||
/* Red and white chequerboard */
|
||||
image [ 0] = 255; image [ 1] = 0; image [ 2] = 0;
|
||||
image [ 3] = 255; image [ 4] = 255; image [ 5] = 255;
|
||||
image [ 6] = 255; image [ 7] = 255; image [ 8] = 255;
|
||||
image [ 9] = 255; image [10] = 0; image [11] = 0;
|
||||
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
return texture;
|
||||
}
|
32
utils/fgpanel/FGDummyTextureLoader.hxx
Normal file
32
utils/fgpanel/FGDummyTextureLoader.hxx
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
#ifndef FGDUMMYTEXTURELOADER_HXX
|
||||
#define FGDUMMYTEXTURELOADER_HXX
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "FGTextureLoaderInterface.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class FGDummyTextureLoader : public FGTextureLoaderInterface {
|
||||
public:
|
||||
virtual GLuint loadTexture (const string& filename);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -17,213 +17,170 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <plib/fnt.h>
|
||||
#include <plib/pu.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "FGFontCache.hxx"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGFontCache class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//extern puFont FONT_HELVETICA_14;
|
||||
//extern puFont FONT_SANS_12B;
|
||||
const unsigned short FGFontCache::First_Printable_Char = 32;
|
||||
const unsigned short FGFontCache::Last_Printable_Char = 127;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct GuiFont
|
||||
{
|
||||
const char *name;
|
||||
puFont *font;
|
||||
struct Predicate
|
||||
: public std::unary_function<const GuiFont, bool>
|
||||
{
|
||||
Predicate(const char* name_) : name(name_) {}
|
||||
bool operator() (const GuiFont& f1) const
|
||||
{
|
||||
return ::strcmp(f1.name, name) == 0;
|
||||
}
|
||||
const char* name;
|
||||
};
|
||||
};
|
||||
|
||||
const GuiFont guifonts[] = {
|
||||
{ "default", &PUFONT_HELVETICA_12 },
|
||||
{ "FIXED_8x13", &PUFONT_8_BY_13 },
|
||||
{ "FIXED_9x15", &PUFONT_9_BY_15 },
|
||||
{ "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
|
||||
{ "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
|
||||
{ "HELVETICA_10", &PUFONT_HELVETICA_10 },
|
||||
{ "HELVETICA_12", &PUFONT_HELVETICA_12 },
|
||||
// { "HELVETICA_14", &FONT_HELVETICA_14 },
|
||||
{ "HELVETICA_18", &PUFONT_HELVETICA_18 },
|
||||
// { "SANS_12B", &FONT_SANS_12B },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])-1];
|
||||
FGFontCache::FGFontCache () :
|
||||
m_Face_Map (),
|
||||
m_Current_Face_Ptr (NULL),
|
||||
m_Pos_Map (),
|
||||
m_Current_Pos (0) {
|
||||
if (FT_Init_FreeType (&m_Ft)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Could not init freetype library");
|
||||
}
|
||||
for (unsigned int Index = 0; Index < Texture_Size * Texture_Size; ++Index) {
|
||||
m_Texture[Index] = char (0);
|
||||
}
|
||||
glGenTextures (1, &m_Glyph_Texture);
|
||||
}
|
||||
|
||||
FGFontCache::fnt::~fnt()
|
||||
{
|
||||
if (texfont) {
|
||||
delete pufont;
|
||||
delete texfont;
|
||||
FGFontCache::~FGFontCache () {
|
||||
for (Face_Map_Type::iterator It = m_Face_Map.begin (); It != m_Face_Map.end (); ++It) {
|
||||
delete (It->second);
|
||||
}
|
||||
m_Face_Map.clear ();
|
||||
glDeleteTextures (1, &m_Glyph_Texture);
|
||||
}
|
||||
|
||||
bool
|
||||
FGFontCache::Set_Font (const string& Font_Name,
|
||||
const float Size,
|
||||
GLuint &Glyph_Texture) {
|
||||
if (m_Face_Map.find (Font_Name) != m_Face_Map.end ()) {
|
||||
m_Current_Face_Ptr = m_Face_Map[Font_Name];
|
||||
} else {
|
||||
FT_Face * const Face_Ptr (new FT_Face);
|
||||
if (FT_New_Face (m_Ft, Font_Name.c_str (), 0, Face_Ptr)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Could not open font : " + Font_Name);
|
||||
return false;
|
||||
}
|
||||
m_Face_Map.insert (pair <string, FT_Face *> (Font_Name, Face_Ptr));
|
||||
m_Current_Face_Ptr = Face_Ptr;
|
||||
}
|
||||
if (m_Current_Face_Ptr != NULL) {
|
||||
FT_Set_Pixel_Sizes (*m_Current_Face_Ptr, 0, Size);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
const string Key_Str (Font_Name + "_" + Get_Size (Size));
|
||||
if (m_Pos_Map.find (Key_Str) != m_Pos_Map.end ()) {
|
||||
m_Current_Pos = m_Pos_Map[Key_Str];
|
||||
} else {
|
||||
m_Current_Pos = m_Pos_Map.size ();
|
||||
for (unsigned short ASCII_Code = First_Printable_Char;
|
||||
ASCII_Code < Last_Printable_Char;
|
||||
++ASCII_Code) {
|
||||
if (FT_Load_Char (*m_Current_Face_Ptr, char (ASCII_Code), FT_LOAD_RENDER)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Could not load character : " << char (ASCII_Code));
|
||||
} else {
|
||||
unsigned int Line;
|
||||
unsigned int Column;
|
||||
const FT_GlyphSlot Glyph ((*m_Current_Face_Ptr)->glyph);
|
||||
for (unsigned int Row = 0; Row < Glyph->bitmap.rows; ++Row) {
|
||||
for (unsigned int Width = 0; Width < Glyph->bitmap.width; ++Width) {
|
||||
Get_Pos (ASCII_Code, Row, Width, Line, Column);
|
||||
m_Texture[Line * Texture_Size + Column] =
|
||||
Glyph->bitmap.buffer[Row * Glyph->bitmap.width + Width];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glBindTexture (GL_TEXTURE_2D, m_Glyph_Texture);
|
||||
/* We require 1 byte alignment when uploading texture data */
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
/* Clamping to edges is important to prevent artifacts when scaling */
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
/* Linear filtering usually looks best for text */
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_ALPHA,
|
||||
Texture_Size,
|
||||
Texture_Size,
|
||||
0,
|
||||
GL_ALPHA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
m_Texture);
|
||||
m_Pos_Map.insert (pair <string, unsigned int> (Key_Str, m_Current_Pos));
|
||||
}
|
||||
Glyph_Texture = m_Glyph_Texture;
|
||||
return true;
|
||||
}
|
||||
|
||||
FGFontCache::FGFontCache() :
|
||||
_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
FGFontCache::~FGFontCache()
|
||||
{
|
||||
PuFontMap::iterator it, end = _puFonts.end();
|
||||
for (it = _puFonts.begin(); it != end; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
|
||||
const FntParams& f2) const
|
||||
{
|
||||
int comp = f1.name.compare(f2.name);
|
||||
if (comp < 0)
|
||||
return true;
|
||||
else if (comp > 0)
|
||||
return false;
|
||||
if (f1.size < f2.size)
|
||||
return true;
|
||||
else if (f1.size > f2.size)
|
||||
return false;
|
||||
return f1.slant < f2.slant;
|
||||
}
|
||||
|
||||
struct FGFontCache::fnt *
|
||||
FGFontCache::getfnt(const char *name, float size, float slant)
|
||||
{
|
||||
std::string fontName(name);
|
||||
FntParams fntParams(fontName, size, slant);
|
||||
PuFontMap::iterator i = _puFonts.find(fntParams);
|
||||
if (i != _puFonts.end())
|
||||
return i->second;
|
||||
// fntTexFont s are all preloaded into the _texFonts map
|
||||
TexFontMap::iterator texi = _texFonts.find(fontName);
|
||||
fntTexFont* texfont = 0;
|
||||
puFont* pufont = 0;
|
||||
if (texi != _texFonts.end()) {
|
||||
texfont = texi->second;
|
||||
bool
|
||||
FGFontCache::Get_Char (const char Char,
|
||||
int &X, int &Y,
|
||||
int &Left, int &Bottom,
|
||||
int &W, int &H,
|
||||
double &X1, double &Y1,
|
||||
double &X2, double &Y2) const {
|
||||
if (m_Current_Face_Ptr != NULL) {
|
||||
if (FT_Load_Char (*m_Current_Face_Ptr, Char, FT_LOAD_RENDER)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Could not load character : " + Char);
|
||||
return false;
|
||||
} else {
|
||||
const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
|
||||
GuiFont::Predicate(name));
|
||||
if (guifont != guifontsEnd) {
|
||||
pufont = guifont->font;
|
||||
}
|
||||
const FT_GlyphSlot Glyph ((*m_Current_Face_Ptr)->glyph);
|
||||
Left = Glyph->bitmap_left;
|
||||
W = Glyph->bitmap.width;
|
||||
H = Glyph->bitmap.rows;
|
||||
Bottom = Glyph->bitmap_top - H;
|
||||
X += (Glyph->advance.x >> 6);
|
||||
Y += (Glyph->advance.y >> 6);
|
||||
Get_Relative_Pos (int (Char), 0, 0, X1, Y1);
|
||||
Get_Relative_Pos (int (Char), Glyph->bitmap.rows, Glyph->bitmap.width, X2, Y2);
|
||||
return true;
|
||||
}
|
||||
fnt* f = new fnt;
|
||||
if (pufont) {
|
||||
f->pufont = pufont;
|
||||
} else if (texfont) {
|
||||
f->texfont = texfont;
|
||||
f->pufont = new puFont;
|
||||
f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
|
||||
} else {
|
||||
f->pufont = guifonts[0].font;
|
||||
}
|
||||
_puFonts[fntParams] = f;
|
||||
return f;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(const char *name, float size, float slant)
|
||||
{
|
||||
return getfnt(name, size, slant)->pufont;
|
||||
void
|
||||
FGFontCache::Get_Pos (const unsigned short ASCII_Code,
|
||||
const unsigned short Row,
|
||||
const unsigned short Width,
|
||||
unsigned int &Line,
|
||||
unsigned int &Column) const {
|
||||
const unsigned short Font_Size (32);
|
||||
Line = (((((ASCII_Code - First_Printable_Char) * Font_Size) / Texture_Size) + 3 * m_Current_Pos) * Font_Size) + Row;
|
||||
Column = (((ASCII_Code - First_Printable_Char) * Font_Size) % Texture_Size) + Width;
|
||||
}
|
||||
|
||||
fntTexFont *
|
||||
FGFontCache::getTexFont(const char *name, float size, float slant)
|
||||
{
|
||||
init();
|
||||
return getfnt(name, size, slant)->texfont;
|
||||
void
|
||||
FGFontCache::Get_Relative_Pos (const unsigned short ASCII_Code,
|
||||
const unsigned short Row,
|
||||
const unsigned short Width,
|
||||
double &X,
|
||||
double &Y) const {
|
||||
unsigned int Line;
|
||||
unsigned int Column;
|
||||
Get_Pos (ASCII_Code, Row, Width, Line, Column);
|
||||
X = double (Column) / double (Texture_Size);
|
||||
Y = double (Line) / double (Texture_Size);
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(SGPropertyNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return get("Helvetica.txf", 15.0, 0.0);
|
||||
|
||||
const char *name = node->getStringValue("name", "Helvetica.txf");
|
||||
float size = node->getFloatValue("size", 15.0);
|
||||
float slant = node->getFloatValue("slant", 0.0);
|
||||
|
||||
return get(name, size, slant);
|
||||
string
|
||||
FGFontCache::Get_Size (const float Size) {
|
||||
const int Half_Size (int (round (2.0 * Size)));
|
||||
const int Int_Part (Half_Size / 2);
|
||||
const int Dec_Part ((Half_Size % 2) ? 5 : 0);
|
||||
stringstream Result_SS;
|
||||
Result_SS << Int_Part << "." << Dec_Part;
|
||||
return Result_SS.str ();
|
||||
}
|
||||
|
||||
void FGFontCache::init()
|
||||
{
|
||||
if (!_initialized) {
|
||||
char *envp = ::getenv("FG_FONTS");
|
||||
if (envp != NULL) {
|
||||
_path = SGPath::fromEnv("FG_FONTS");
|
||||
} else {
|
||||
_path = ApplicationProperties::GetRootPath("Fonts");
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
SGPath
|
||||
FGFontCache::getfntpath(const char *name)
|
||||
{
|
||||
init();
|
||||
SGPath path(_path);
|
||||
if (name && std::string(name) != "") {
|
||||
path.append(name);
|
||||
if (path.exists())
|
||||
return path;
|
||||
}
|
||||
|
||||
path = SGPath(_path);
|
||||
path.append("Helvetica.txf");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
bool FGFontCache::initializeFonts()
|
||||
{
|
||||
static std::string fontext("txf");
|
||||
init();
|
||||
std::string pdata = _path.local8BitStr();
|
||||
ulDir* fontdir = ulOpenDir(pdata.c_str());
|
||||
if (!fontdir)
|
||||
return false;
|
||||
const ulDirEnt *dirEntry;
|
||||
while ((dirEntry = ulReadDir(fontdir)) != 0) {
|
||||
SGPath path(_path);
|
||||
path.append(dirEntry->d_name);
|
||||
if (path.extension() == fontext) {
|
||||
std::string fdata = path.local8BitStr();
|
||||
fntTexFont* f = new fntTexFont;
|
||||
if (f->load((char *)fdata.c_str()))
|
||||
_texFonts[std::string(dirEntry->d_name)] = f;
|
||||
else
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
ulCloseDir(fontdir);
|
||||
return true;
|
||||
}
|
||||
|
||||
// end of new_gui.cxx
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -15,78 +16,65 @@
|
|||
#ifndef __FGFONTCACHE_HXX
|
||||
#define __FGFONTCACHE_HXX
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
// forward declare only!
|
||||
class puFont;
|
||||
class fntTexFont;
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* A class to keep all fonts available for future use.
|
||||
* This also assures a font isn't resident more than once.
|
||||
*/
|
||||
class FGFontCache {
|
||||
private:
|
||||
// The parameters of a request to the cache.
|
||||
struct FntParams
|
||||
{
|
||||
const std::string name;
|
||||
const float size;
|
||||
const float slant;
|
||||
FntParams() : size(0.0f), slant(0.0f) {}
|
||||
FntParams(const FntParams& rhs)
|
||||
: name(rhs.name), size(rhs.size), slant(rhs.slant)
|
||||
{
|
||||
}
|
||||
FntParams(const std::string& name_, float size_, float slant_)
|
||||
: name(name_), size(size_), slant(slant_)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct FntParamsLess
|
||||
: public std::binary_function<const FntParams, const FntParams, bool>
|
||||
{
|
||||
bool operator() (const FntParams& f1, const FntParams& f2) const;
|
||||
};
|
||||
struct fnt {
|
||||
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
|
||||
~fnt();
|
||||
// Font used by plib GUI code
|
||||
puFont *pufont;
|
||||
// TXF font
|
||||
fntTexFont *texfont;
|
||||
};
|
||||
// Path to the font directory
|
||||
SGPath _path;
|
||||
|
||||
typedef std::map<const std::string, fntTexFont*> TexFontMap;
|
||||
typedef std::map<const FntParams, fnt*, FntParamsLess> PuFontMap;
|
||||
TexFontMap _texFonts;
|
||||
PuFontMap _puFonts;
|
||||
|
||||
bool _initialized;
|
||||
struct fnt *getfnt(const char *name, float size, float slant);
|
||||
void init();
|
||||
|
||||
public:
|
||||
FGFontCache();
|
||||
~FGFontCache();
|
||||
|
||||
puFont *get(const char *name, float size=15.0, float slant=0.0);
|
||||
puFont *get(SGPropertyNode *node);
|
||||
|
||||
fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
|
||||
|
||||
SGPath getfntpath(const char *name);
|
||||
/**
|
||||
* Preload all the fonts in the FlightGear font directory. It is
|
||||
* important to load the font textures early, with the proper
|
||||
* graphics context current, so that no plib (or our own) code
|
||||
* tries to load a font from disk when there's no current graphics
|
||||
* context.
|
||||
*/
|
||||
bool initializeFonts();
|
||||
FGFontCache ();
|
||||
~FGFontCache ();
|
||||
bool Set_Font (const string& Font_Name,
|
||||
const float Size,
|
||||
GLuint &Glyph_Texture);
|
||||
bool Get_Char (const char Char,
|
||||
int &X, int &Y,
|
||||
int &Left, int &Bottom,
|
||||
int &W, int &H,
|
||||
double &X1, double &Y1, // Top (Y1) left (X1)
|
||||
double &X2, double &Y2) const; // Bottom (Y2) right (X2)
|
||||
private:
|
||||
void Get_Pos (const unsigned short ASCII_Code,
|
||||
const unsigned short Row,
|
||||
const unsigned short Width,
|
||||
unsigned int &Line,
|
||||
unsigned int &Column) const;
|
||||
void Get_Relative_Pos (const unsigned short ASCII_Code,
|
||||
const unsigned short Row,
|
||||
const unsigned short Width,
|
||||
double &X,
|
||||
double &Y) const;
|
||||
static string Get_Size (const float Size);
|
||||
static const unsigned short First_Printable_Char;
|
||||
static const unsigned short Last_Printable_Char;
|
||||
static const unsigned int Texture_Size = 1024;
|
||||
FT_Library m_Ft;
|
||||
typedef map <string, FT_Face *> Face_Map_Type;
|
||||
Face_Map_Type m_Face_Map;
|
||||
FT_Face *m_Current_Face_Ptr;
|
||||
char m_Texture[Texture_Size * Texture_Size];
|
||||
typedef map <string, unsigned int> Pos_Map_Type;
|
||||
Pos_Map_Type m_Pos_Map;
|
||||
unsigned int m_Current_Pos;
|
||||
GLuint m_Glyph_Texture;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -20,93 +20,137 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <stdio.h>
|
||||
|
||||
FGGLApplication * FGGLApplication::application = NULL;
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#include "GLES_utils.hxx"
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/freeglut.h>
|
||||
#endif
|
||||
|
||||
FGGLApplication::FGGLApplication( const char * aName, int argc, char ** argv ) :
|
||||
gameMode(false),
|
||||
name( aName )
|
||||
{
|
||||
if( application != NULL ) {
|
||||
std::cerr << "Only one instance of FGGLApplication allowed!" << std::endl;
|
||||
throw std::exception();
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
FGGLApplication *FGGLApplication::application = NULL;
|
||||
|
||||
FGGLApplication::FGGLApplication (const char * a_name, int argc, char **argv) :
|
||||
gameMode (false),
|
||||
name (a_name) {
|
||||
if (application != NULL ) {
|
||||
cerr << "Only one instance of FGGLApplication allowed!" << endl;
|
||||
throw exception ();
|
||||
}
|
||||
application = this;
|
||||
application = this;
|
||||
|
||||
glutInit( &argc, argv );
|
||||
#ifdef _GLES2
|
||||
GLES_utils::instance ().init ("FG Panel");
|
||||
#else
|
||||
glutInit (&argc, argv);
|
||||
glutInitContextVersion (2, 1);
|
||||
glutInitContextFlags (GLUT_CORE_PROFILE);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGGLApplication::~FGGLApplication()
|
||||
{
|
||||
if (gameMode)
|
||||
glutLeaveGameMode();
|
||||
FGGLApplication::~FGGLApplication () {
|
||||
#ifndef _GLES2
|
||||
if (gameMode) {
|
||||
glutLeaveGameMode ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FGGLApplication::DisplayCallback()
|
||||
{
|
||||
if( application ) application->Display();
|
||||
void
|
||||
FGGLApplication::DisplayCallback () {
|
||||
if (application) {
|
||||
application->Display ();
|
||||
}
|
||||
}
|
||||
|
||||
void FGGLApplication::IdleCallback()
|
||||
{
|
||||
if( application ) application->Idle();
|
||||
void
|
||||
FGGLApplication::IdleCallback () {
|
||||
if (application) {
|
||||
application->Idle ();
|
||||
}
|
||||
}
|
||||
|
||||
void FGGLApplication::KeyCallback( unsigned char key, int x, int y )
|
||||
{
|
||||
if( application ) application->Key( key, x, y );
|
||||
void
|
||||
FGGLApplication::KeyCallback (const unsigned char key, const int x, const int y) {
|
||||
if (application) {
|
||||
application->Key (key, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void FGGLApplication::ReshapeCallback( int width, int height )
|
||||
{
|
||||
if( application ) application->Reshape( width, height );
|
||||
void
|
||||
FGGLApplication::ReshapeCallback (const int width, const int height) {
|
||||
if (application) {
|
||||
application->Reshape (width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void FGGLApplication::Run( int glutMode, bool gameMode, int width, int height, int bpp )
|
||||
{
|
||||
glutInitDisplayMode(glutMode);
|
||||
if( gameMode ) {
|
||||
width = glutGet(GLUT_SCREEN_WIDTH);
|
||||
height = glutGet(GLUT_SCREEN_HEIGHT);
|
||||
void
|
||||
FGGLApplication::Run (const int glutMode,
|
||||
const bool gameMode,
|
||||
int width,
|
||||
int height,
|
||||
const int bpp) {
|
||||
#ifndef _GLES2
|
||||
glutInitDisplayMode (glutMode);
|
||||
if (gameMode) {
|
||||
width = glutGet (GLUT_SCREEN_WIDTH);
|
||||
height = glutGet (GLUT_SCREEN_HEIGHT);
|
||||
char game_mode_str[20];
|
||||
snprintf(game_mode_str, 20, "%dx%d:%d", width, height, bpp );
|
||||
glutGameModeString( game_mode_str );
|
||||
glutEnterGameMode();
|
||||
snprintf (game_mode_str, 20, "%dx%d:%d", width, height, bpp);
|
||||
glutGameModeString (game_mode_str);
|
||||
glutEnterGameMode ();
|
||||
this->gameMode = gameMode;
|
||||
} else {
|
||||
if( width == -1 )
|
||||
width = glutGet(GLUT_SCREEN_WIDTH);
|
||||
|
||||
if( height == -1 )
|
||||
height = glutGet(GLUT_SCREEN_HEIGHT);
|
||||
|
||||
glutInitDisplayMode(glutMode);
|
||||
// glutInitWindowSize(width, height);
|
||||
windowId = glutCreateWindow(name);
|
||||
if (width == -1) {
|
||||
width = glutGet (GLUT_SCREEN_WIDTH);
|
||||
}
|
||||
if (height == -1) {
|
||||
height = glutGet (GLUT_SCREEN_HEIGHT);
|
||||
}
|
||||
glutInitDisplayMode (glutMode);
|
||||
glutInitWindowSize(width, height);
|
||||
windowId = glutCreateWindow (name);
|
||||
}
|
||||
Init();
|
||||
|
||||
glutKeyboardFunc(FGGLApplication::KeyCallback);
|
||||
glutIdleFunc(FGGLApplication::IdleCallback);
|
||||
glutDisplayFunc(FGGLApplication::DisplayCallback);
|
||||
glutReshapeFunc(FGGLApplication::ReshapeCallback);
|
||||
glutMainLoop();
|
||||
const GLenum GLEW_err (glewInit ());
|
||||
if (GLEW_OK != GLEW_err) {
|
||||
cerr << "Unable to initialize GLEW " << glewGetErrorString (GLEW_err) << endl;
|
||||
exit (1);
|
||||
}
|
||||
if (!GLEW_VERSION_2_1) { // check that the machine supports the 2.1 API.
|
||||
cerr << "GLEW version 2.1 not supported : " << glewGetString (GLEW_VERSION) << endl;
|
||||
exit (1);
|
||||
}
|
||||
cout << "OpenGL version = " << glGetString (GL_VERSION) << endl;
|
||||
#endif
|
||||
Init ();
|
||||
#ifdef _GLES2
|
||||
GLES_utils::instance ().register_keyboard_func (FGGLApplication::KeyCallback);
|
||||
GLES_utils::instance ().register_idle_func (FGGLApplication::IdleCallback);
|
||||
GLES_utils::instance ().register_display_func (FGGLApplication::DisplayCallback);
|
||||
GLES_utils::instance ().register_reshape_func (FGGLApplication::ReshapeCallback);
|
||||
GLES_utils::instance ().main_loop ();
|
||||
#else
|
||||
glutKeyboardFunc (FGGLApplication::KeyCallback);
|
||||
glutIdleFunc (FGGLApplication::IdleCallback);
|
||||
glutDisplayFunc (FGGLApplication::DisplayCallback);
|
||||
glutReshapeFunc (FGGLApplication::ReshapeCallback);
|
||||
glutMainLoop ();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -20,28 +20,32 @@
|
|||
|
||||
class FGGLApplication {
|
||||
public:
|
||||
FGGLApplication( const char * name, int argc, char ** argv );
|
||||
virtual ~FGGLApplication();
|
||||
void Run( int glutMode, bool gameMode, int widht=-1, int height=-1, int bpp = 32 );
|
||||
FGGLApplication (const char *a_name, int argc, char **argv);
|
||||
virtual ~FGGLApplication ();
|
||||
void Run (const int glutMode,
|
||||
const bool gameMode,
|
||||
int widht = -1,
|
||||
int height = -1,
|
||||
const int bpp = 32);
|
||||
protected:
|
||||
virtual void Key( unsigned char key, int x, int y ) {}
|
||||
virtual void Idle() {}
|
||||
virtual void Display() {}
|
||||
virtual void Reshape( int width, int height ) {}
|
||||
virtual void Key (const unsigned char key, const int x, const int y) {}
|
||||
virtual void Idle () {}
|
||||
virtual void Display () {}
|
||||
virtual void Reshape (const int width, const int height) {}
|
||||
|
||||
virtual void Init() {}
|
||||
virtual void Init () {}
|
||||
|
||||
int windowId;
|
||||
bool gameMode;
|
||||
|
||||
const char * name;
|
||||
const char *name;
|
||||
|
||||
static FGGLApplication * application;
|
||||
static FGGLApplication *application;
|
||||
private:
|
||||
static void KeyCallback( unsigned char key, int x, int y );
|
||||
static void IdleCallback();
|
||||
static void DisplayCallback();
|
||||
static void ReshapeCallback( int width, int height );
|
||||
static void KeyCallback (const unsigned char key, const int x, const int y);
|
||||
static void IdleCallback ();
|
||||
static void DisplayCallback ();
|
||||
static void ReshapeCallback (const int width, const int height);
|
||||
|
||||
};
|
||||
|
||||
|
|
43
utils/fgpanel/FGGroupLayer.cxx
Normal file
43
utils/fgpanel/FGGroupLayer.cxx
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "FGGroupLayer.hxx"
|
||||
|
||||
FGGroupLayer::FGGroupLayer () {
|
||||
}
|
||||
|
||||
FGGroupLayer::~FGGroupLayer () {
|
||||
for (unsigned int i = 0; i < m_layers.size (); ++i)
|
||||
delete m_layers[i];
|
||||
}
|
||||
|
||||
void
|
||||
FGGroupLayer::draw () {
|
||||
if (test ()) {
|
||||
transform ();
|
||||
for (unsigned int i = 0; i < m_layers.size (); ++i) {
|
||||
m_layers[i]->draw ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGGroupLayer::addLayer (FGInstrumentLayer * const layer) {
|
||||
m_layers.push_back (layer);
|
||||
}
|
43
utils/fgpanel/FGGroupLayer.hxx
Normal file
43
utils/fgpanel/FGGroupLayer.hxx
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGGROUPLAYER_HXX
|
||||
#define FGGROUPLAYER_HXX
|
||||
|
||||
#include "FGInstrumentLayer.hxx"
|
||||
|
||||
/**
|
||||
* An instrument layer containing a group of sublayers.
|
||||
*
|
||||
* This class is useful for gathering together a group of related
|
||||
* layers, either to hold in an external file or to work under
|
||||
* the same condition.
|
||||
*/
|
||||
class FGGroupLayer : public FGInstrumentLayer {
|
||||
public:
|
||||
FGGroupLayer ();
|
||||
virtual ~FGGroupLayer ();
|
||||
virtual void draw ();
|
||||
// transfer pointer ownership
|
||||
virtual void addLayer (FGInstrumentLayer * const layer);
|
||||
protected:
|
||||
vector <FGInstrumentLayer *> m_layers;
|
||||
};
|
||||
|
||||
#endif
|
100
utils/fgpanel/FGInstrumentLayer.cxx
Normal file
100
utils/fgpanel/FGInstrumentLayer.cxx
Normal file
|
@ -0,0 +1,100 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGInstrumentLayer.hxx"
|
||||
|
||||
FGInstrumentLayer::FGInstrumentLayer (const int w, const int h) :
|
||||
m_w (w), m_h (h) {
|
||||
}
|
||||
|
||||
FGInstrumentLayer::~FGInstrumentLayer () {
|
||||
for (transformation_list::iterator it = m_transformations.begin ();
|
||||
it != m_transformations.end ();
|
||||
++it) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::transform () const {
|
||||
for (transformation_list::const_iterator it = m_transformations.begin ();
|
||||
it != m_transformations.end ();
|
||||
++it) {
|
||||
FGPanelTransformation *t = *it;
|
||||
if (t->test ()) {
|
||||
float val (t->node == 0 ? 0.0 : t->node->getFloatValue ());
|
||||
if (t->has_mod) {
|
||||
val = fmod (val, t->mod);
|
||||
}
|
||||
if (val < t->min) {
|
||||
val = t->min;
|
||||
} else if (val > t->max) {
|
||||
val = t->max;
|
||||
}
|
||||
|
||||
if (t->table == 0) {
|
||||
val = val * t->factor + t->offset;
|
||||
} else {
|
||||
val = t->table->interpolate (val) * t->factor + t->offset;
|
||||
}
|
||||
|
||||
switch (t->type) {
|
||||
case FGPanelTransformation::XSHIFT:
|
||||
GL_utils::instance ().glTranslatef (val, 0.0, 0.0);
|
||||
break;
|
||||
case FGPanelTransformation::YSHIFT:
|
||||
GL_utils::instance ().glTranslatef (0.0, val, 0.0);
|
||||
break;
|
||||
case FGPanelTransformation::ROTATION:
|
||||
GL_utils::instance ().glRotatef (-val, 0.0, 0.0, 1.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
FGInstrumentLayer::getWidth () const {
|
||||
return m_w;
|
||||
}
|
||||
|
||||
int
|
||||
FGInstrumentLayer::getHeight () const {
|
||||
return m_h;
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::setWidth (const int w) {
|
||||
m_w = w;
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::setHeight (const int h) {
|
||||
m_h = h;
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::addTransformation (FGPanelTransformation * const transformation) {
|
||||
m_transformations.push_back (transformation);
|
||||
}
|
61
utils/fgpanel/FGInstrumentLayer.hxx
Normal file
61
utils/fgpanel/FGInstrumentLayer.hxx
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGINSTRUMENTLAYER_HXX
|
||||
#define FGINSTRUMENTLAYER_HXX
|
||||
|
||||
#include <vector>
|
||||
#include <simgear/props/condition.hxx>
|
||||
|
||||
#include "FGPanelTransformation.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* A single layer of a multi-layered instrument.
|
||||
*
|
||||
* Each layer can be subject to a series of transformations based
|
||||
* on current FGFS instrument readings: for example, a texture
|
||||
* representing a needle can rotate to show the airspeed.
|
||||
*/
|
||||
class FGInstrumentLayer : public SGConditional {
|
||||
public:
|
||||
FGInstrumentLayer (const int w = -1, const int h = -1);
|
||||
virtual ~FGInstrumentLayer ();
|
||||
|
||||
virtual void draw () = 0;
|
||||
virtual void transform () const;
|
||||
|
||||
virtual int getWidth () const;
|
||||
virtual int getHeight () const;
|
||||
virtual void setWidth (const int w);
|
||||
virtual void setHeight (const int h);
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
// DEPRECATED
|
||||
virtual void addTransformation (FGPanelTransformation * const transformation);
|
||||
|
||||
protected:
|
||||
int m_w, m_h;
|
||||
|
||||
typedef vector <FGPanelTransformation *> transformation_list;
|
||||
transformation_list m_transformations;
|
||||
};
|
||||
|
||||
#endif
|
70
utils/fgpanel/FGLayeredInstrument.cxx
Normal file
70
utils/fgpanel/FGLayeredInstrument.cxx
Normal file
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGLayeredInstrument.hxx"
|
||||
#include "FGTexturedLayer.hxx"
|
||||
|
||||
FGLayeredInstrument::FGLayeredInstrument (const int x, const int y, const int w, const int h) :
|
||||
FGPanelInstrument (x, y, w, h) {
|
||||
}
|
||||
|
||||
FGLayeredInstrument::~FGLayeredInstrument () {
|
||||
for (layer_list::iterator it = m_layers.begin();
|
||||
it != m_layers.end();
|
||||
++it) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGLayeredInstrument::draw () {
|
||||
if (test ()) {
|
||||
for (unsigned int i = 0; i < m_layers.size (); ++i) {
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
m_layers[i]->draw ();
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
FGLayeredInstrument::addLayer (FGInstrumentLayer * const layer) {
|
||||
const int n (m_layers.size ());
|
||||
if (layer->getWidth () == -1) {
|
||||
layer->setWidth (getWidth ());
|
||||
}
|
||||
if (layer->getHeight () == -1) {
|
||||
layer->setHeight (getHeight ());
|
||||
}
|
||||
m_layers.push_back (layer);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
FGLayeredInstrument::addLayer (const FGCroppedTexture_ptr texture, const int w, const int h) {
|
||||
return addLayer (new FGTexturedLayer (texture, w, h));
|
||||
}
|
||||
|
||||
void
|
||||
FGLayeredInstrument::addTransformation (FGPanelTransformation * const transformation) {
|
||||
const int layer (m_layers.size () - 1);
|
||||
m_layers[layer]->addTransformation (transformation);
|
||||
}
|
54
utils/fgpanel/FGLayeredInstrument.hxx
Normal file
54
utils/fgpanel/FGLayeredInstrument.hxx
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGLAYEREDINSTRUMENT_HXX
|
||||
#define FGLAYEREDINSTRUMENT_HXX
|
||||
|
||||
#include "FGCroppedTexture.hxx"
|
||||
#include "FGInstrumentLayer.hxx"
|
||||
#include "FGPanelInstrument.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* An instrument constructed of multiple layers.
|
||||
*
|
||||
* Each individual layer can be rotated or shifted to correspond
|
||||
* to internal FGFS instrument readings.
|
||||
*/
|
||||
class FGLayeredInstrument : public FGPanelInstrument {
|
||||
public:
|
||||
FGLayeredInstrument (const int x, const int y, const int w, const int h);
|
||||
virtual ~FGLayeredInstrument ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
virtual int addLayer (FGInstrumentLayer * const layer);
|
||||
virtual int addLayer (const FGCroppedTexture_ptr texture, const int w = -1, const int h = -1);
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
virtual void addTransformation (FGPanelTransformation * const transformation);
|
||||
|
||||
private:
|
||||
typedef vector <FGInstrumentLayer *> layer_list;
|
||||
layer_list m_layers;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -20,134 +20,137 @@
|
|||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "FGPNGTextureLoader.hxx"
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "FGPNGTextureLoader.hxx"
|
||||
|
||||
using namespace std;
|
||||
GLuint FGPNGTextureLoader::loadTexture( const string & filename )
|
||||
{
|
||||
|
||||
GLuint
|
||||
FGPNGTextureLoader::loadTexture (const string &filename) {
|
||||
//header for testing if it is a png
|
||||
png_byte header[8];
|
||||
|
||||
|
||||
//open file as binary
|
||||
FILE *fp = fopen(filename.c_str(), "rb");
|
||||
FILE * const fp (fopen (filename.c_str (), "rb"));
|
||||
if (!fp) {
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
|
||||
//read the header
|
||||
fread(header, 1, 8, fp);
|
||||
|
||||
fread (header, 1, 8, fp);
|
||||
|
||||
//test if png
|
||||
int is_png = !png_sig_cmp(header, 0, 8);
|
||||
const int is_png (!png_sig_cmp (header, 0, 8));
|
||||
if (!is_png) {
|
||||
fclose(fp);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
|
||||
//create png struct
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
||||
NULL, NULL);
|
||||
png_structp png_ptr (png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL));
|
||||
if (!png_ptr) {
|
||||
fclose(fp);
|
||||
return (NOTEXTURE);
|
||||
}
|
||||
|
||||
//create png info struct
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
return (NOTEXTURE);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
//create png info struct
|
||||
png_infop end_info = png_create_info_struct(png_ptr);
|
||||
png_infop info_ptr (png_create_info_struct (png_ptr));
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct (&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
//create png info struct
|
||||
png_infop end_info (png_create_info_struct (png_ptr));
|
||||
if (!end_info) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
fclose(fp);
|
||||
return (NOTEXTURE);
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
//png error stuff, not sure libpng man suggests this.
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(fp);
|
||||
return (NOTEXTURE);
|
||||
if (setjmp (png_jmpbuf (png_ptr))) {
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
//init png reading
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
//let libpng know you already read the first 8 bytes
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
// init png reading
|
||||
png_init_io (png_ptr, fp);
|
||||
|
||||
// let libpng know you already read the first 8 bytes
|
||||
png_set_sig_bytes (png_ptr, 8);
|
||||
|
||||
// read all the info up to the image data
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_read_info (png_ptr, info_ptr);
|
||||
|
||||
//variables to pass to get info
|
||||
// variables to pass to get info
|
||||
int bit_depth, color_type;
|
||||
png_uint_32 twidth, theight;
|
||||
|
||||
// get info about png
|
||||
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
|
||||
NULL, NULL, NULL);
|
||||
png_get_IHDR (png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
|
||||
// Update the png info struct.
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
png_read_update_info (png_ptr, info_ptr);
|
||||
|
||||
// Row size in bytes.
|
||||
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
const int rowbytes (png_get_rowbytes (png_ptr, info_ptr));
|
||||
|
||||
// Allocate the image_data as a big block, to be given to opengl
|
||||
png_byte *image_data = new png_byte[rowbytes * theight];
|
||||
png_byte *image_data (new png_byte[rowbytes * theight]);
|
||||
if (!image_data) {
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
fclose(fp);
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
|
||||
//row_pointers is for pointing to image_data for reading the png with libpng
|
||||
png_bytep *row_pointers = new png_bytep[theight];
|
||||
// row_pointers is for pointing to image_data for reading the png with libpng
|
||||
png_bytep *row_pointers (new png_bytep[theight]);
|
||||
if (!row_pointers) {
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
delete[] image_data;
|
||||
fclose(fp);
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
|
||||
delete []image_data;
|
||||
fclose (fp);
|
||||
return NOTEXTURE;
|
||||
}
|
||||
// set the individual row_pointers to point at the correct offsets of image_data
|
||||
for (png_uint_32 i = 0; i < theight; ++i)
|
||||
for (png_uint_32 i = 0; i < theight; ++i) {
|
||||
row_pointers[theight - 1 - i] = image_data + i * rowbytes;
|
||||
|
||||
}
|
||||
//read the png into image_data through row_pointers
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
png_read_image (png_ptr, row_pointers);
|
||||
|
||||
//Now generate the OpenGL texture object
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, twidth, theight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
// glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, twidth, theight, 0,
|
||||
// GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
|
||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glGenTextures (1, &texture);
|
||||
glBindTexture (GL_TEXTURE_2D, texture);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
//clean up memory and close stuff
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
delete[] image_data;
|
||||
delete[] row_pointers;
|
||||
fclose(fp);
|
||||
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
|
||||
delete []image_data;
|
||||
delete []row_pointers;
|
||||
fclose (fp);
|
||||
return texture;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -19,8 +20,9 @@
|
|||
|
||||
class FGPNGTextureLoader : public FGTextureLoaderInterface {
|
||||
public:
|
||||
virtual GLuint loadTexture( const std::string & filename );
|
||||
virtual GLuint loadTexture (const string &filename);
|
||||
|
||||
const static GLuint NOTEXTURE = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
434
utils/fgpanel/FGPanel.cxx
Normal file
434
utils/fgpanel/FGPanel.cxx
Normal file
|
@ -0,0 +1,434 @@
|
|||
// FGPanel.cxx - default, 2D single-engine prop instrument panel
|
||||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id: FGPanel.cxx,v 1.1 2016/07/20 22:01:30 allaert Exp $
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // sprintf
|
||||
#include <string.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGPanel.hxx"
|
||||
#include "FGTextLayer.hxx"
|
||||
#include "FGTexturedLayer.hxx"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Local functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
GLuint FGPanel::Textured_Layer_Program_Object (0);
|
||||
GLint FGPanel::Textured_Layer_Position_Loc (0);
|
||||
GLint FGPanel::Textured_Layer_Tex_Coord_Loc (0);
|
||||
GLint FGPanel::Textured_Layer_MVP_Loc (0);
|
||||
GLint FGPanel::Textured_Layer_Sampler_Loc (0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGPanel.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
FGPanel::FGPanel (const SGPropertyNode_ptr root) :
|
||||
m_flipx (root->getNode ("/sim/panel/flip-x", true)),
|
||||
m_bg_width (1.0), m_bg_height (1.0) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
FGPanel::~FGPanel () {
|
||||
for (instrument_list_type::iterator it = m_instruments.begin ();
|
||||
it != m_instruments.end ();
|
||||
++it) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the panel.
|
||||
*/
|
||||
void
|
||||
FGPanel::init () {
|
||||
// Textured Layer Shaders
|
||||
const char V_Textured_Layer_Shader_Str[] =
|
||||
#ifdef _GLES2
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_tex_coord; \n"
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
#else
|
||||
"#version 330 \n"
|
||||
"in vec4 a_position; \n"
|
||||
"in vec2 a_tex_coord; \n"
|
||||
"out vec2 v_tex_coord; \n"
|
||||
#endif
|
||||
"uniform mat4 u_mvp_matrix; \n"
|
||||
"void main () { \n"
|
||||
" gl_Position = u_mvp_matrix * a_position; \n"
|
||||
" v_tex_coord = a_tex_coord; \n"
|
||||
"} \n";
|
||||
|
||||
const char F_Textured_Layer_Shader_Str[] =
|
||||
#ifdef _GLES2
|
||||
"precision mediump float; \n"
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
#else
|
||||
"#version 330 \n"
|
||||
"in vec2 v_tex_coord; \n"
|
||||
"out vec4 gl_FragColor; \n"
|
||||
#endif
|
||||
"uniform sampler2D u_texture; \n"
|
||||
"void main () { \n"
|
||||
" vec4 base_color = texture2D (u_texture, v_tex_coord); \n"
|
||||
" if (base_color.a <= 0.1) { \n"
|
||||
" discard; \n"
|
||||
" } \n"
|
||||
" gl_FragColor = base_color; \n"
|
||||
"} \n";
|
||||
|
||||
Textured_Layer_Program_Object = GL_utils::instance ().load_program (V_Textured_Layer_Shader_Str,
|
||||
F_Textured_Layer_Shader_Str);
|
||||
if (Textured_Layer_Program_Object == 0) {
|
||||
terminate ();
|
||||
}
|
||||
|
||||
// Get the attribute locations
|
||||
Textured_Layer_Position_Loc = glGetAttribLocation (Textured_Layer_Program_Object, "a_position");
|
||||
Textured_Layer_Tex_Coord_Loc = glGetAttribLocation (Textured_Layer_Program_Object, "a_tex_coord");
|
||||
|
||||
// Get the uniform locations
|
||||
Textured_Layer_MVP_Loc = glGetUniformLocation (Textured_Layer_Program_Object, "u_mvp_matrix");
|
||||
|
||||
// Get the sampler location
|
||||
Textured_Layer_Sampler_Loc = glGetUniformLocation (Textured_Layer_Program_Object, "u_texture");
|
||||
|
||||
FGTexturedLayer::Init (Textured_Layer_Program_Object,
|
||||
Textured_Layer_Position_Loc,
|
||||
Textured_Layer_Tex_Coord_Loc,
|
||||
Textured_Layer_MVP_Loc,
|
||||
Textured_Layer_Sampler_Loc);
|
||||
|
||||
// Text Layer Shaders
|
||||
if (!FGTextLayer::Init ()) {
|
||||
terminate ();
|
||||
}
|
||||
|
||||
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind panel properties.
|
||||
*/
|
||||
void
|
||||
FGPanel::bind () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind panel properties.
|
||||
*/
|
||||
void
|
||||
FGPanel::unbind () {
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::update (const double dt) {
|
||||
getInitDisplayList ();
|
||||
// Draw the instruments.
|
||||
// Syd Adams: added instrument clipping
|
||||
for (instrument_list_type::const_iterator current = m_instruments.begin ();
|
||||
current != m_instruments.end ();
|
||||
++current) {
|
||||
FGPanelInstrument *instr = *current;
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glTranslatef (instr->getXPos (), instr->getYPos (), 0);
|
||||
|
||||
instr->draw();
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
}
|
||||
#ifndef _GLES2
|
||||
// restore some original state
|
||||
//glPopAttrib ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an instrument to the panel.
|
||||
*/
|
||||
void
|
||||
FGPanel::addInstrument (FGPanelInstrument * const instrument) {
|
||||
m_instruments.push_back (instrument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the panel's background texture.
|
||||
*/
|
||||
void
|
||||
FGPanel::setBackground (const FGCroppedTexture_ptr texture) {
|
||||
m_bg = texture;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::setBackgroundWidth (const double d) {
|
||||
m_bg_width = d;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::setBackgroundHeight (const double d) {
|
||||
m_bg_height = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the panel's multiple background textures.
|
||||
*/
|
||||
void
|
||||
FGPanel::setMultiBackground (const FGCroppedTexture_ptr texture, const int idx) {
|
||||
m_bg = 0;
|
||||
m_mbg[idx] = texture;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::setWidth (const int width) {
|
||||
m_width = width;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanel::getWidth () const {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::setHeight (const int height) {
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanel::getHeight () const {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::getInitDisplayList () {
|
||||
glUseProgram (Textured_Layer_Program_Object);
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glLoadIdentity ();
|
||||
if (m_flipx->getBoolValue ()) {
|
||||
GL_utils::instance ().gluOrtho2D (m_width, 0, m_height, 0);
|
||||
} else {
|
||||
GL_utils::instance ().gluOrtho2D (0, m_width, 0, m_height);
|
||||
}
|
||||
GL_utils::instance ().glTranslatef (-1.0f, -1.0f, 0.0f);
|
||||
GL_utils::instance ().glScalef (2.0f / GLfloat (m_width), 2.0f / GLfloat (m_height), 1.0f);
|
||||
|
||||
#ifndef _GLES2
|
||||
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
#endif
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
GL_utils::instance ().glLoadIdentity ();
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUseProgram (Textured_Layer_Program_Object);
|
||||
#ifndef _GLES2
|
||||
// save some state
|
||||
//glPushAttrib (GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT |
|
||||
// GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE |
|
||||
// GL_DEPTH_BUFFER_BIT );
|
||||
#endif
|
||||
// Draw the background
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
#ifndef _GLES2
|
||||
glDisable (GL_LIGHTING);
|
||||
#endif
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
#ifndef _GLES2
|
||||
glEnable (GL_COLOR_MATERIAL);
|
||||
#endif
|
||||
glEnable (GL_CULL_FACE);
|
||||
glCullFace (GL_BACK);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
|
||||
if (m_bg != NULL) {
|
||||
m_bg->bind (Textured_Layer_Sampler_Loc);
|
||||
const GLfloat v_Vertices[] = {
|
||||
0.0f, 0.0f, 0.0f, // Position 0 (bottom left corner)
|
||||
0.0f, 0.0f, // TexCoord 0 (bottom left corner)
|
||||
float (m_width), 0.0f, 0.0f, // Position 1 (bottom right corner)
|
||||
float (m_bg_width), 0.0f, // TexCoord 1 (bottom right corner)
|
||||
float (m_width), float (m_height), 0.0f, // Position 2 (top right corner)
|
||||
float (m_bg_width), float (m_bg_height), // TexCoord 2 (top right corner)
|
||||
0.0f, float (m_height), 0.0f, // Position 3 (top left corner)
|
||||
0.0f, float (m_bg_height) }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Textured_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices);
|
||||
glVertexAttribPointer (Textured_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices[3]);
|
||||
|
||||
glEnableVertexAttribArray (Textured_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Textured_Layer_Tex_Coord_Loc);
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Textured_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
|
||||
const GLushort indices[] = {0, 1, 2, 0, 2, 3};
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
} else if (m_mbg[0] != NULL) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// top row of textures...(1,3,5,7)
|
||||
m_mbg[i*2]->bind (Textured_Layer_Sampler_Loc);
|
||||
const GLfloat v_Vertices_Top[] = {
|
||||
float (i * m_width / 4), float (m_height / 2), 0.0f, // Position 0 (bottom left corner)
|
||||
0.0f, 0.0f, // TexCoord 0 (bottom left corner)
|
||||
float ((i + 1) * m_width / 4), float (m_height / 2), 0.0f, // Position 1 (bottom right corner)
|
||||
1.0f, 0.0f, // TexCoord 1 (bottom right corner)
|
||||
float ((i + 1) * m_width / 4), float (m_height), 0.0f, // Position 2 (top right corner)
|
||||
1.0f, 1.0f, // TexCoord 2 (top right corner)
|
||||
float (i * m_width / 4), float (m_height), 0.0f, // Position 3 (top left corner)
|
||||
0.0f, 1.0f }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Textured_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices_Top);
|
||||
glVertexAttribPointer (Textured_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices_Top[3]);
|
||||
|
||||
glEnableVertexAttribArray (Textured_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Textured_Layer_Tex_Coord_Loc);
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Textured_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
|
||||
const GLushort indices[] = {0, 1, 2, 0, 2, 3};
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
|
||||
// bottom row of textures...(2,4,6,8)
|
||||
m_mbg[i*2+1]->bind (Textured_Layer_Sampler_Loc);
|
||||
const GLfloat v_Vertices_Bot[] = {
|
||||
float (i * m_width / 4), 0.0f, 0.0f, // Position 0 (bottom left corner)
|
||||
0.0f, 0.0f, // TexCoord 0 (bottom left corner)
|
||||
float ((i + 1) * m_width / 4), 0.0f, 0.0f, // Position 1 (bottom right corner)
|
||||
1.0f, 0.0f, // TexCoord 1 (bottom right corner)
|
||||
float ((i + 1) * m_width / 4), float (m_height / 2), 0.0f, // Position 2 (top right corner)
|
||||
1.0f, 1.0f, // TexCoord 2 (top right corner)
|
||||
float (i * m_width / 4), float (m_height / 2), 0.0f, // Position 3 (top left corner)
|
||||
0.0f, 1.0f }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Textured_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices_Bot);
|
||||
glVertexAttribPointer (Textured_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices_Bot[3]);
|
||||
|
||||
glEnableVertexAttribArray (Textured_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Textured_Layer_Tex_Coord_Loc);
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Textured_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
}
|
||||
} else {
|
||||
#ifndef _GLES2
|
||||
glUseProgram (0);
|
||||
float c[4];
|
||||
glGetFloatv (GL_CURRENT_COLOR, c);
|
||||
glColor4f (1.0, 0.0, 0.0, 1.0);
|
||||
glBegin (GL_QUADS);
|
||||
glVertex2f (0, 0);
|
||||
glVertex2f (m_width, 0);
|
||||
glVertex2f (m_width, m_height);
|
||||
glVertex2f (0, m_height);
|
||||
glEnd ();
|
||||
glColor4fv (c);
|
||||
glUseProgram (Textured_Layer_Program_Object);
|
||||
#endif
|
||||
}
|
||||
}
|
109
utils/fgpanel/FGPanel.hxx
Normal file
109
utils/fgpanel/FGPanel.hxx
Normal file
|
@ -0,0 +1,109 @@
|
|||
// FGPanel.hxx - generic support classes for a 2D panel.
|
||||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id: FGPanel.hxx,v 1.1 2016/07/20 22:01:30 allaert Exp $
|
||||
|
||||
#ifndef FGPANEL_HXX
|
||||
#define FGPANEL_HXX
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/props/propsfwd.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include "FGCroppedTexture.hxx"
|
||||
#include "FGPanelInstrument.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Top-level panel.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Instrument panel class.
|
||||
*
|
||||
* The panel is a container that has a background texture and holds
|
||||
* zero or more instruments. The panel will order the instruments to
|
||||
* redraw themselves when necessary, and will pass mouse clicks on to
|
||||
* the appropriate instruments for processing.
|
||||
*/
|
||||
class FGPanel : public SGSubsystem {
|
||||
public:
|
||||
FGPanel (const SGPropertyNode_ptr root);
|
||||
virtual ~FGPanel ();
|
||||
|
||||
// Update the panel (every frame).
|
||||
virtual void init ();
|
||||
virtual void bind ();
|
||||
virtual void unbind ();
|
||||
// virtual void draw ();
|
||||
virtual void update (const double dt);
|
||||
|
||||
// transfer pointer ownership!!!
|
||||
virtual void addInstrument (FGPanelInstrument * const instrument);
|
||||
|
||||
// Background texture.
|
||||
virtual void setBackground (const FGCroppedTexture_ptr texture);
|
||||
void setBackgroundWidth (const double d);
|
||||
void setBackgroundHeight (const double d);
|
||||
|
||||
// Background multiple textures.
|
||||
virtual void setMultiBackground (const FGCroppedTexture_ptr texture , const int idx);
|
||||
|
||||
// Full width of panel.
|
||||
virtual void setWidth (const int width);
|
||||
virtual int getWidth () const;
|
||||
|
||||
// Full height of panel.
|
||||
virtual void setHeight (const int height);
|
||||
virtual int getHeight () const;
|
||||
|
||||
private:
|
||||
|
||||
typedef vector <FGPanelInstrument *> instrument_list_type;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
SGPropertyNode_ptr m_flipx;
|
||||
|
||||
FGCroppedTexture_ptr m_bg;
|
||||
double m_bg_width;
|
||||
double m_bg_height;
|
||||
FGCroppedTexture_ptr m_mbg[8];
|
||||
// List of instruments in panel.
|
||||
instrument_list_type m_instruments;
|
||||
|
||||
void getInitDisplayList ();
|
||||
|
||||
static GLuint Textured_Layer_Program_Object;
|
||||
static GLint Textured_Layer_Position_Loc;
|
||||
static GLint Textured_Layer_Tex_Coord_Loc;
|
||||
static GLint Textured_Layer_MVP_Loc;
|
||||
static GLint Textured_Layer_Sampler_Loc;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -29,245 +29,238 @@
|
|||
# include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#include "FGPanelApplication.hxx"
|
||||
#include <iostream>
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#include "GLES_utils.hxx"
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#include "FGPanelApplication.hxx"
|
||||
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/ResourceManager.hxx>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "panel_io.hxx"
|
||||
#include "ApplicationProperties.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
inline static string ParseArgs( int argc, char ** argv, const string & token )
|
||||
{
|
||||
for( int i = 0; i < argc; i++ ) {
|
||||
string arg = argv[i];
|
||||
if( arg.find( token ) == 0 )
|
||||
return arg.substr( token.length() );
|
||||
inline static string
|
||||
ParseArgs (int argc, char **argv, const string &token) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
const string arg (argv[i]);
|
||||
if (arg.find (token) == 0) {
|
||||
return arg.substr (token.length ());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
inline static string ParseArgs( int argc, char ** argv, const char * token )
|
||||
{
|
||||
string s = token;
|
||||
return ParseArgs( argc, argv, s );
|
||||
}
|
||||
|
||||
|
||||
// define default location of fgdata (use the same as for fgfs)
|
||||
inline static SGPath
|
||||
platformDefaultRoot () {
|
||||
#if defined(__CYGWIN__)
|
||||
inline static SGPath platformDefaultRoot()
|
||||
{
|
||||
return SGPath("../data");
|
||||
}
|
||||
|
||||
return SGPath ("../data");
|
||||
#elif defined(_WIN32)
|
||||
inline static SGPath platformDefaultRoot()
|
||||
{
|
||||
return SGPath("..\\data");
|
||||
}
|
||||
return SGPath ("..\\data");
|
||||
#elif defined(__APPLE__)
|
||||
inline static SGPath platformDefaultRoot()
|
||||
{
|
||||
/*
|
||||
The following code looks for the base package inside the application
|
||||
bundle, in the standard Contents/Resources location.
|
||||
*/
|
||||
CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
||||
CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL (CFBundleGetMainBundle ());
|
||||
|
||||
// look for a 'data' subdir
|
||||
CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, resourcesUrl, CFSTR("data"), true);
|
||||
CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent (NULL, resourcesUrl, CFSTR ("data"), true);
|
||||
|
||||
// now convert down to a path, and the a c-string
|
||||
CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
|
||||
string root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
|
||||
CFStringRef path = CFURLCopyFileSystemPath (dataDir, kCFURLPOSIXPathStyle);
|
||||
string root = CFStringGetCStringPtr (path, CFStringGetSystemEncoding ());
|
||||
|
||||
CFRelease(resourcesUrl);
|
||||
CFRelease(dataDir);
|
||||
CFRelease(path);
|
||||
CFRelease (resourcesUrl);
|
||||
CFRelease (dataDir);
|
||||
CFRelease (path);
|
||||
|
||||
return SGPath(root);
|
||||
}
|
||||
return SGPath (root);
|
||||
#else
|
||||
inline static SGPath platformDefaultRoot()
|
||||
{
|
||||
return SGPath(PKGLIBDIR);
|
||||
}
|
||||
return SGPath (PKGLIBDIR);
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "FGPNGTextureLoader.hxx"
|
||||
#include "FGRGBTextureLoader.hxx"
|
||||
|
||||
static FGPNGTextureLoader pngTextureLoader;
|
||||
static FGRGBTextureLoader rgbTextureLoader;
|
||||
|
||||
FGPanelApplication::FGPanelApplication( int argc, char ** argv ) :
|
||||
FGGLApplication( "FlightGear Panel", argc, argv )
|
||||
{
|
||||
sglog().setLogLevels( SG_ALL, SG_WARN );
|
||||
FGCroppedTexture::registerTextureLoader( "png", &pngTextureLoader );
|
||||
FGCroppedTexture::registerTextureLoader( "rgb", &rgbTextureLoader );
|
||||
FGPanelApplication::FGPanelApplication (int argc, char **argv) :
|
||||
FGGLApplication ("FlightGear Panel", argc, argv) {
|
||||
sglog().setLogLevels (SG_ALL, SG_WARN);
|
||||
FGCroppedTexture::registerTextureLoader ("png", &pngTextureLoader);
|
||||
FGCroppedTexture::registerTextureLoader ("rgb", &rgbTextureLoader);
|
||||
|
||||
ApplicationProperties::root = platformDefaultRoot().local8BitStr();
|
||||
ApplicationProperties::root = platformDefaultRoot ().local8BitStr ();
|
||||
|
||||
string panelFilename;
|
||||
string fgRoot;
|
||||
const string panelFilename (ParseArgs (argc, argv, "--panel="));
|
||||
const string fgRoot (ParseArgs (argc, argv, "--fg-root="));
|
||||
|
||||
for( int i = 1; i < argc; i++ ) {
|
||||
panelFilename = ParseArgs( argc, argv, "--panel=" );
|
||||
fgRoot = ParseArgs( argc, argv, "--fg-root=" );
|
||||
}
|
||||
|
||||
if( fgRoot.length() > 0 )
|
||||
if (fgRoot.length () > 0) {
|
||||
ApplicationProperties::root = fgRoot;
|
||||
}
|
||||
simgear::ResourceManager::instance ()->addBasePath (ApplicationProperties::root);
|
||||
|
||||
simgear::ResourceManager::instance()->addBasePath(ApplicationProperties::root);
|
||||
|
||||
if( panelFilename.length() == 0 ) {
|
||||
cerr << "Need a panel filename. Use --panel=path_to_filename" << endl;
|
||||
throw exception();
|
||||
if (panelFilename.length () == 0 ) {
|
||||
cerr << "Need a panel filename. Use --panel=path_to_filename" << endl;
|
||||
throw exception ();
|
||||
}
|
||||
|
||||
// see if we got a valid fgdata path
|
||||
SGPath BaseCheck(ApplicationProperties::root);
|
||||
BaseCheck.append("version");
|
||||
if (!BaseCheck.exists())
|
||||
{
|
||||
cerr << "Missing base package. Use --fg-root=path_to_fgdata" << endl;
|
||||
throw exception();
|
||||
SGPath BaseCheck (ApplicationProperties::root);
|
||||
BaseCheck.append ("version");
|
||||
if (!BaseCheck.exists ()) {
|
||||
cerr << "Missing base package. Use --fg-root=path_to_fgdata" << endl;
|
||||
throw exception ();
|
||||
}
|
||||
|
||||
try {
|
||||
SGPath tpath = ApplicationProperties::GetRootPath( panelFilename.c_str() );
|
||||
readProperties( tpath, ApplicationProperties::Properties );
|
||||
const SGPath tpath (ApplicationProperties::GetRootPath (panelFilename.c_str ()));
|
||||
readProperties (tpath, ApplicationProperties::Properties);
|
||||
}
|
||||
catch( sg_io_exception & e ) {
|
||||
cerr << e.getFormattedMessage() << endl;
|
||||
catch (sg_io_exception & e) {
|
||||
cerr << e.getFormattedMessage () << endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
for( int i = 1; i < argc; i++ ) {
|
||||
string arg = argv[i];
|
||||
if( arg.find( "--prop:" ) == 0 ) {
|
||||
string s2 = arg.substr( 7 );
|
||||
string::size_type p = s2.find( "=" );
|
||||
if( p != string::npos ) {
|
||||
string propertyName = s2.substr( 0, p );
|
||||
string propertyValue = s2.substr( p+1 );
|
||||
ApplicationProperties::Properties->getNode( propertyName.c_str(), true )->setValue( propertyValue.c_str() );
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const string arg (argv[i]);
|
||||
if (arg.find ("--prop:") == 0 ) {
|
||||
const string s2 (arg.substr (7));
|
||||
string::size_type p (s2.find ("="));
|
||||
if (p != string::npos) {
|
||||
const string propertyName (s2.substr (0, p));
|
||||
const string propertyValue (s2.substr (p + 1));
|
||||
ApplicationProperties::Properties->getNode (propertyName.c_str (), true )->setValue (propertyValue.c_str ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SGPropertyNode_ptr n;
|
||||
if( (n = ApplicationProperties::Properties->getNode( "panel" )) != NULL )
|
||||
panel = FGReadablePanel::read( n );
|
||||
|
||||
protocol = new FGPanelProtocol( ApplicationProperties::Properties->getNode( "communication", true ) );
|
||||
protocol->init();
|
||||
const SGPropertyNode_ptr n (ApplicationProperties::Properties->getNode ("panel"));
|
||||
if (n != NULL) {
|
||||
panel = FGReadablePanel::read (n);
|
||||
}
|
||||
protocol = new FGPanelProtocol (ApplicationProperties::Properties->getNode ("communication", true));
|
||||
protocol->init ();
|
||||
}
|
||||
|
||||
FGPanelApplication::~FGPanelApplication()
|
||||
{
|
||||
FGPanelApplication::~FGPanelApplication () {
|
||||
}
|
||||
|
||||
void FGPanelApplication::Run()
|
||||
{
|
||||
int mode = GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE;
|
||||
int w = panel == NULL ? 0 : panel->getWidth();
|
||||
int h = panel == NULL ? 0 : panel->getHeight();
|
||||
if( w == 0 && h == 0 ) {
|
||||
void
|
||||
FGPanelApplication::Run () {
|
||||
#ifdef _GLES2
|
||||
const int mode (0);
|
||||
#else
|
||||
const int mode (GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
|
||||
#endif
|
||||
int w (panel == NULL ? 0 : panel->getWidth ());
|
||||
int h (panel == NULL ? 0 : panel->getHeight ());
|
||||
if (w == 0 && h == 0) {
|
||||
w = 1024;
|
||||
h = 768;
|
||||
} else if( w == 0 ) {
|
||||
} else if (w == 0) {
|
||||
w = h / 0.75;
|
||||
} else if( h == 0 ) {
|
||||
} else if (h == 0) {
|
||||
h = w * 0.75;
|
||||
}
|
||||
|
||||
bool gameMode = ApplicationProperties::Properties->getNode( "game-mode", true )->getBoolValue();
|
||||
FGGLApplication::Run( mode, gameMode, w, h );
|
||||
|
||||
const bool gameMode (ApplicationProperties::Properties->getNode ( "game-mode", true)->getBoolValue ());
|
||||
FGGLApplication::Run (mode, gameMode, w, h);
|
||||
}
|
||||
|
||||
void FGPanelApplication::Init()
|
||||
{
|
||||
glAlphaFunc(GL_GREATER, 0.1);
|
||||
glutSetCursor( GLUT_CURSOR_NONE );
|
||||
ApplicationProperties::fontCache.initializeFonts();
|
||||
void
|
||||
FGPanelApplication::Init () {
|
||||
#ifndef _GLES2
|
||||
glutSetCursor (GLUT_CURSOR_NONE);
|
||||
#endif
|
||||
if (panel != NULL) {
|
||||
panel->init ();
|
||||
}
|
||||
}
|
||||
|
||||
void FGPanelApplication::Reshape( int width, int height )
|
||||
{
|
||||
void
|
||||
FGPanelApplication::Reshape (const int width, const int height) {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
glViewport(0, 0, (GLsizei) width, (GLsizei) height);
|
||||
glViewport (0, 0, GLsizei (width), GLsizei (height));
|
||||
}
|
||||
|
||||
void FGPanelApplication::Idle()
|
||||
{
|
||||
double d = glutGet(GLUT_ELAPSED_TIME);
|
||||
|
||||
double dt = Sleep();
|
||||
if( dt == 0 )
|
||||
void
|
||||
FGPanelApplication::Idle () {
|
||||
#ifndef _GLES2
|
||||
const double d (glutGet (GLUT_ELAPSED_TIME));
|
||||
#endif
|
||||
const double dt (Sleep ());
|
||||
if (dt == 0) {
|
||||
return;
|
||||
|
||||
if( panel != NULL )
|
||||
panel->update( dt );
|
||||
|
||||
glutSwapBuffers();
|
||||
|
||||
if( protocol != NULL )
|
||||
protocol->update( dt );
|
||||
|
||||
}
|
||||
if (panel != NULL) {
|
||||
panel->update (dt);
|
||||
}
|
||||
#ifndef _GLES2
|
||||
glutSwapBuffers ();
|
||||
#endif
|
||||
if (protocol != NULL) {
|
||||
protocol->update (dt);
|
||||
}
|
||||
#ifndef _GLES2
|
||||
static double dsum = 0.0;
|
||||
static unsigned cnt = 0;
|
||||
dsum += glutGet(GLUT_ELAPSED_TIME)-d;
|
||||
dsum += glutGet (GLUT_ELAPSED_TIME) - d;
|
||||
cnt++;
|
||||
if( dsum > 1000.0 ) {
|
||||
ApplicationProperties::Properties->getNode( "/sim/frame-rate", true )->setDoubleValue(cnt*1000.0/dsum );
|
||||
if (dsum > 1000.0) {
|
||||
ApplicationProperties::Properties->getNode ("/sim/frame-rate", true)->setDoubleValue (cnt * 1000.0 / dsum);
|
||||
dsum = 0.0;
|
||||
cnt = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FGPanelApplication::Key( unsigned char key, int x, int y )
|
||||
{
|
||||
switch( key ) {
|
||||
case 0x1b:
|
||||
exit(0);
|
||||
break;
|
||||
void
|
||||
FGPanelApplication::Key (const unsigned char key, const int x, const int y) {
|
||||
switch (key) {
|
||||
case 0x1b:
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
double FGPanelApplication::Sleep()
|
||||
{
|
||||
double
|
||||
FGPanelApplication::Sleep () {
|
||||
SGTimeStamp current_time_stamp;
|
||||
static SGTimeStamp last_time_stamp;
|
||||
|
||||
if ( last_time_stamp.get_seconds() == 0 )
|
||||
last_time_stamp.stamp();
|
||||
|
||||
double model_hz = 60;
|
||||
double throttle_hz = ApplicationProperties::getDouble("/sim/frame-rate-throttle-hz", 0.0);
|
||||
if ( throttle_hz > 0.0 ) {
|
||||
if (last_time_stamp.get_seconds () == 0) {
|
||||
last_time_stamp.stamp ();
|
||||
}
|
||||
const double model_hz (60);
|
||||
const double throttle_hz (ApplicationProperties::getDouble ("/sim/frame-rate-throttle-hz", 0.0));
|
||||
if (throttle_hz > 0.0) {
|
||||
// optionally throttle the frame rate (to get consistent frame
|
||||
// rates or reduce cpu usage.
|
||||
|
||||
double frame_us = 1.0e6 / throttle_hz;
|
||||
double frame_us (1.0e6 / throttle_hz);
|
||||
|
||||
// sleep based timing loop.
|
||||
//
|
||||
|
@ -292,19 +285,19 @@ double FGPanelApplication::Sleep()
|
|||
// sleep() will always overshoot by a bit so undersleep by
|
||||
// 2000us in the hopes of never oversleeping.
|
||||
frame_us -= 2000.0;
|
||||
if ( frame_us < 0.0 ) {
|
||||
if (frame_us < 0.0) {
|
||||
frame_us = 0.0;
|
||||
}
|
||||
current_time_stamp.stamp();
|
||||
current_time_stamp.stamp ();
|
||||
|
||||
/* Convert to ms */
|
||||
double elapsed_us = (current_time_stamp - last_time_stamp).toUSecs();
|
||||
if ( elapsed_us < frame_us ) {
|
||||
double requested_us = frame_us - elapsed_us;
|
||||
const double elapsed_us ((current_time_stamp - last_time_stamp).toUSecs ());
|
||||
if (elapsed_us < frame_us) {
|
||||
const double requested_us (frame_us - elapsed_us);
|
||||
#ifdef _WIN32
|
||||
::Sleep ((int)(requested_us / 1000.0)) ;
|
||||
::Sleep (int (requested_us / 1000.0));
|
||||
#else
|
||||
usleep ( (useconds_t)(requested_us ) ) ;
|
||||
usleep (useconds_t (requested_us));
|
||||
#endif
|
||||
}
|
||||
// busy wait timing loop.
|
||||
|
@ -312,82 +305,27 @@ double FGPanelApplication::Sleep()
|
|||
// This yields the most accurate timing. If the previous
|
||||
// usleep() call is omitted this will peg the cpu
|
||||
// (which is just fine if FG is the only app you care about.)
|
||||
current_time_stamp.stamp();
|
||||
SGTimeStamp next_time_stamp = last_time_stamp;
|
||||
next_time_stamp += SGTimeStamp::fromSec(1e-6*frame_us);
|
||||
while ( current_time_stamp < next_time_stamp ) {
|
||||
current_time_stamp.stamp();
|
||||
current_time_stamp.stamp ();
|
||||
const SGTimeStamp next_time_stamp (last_time_stamp + SGTimeStamp::fromSec (1e-6*frame_us));
|
||||
while (current_time_stamp < next_time_stamp) {
|
||||
current_time_stamp.stamp ();
|
||||
}
|
||||
|
||||
} else {
|
||||
current_time_stamp.stamp();
|
||||
current_time_stamp.stamp ();
|
||||
}
|
||||
|
||||
double real_delta_time_sec = double(current_time_stamp.toUSecs() - last_time_stamp.toUSecs()) / 1000000.0;
|
||||
static double reminder = 0.0;
|
||||
static long global_multi_loop = 0;
|
||||
const double real_delta_time_sec ((double (current_time_stamp.toUSecs () - last_time_stamp.toUSecs ()) / 1000000.0) + reminder);
|
||||
last_time_stamp = current_time_stamp;
|
||||
//fprintf(stdout,"\r%4.1lf ", 1/real_delta_time_sec );
|
||||
//fflush(stdout);
|
||||
|
||||
// round the real time down to a multiple of 1/model-hz.
|
||||
// this way all systems are updated the _same_ amount of dt.
|
||||
static double reminder = 0.0;
|
||||
static long global_multi_loop = 0;
|
||||
real_delta_time_sec += reminder;
|
||||
global_multi_loop = long(floor(real_delta_time_sec*model_hz));
|
||||
global_multi_loop = SGMisc<long>::max(0, global_multi_loop);
|
||||
reminder = real_delta_time_sec - double(global_multi_loop)/double(model_hz);
|
||||
return double(global_multi_loop)/double(model_hz);
|
||||
global_multi_loop = long (floor (real_delta_time_sec * model_hz));
|
||||
global_multi_loop = SGMisc<long>::max (0, global_multi_loop);
|
||||
reminder = real_delta_time_sec - double (global_multi_loop) / double (model_hz);
|
||||
return double (global_multi_loop) / double (model_hz);
|
||||
}
|
||||
|
||||
double ApplicationProperties::getDouble( const char * name, double def )
|
||||
{
|
||||
SGPropertyNode_ptr n = ApplicationProperties::Properties->getNode( name, false );
|
||||
if( n == NULL ) return def;
|
||||
return n->getDoubleValue();
|
||||
}
|
||||
|
||||
SGPath ApplicationProperties::GetCwd()
|
||||
{
|
||||
SGPath path(".");
|
||||
char buf[512], *cwd = getcwd(buf, 511);
|
||||
buf[511] = '\0';
|
||||
if (cwd)
|
||||
{
|
||||
path = SGPath::fromLocal8Bit(cwd);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
SGPath ApplicationProperties::GetRootPath( const char * sub )
|
||||
{
|
||||
if( sub != NULL )
|
||||
{
|
||||
SGPath subpath( sub );
|
||||
|
||||
// relative path to current working dir?
|
||||
if (subpath.isRelative())
|
||||
{
|
||||
SGPath path = GetCwd();
|
||||
path.append( sub );
|
||||
if (path.exists())
|
||||
return path;
|
||||
}
|
||||
else
|
||||
if ( subpath.exists() )
|
||||
{
|
||||
// absolute path
|
||||
return subpath;
|
||||
}
|
||||
}
|
||||
|
||||
// default: relative path to FGROOT
|
||||
SGPath path( ApplicationProperties::root );
|
||||
if( sub != NULL )
|
||||
path.append( sub );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string ApplicationProperties::root = ".";
|
||||
SGPropertyNode_ptr ApplicationProperties::Properties = new SGPropertyNode;
|
||||
FGFontCache ApplicationProperties::fontCache;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -18,32 +18,28 @@
|
|||
#ifndef __FGPANELAPPLICATION_HXX
|
||||
#define __FGPANELAPPLICATION_HXX
|
||||
|
||||
#include "FGGLApplication.hxx"
|
||||
#include "FGPanelProtocol.hxx"
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "panel.hxx"
|
||||
#include "FGGLApplication.hxx"
|
||||
#include "FGPanel.hxx"
|
||||
#include "FGPanelProtocol.hxx"
|
||||
|
||||
class FGPanelApplication : public FGGLApplication {
|
||||
public:
|
||||
FGPanelApplication( int argc, char ** argv );
|
||||
~FGPanelApplication();
|
||||
FGPanelApplication (int argc, char **argv);
|
||||
~FGPanelApplication ();
|
||||
|
||||
void Run();
|
||||
void Run ();
|
||||
|
||||
protected:
|
||||
virtual void Key( unsigned char key, int x, int y );
|
||||
virtual void Idle();
|
||||
// virtual void Display();
|
||||
virtual void Reshape( int width, int height );
|
||||
virtual void Key (const unsigned char key, const int x, const int y);
|
||||
virtual void Idle ();
|
||||
// !!! virtual void Display ();
|
||||
virtual void Reshape (const int width, const int height);
|
||||
|
||||
virtual void Init();
|
||||
virtual void Init ();
|
||||
|
||||
double Sleep();
|
||||
double Sleep ();
|
||||
|
||||
SGSharedPtr<FGPanel> panel;
|
||||
SGSharedPtr<FGPanelProtocol> protocol;
|
||||
|
|
65
utils/fgpanel/FGPanelInstrument.cxx
Normal file
65
utils/fgpanel/FGPanelInstrument.cxx
Normal file
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "FGPanelInstrument.hxx"
|
||||
|
||||
FGPanelInstrument::FGPanelInstrument () {
|
||||
setPosition (0, 0);
|
||||
setSize (0, 0);
|
||||
}
|
||||
|
||||
FGPanelInstrument::FGPanelInstrument (const int x, const int y, const int w, const int h) {
|
||||
setPosition (x, y);
|
||||
setSize (w, h);
|
||||
}
|
||||
|
||||
FGPanelInstrument::~FGPanelInstrument () {
|
||||
}
|
||||
|
||||
void
|
||||
FGPanelInstrument::setPosition (const int x, const int y) {
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanelInstrument::setSize (const int w, const int h) {
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getXPos () const {
|
||||
return m_x;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getYPos () const {
|
||||
return m_y;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getWidth () const {
|
||||
return m_w;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getHeight () const {
|
||||
return m_h;
|
||||
}
|
56
utils/fgpanel/FGPanelInstrument.hxx
Normal file
56
utils/fgpanel/FGPanelInstrument.hxx
Normal file
|
@ -0,0 +1,56 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGPANELINSTRUMENT_HXX
|
||||
#define FGPANELINSTRUMENT_HXX
|
||||
|
||||
#include <simgear/props/condition.hxx>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Abstract base class for a panel instrument.
|
||||
*
|
||||
* A panel instrument consists of zero or more actions, associated
|
||||
* with mouse clicks in rectangular areas. Currently, the only
|
||||
* concrete class derived from this is FGLayeredInstrument, but others
|
||||
* may show up in the future (some complex instruments could be
|
||||
* entirely hand-coded, for example).
|
||||
*/
|
||||
class FGPanelInstrument : public SGConditional {
|
||||
public:
|
||||
FGPanelInstrument ();
|
||||
FGPanelInstrument (const int x, const int y, const int w, const int h);
|
||||
virtual ~FGPanelInstrument ();
|
||||
|
||||
virtual void draw () = 0;
|
||||
|
||||
virtual void setPosition (const int x, const int y);
|
||||
virtual void setSize (const int w, const int h);
|
||||
|
||||
virtual int getXPos () const;
|
||||
virtual int getYPos () const;
|
||||
virtual int getWidth () const;
|
||||
virtual int getHeight () const;
|
||||
|
||||
private:
|
||||
int m_x, m_y, m_w, m_h;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -27,92 +27,92 @@
|
|||
#define strtof strtod
|
||||
#endif
|
||||
|
||||
#include "FGPanelProtocol.hxx"
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include <simgear/io/sg_socket.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
|
||||
using namespace std;
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "FGPanelProtocol.hxx"
|
||||
|
||||
class PropertySetter {
|
||||
public:
|
||||
PropertySetter( SGPropertyNode_ptr node ) : _node(node) {}
|
||||
virtual void setValue( const char * value ) = 0;
|
||||
virtual ~PropertySetter() {};
|
||||
PropertySetter (SGPropertyNode_ptr node) : _node (node) {}
|
||||
virtual void setValue (const char *value) = 0;
|
||||
virtual ~PropertySetter () {};
|
||||
protected:
|
||||
SGPropertyNode_ptr _node;
|
||||
};
|
||||
|
||||
class BoolPropertySetter : public PropertySetter {
|
||||
public:
|
||||
BoolPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
|
||||
virtual void setValue( const char * value ) {
|
||||
_node->setBoolValue( atoi( value ) != 0 );
|
||||
BoolPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
|
||||
virtual void setValue (const char *value) {
|
||||
_node->setBoolValue (atoi (value) != 0 );
|
||||
}
|
||||
};
|
||||
|
||||
class IntPropertySetter : public PropertySetter {
|
||||
public:
|
||||
IntPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
|
||||
virtual void setValue( const char * value ) {
|
||||
_node->setIntValue( atol( value ) );
|
||||
IntPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
|
||||
virtual void setValue (const char *value) {
|
||||
_node->setIntValue (atol (value));
|
||||
}
|
||||
};
|
||||
|
||||
class FloatPropertySetter : public PropertySetter {
|
||||
public:
|
||||
FloatPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
|
||||
virtual void setValue( const char * value ) {
|
||||
_node->setFloatValue( strtof( value, NULL ) );
|
||||
FloatPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
|
||||
virtual void setValue (const char *value) {
|
||||
_node->setFloatValue (strtof (value, NULL));
|
||||
}
|
||||
};
|
||||
|
||||
class DoublePropertySetter : public PropertySetter {
|
||||
public:
|
||||
DoublePropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
|
||||
virtual void setValue( const char * value ) {
|
||||
_node->setDoubleValue( strtod( value, NULL ) );
|
||||
DoublePropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
|
||||
virtual void setValue (const char *value) {
|
||||
_node->setDoubleValue (strtod (value, NULL));
|
||||
}
|
||||
};
|
||||
|
||||
class StringPropertySetter : public PropertySetter {
|
||||
public:
|
||||
StringPropertySetter( SGPropertyNode_ptr node ) : PropertySetter(node) {}
|
||||
virtual void setValue( const char * value ) {
|
||||
_node->setStringValue( value );
|
||||
StringPropertySetter (SGPropertyNode_ptr node) : PropertySetter (node) {}
|
||||
virtual void setValue (const char *value) {
|
||||
_node->setStringValue (value);
|
||||
}
|
||||
};
|
||||
|
||||
FGPanelProtocol::FGPanelProtocol( SGPropertyNode_ptr aRoot )
|
||||
: SGSubsystem(),
|
||||
root(aRoot),
|
||||
io(NULL)
|
||||
{
|
||||
SGPropertyNode_ptr outputNode = root->getNode( "protocol/generic/output" );
|
||||
if( outputNode ) {
|
||||
vector<SGPropertyNode_ptr> chunks = outputNode->getChildren( "chunk" );
|
||||
for( vector<SGPropertyNode_ptr>::size_type i = 0; i < chunks.size(); i++ ) {
|
||||
SGPropertyNode_ptr chunk = chunks[i];
|
||||
FGPanelProtocol::FGPanelProtocol (SGPropertyNode_ptr a_Root) :
|
||||
SGSubsystem (),
|
||||
root (a_Root),
|
||||
io (NULL) {
|
||||
const SGPropertyNode_ptr outputNode (root->getNode ("protocol/generic/output"));
|
||||
if (outputNode) {
|
||||
const vector<SGPropertyNode_ptr> chunks (outputNode->getChildren ("chunk"));
|
||||
for (vector<SGPropertyNode_ptr>::size_type i = 0; i < chunks.size (); i++) {
|
||||
const SGPropertyNode_ptr chunk (chunks[i]);
|
||||
|
||||
SGPropertyNode_ptr nodeNode = chunk->getNode("node", false );
|
||||
if( nodeNode == NULL )
|
||||
const SGPropertyNode_ptr nodeNode (chunk->getNode ("node", false));
|
||||
if (nodeNode == NULL) {
|
||||
continue;
|
||||
}
|
||||
const SGPropertyNode_ptr node (ApplicationProperties::Properties->getNode (nodeNode->getStringValue (), true));
|
||||
|
||||
SGPropertyNode_ptr node = ApplicationProperties::Properties->getNode( nodeNode->getStringValue(), true );
|
||||
|
||||
string type = "";
|
||||
SGPropertyNode_ptr typeNode = chunk->getNode( "type", false );
|
||||
if( typeNode != NULL ) type = typeNode->getStringValue();
|
||||
if( type == "float" ) {
|
||||
propertySetterVector.push_back( new FloatPropertySetter( node ) );
|
||||
} else if( type == "double" || type == "fixed" ) {
|
||||
propertySetterVector.push_back( new DoublePropertySetter( node ) );
|
||||
} else if( type == "bool" || type == "boolean" ) {
|
||||
propertySetterVector.push_back( new BoolPropertySetter( node ) );
|
||||
} else if( type == "string" ) {
|
||||
propertySetterVector.push_back( new StringPropertySetter( node ) );
|
||||
string type;
|
||||
const SGPropertyNode_ptr typeNode (chunk->getNode ("type", false));
|
||||
if (typeNode != NULL) {
|
||||
type = typeNode->getStringValue ();
|
||||
}
|
||||
if (type == "float") {
|
||||
propertySetterVector.push_back (new FloatPropertySetter (node));
|
||||
} else if (type == "double" || type == "fixed") {
|
||||
propertySetterVector.push_back (new DoublePropertySetter (node));
|
||||
} else if (type == "bool" || type == "boolean") {
|
||||
propertySetterVector.push_back (new BoolPropertySetter (node));
|
||||
} else if (type == "string") {
|
||||
propertySetterVector.push_back (new StringPropertySetter (node));
|
||||
} else {
|
||||
propertySetterVector.push_back( new IntPropertySetter( node ) );
|
||||
propertySetterVector.push_back (new IntPropertySetter (node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,60 +120,60 @@ FGPanelProtocol::FGPanelProtocol( SGPropertyNode_ptr aRoot )
|
|||
|
||||
FGPanelProtocol::~FGPanelProtocol()
|
||||
{
|
||||
for( PropertySetterVector::size_type i = 0; i < propertySetterVector.size(); i++ )
|
||||
for (PropertySetterVector::size_type i = 0; i < propertySetterVector.size(); i++) {
|
||||
delete propertySetterVector[i];
|
||||
}
|
||||
}
|
||||
|
||||
void FGPanelProtocol::update( double dt )
|
||||
{
|
||||
void
|
||||
FGPanelProtocol::update (double dt) {
|
||||
char buf[2][8192];
|
||||
|
||||
if( io == NULL )
|
||||
if (io == NULL) {
|
||||
return;
|
||||
|
||||
}
|
||||
// read all available lines, keep last one
|
||||
int Page = 0;
|
||||
bool HaveData = false;
|
||||
while ( io->readline( buf[Page], sizeof(buf[Page])-1 ) > 0 )
|
||||
{
|
||||
HaveData = true;
|
||||
Page ^= 1;
|
||||
int Page (0);
|
||||
bool HaveData (false);
|
||||
while (io->readline (buf[Page], sizeof (buf[Page]) - 1) > 0) {
|
||||
HaveData = true;
|
||||
Page ^= 1;
|
||||
}
|
||||
|
||||
if ( HaveData ) {
|
||||
if (HaveData) {
|
||||
// process most recent line of data
|
||||
Page ^= 1;
|
||||
buf[Page][sizeof(buf[Page])-1] = 0;
|
||||
vector<string> tokens = simgear::strutils::split( buf[Page], "," );
|
||||
for( vector<string>::size_type i = 0; i < tokens.size(); i++ ) {
|
||||
if( i < propertySetterVector.size() )
|
||||
propertySetterVector[i]->setValue( tokens[i].c_str() );
|
||||
buf[Page][sizeof (buf[Page]) - 1] = 0;
|
||||
const vector<string> tokens (simgear::strutils::split (buf[Page], ","));
|
||||
for (vector<string>::size_type i = 0; i < tokens.size (); i++) {
|
||||
if (i < propertySetterVector.size ()) {
|
||||
propertySetterVector[i]->setValue (tokens[i].c_str ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FGPanelProtocol::init()
|
||||
{
|
||||
SGPropertyNode_ptr listenNode = root->getNode( "listen" );
|
||||
if( listenNode == NULL ) {
|
||||
void
|
||||
FGPanelProtocol::init () {
|
||||
const SGPropertyNode_ptr listenNode (root->getNode ("listen"));
|
||||
if (listenNode == NULL) {
|
||||
return;
|
||||
}
|
||||
const string hostname (listenNode->getNode ("host", true)->getStringValue ());
|
||||
const string port (listenNode->getNode ("port", true)->getStringValue ());
|
||||
const string style (listenNode->getNode ("style", true)->getStringValue ());
|
||||
|
||||
string hostname = listenNode->getNode( "host", true )->getStringValue();
|
||||
string port = listenNode->getNode( "port", true )->getStringValue();
|
||||
string style = listenNode->getNode( "style", true )->getStringValue();
|
||||
|
||||
if( io != NULL )
|
||||
if (io != NULL) {
|
||||
delete io;
|
||||
}
|
||||
io = new SGSocket (hostname, port, style);
|
||||
|
||||
io = new SGSocket( hostname, port, style );
|
||||
|
||||
if( !io->open( SG_IO_IN ) ) {
|
||||
if (!io->open (SG_IO_IN)) {
|
||||
cerr << "can't open socket " << style << ":" << hostname << ":" << port << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void FGPanelProtocol::reinit()
|
||||
{
|
||||
init();
|
||||
void
|
||||
FGPanelProtocol::reinit () {
|
||||
init ();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -17,25 +17,31 @@
|
|||
//
|
||||
#ifndef __FGPANELPROTOCOL_HXX
|
||||
#define __FGPANELPROTOCOL_HXX
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/io/iochannel.hxx>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class PropertySetter;
|
||||
|
||||
typedef std::vector<PropertySetter*> PropertySetterVector;
|
||||
typedef vector<PropertySetter*> PropertySetterVector;
|
||||
|
||||
class FGPanelProtocol : public SGSubsystem {
|
||||
public:
|
||||
FGPanelProtocol( SGPropertyNode_ptr root );
|
||||
virtual ~FGPanelProtocol();
|
||||
virtual void init();
|
||||
virtual void reinit();
|
||||
virtual void update( double dt );
|
||||
FGPanelProtocol (SGPropertyNode_ptr a_Root);
|
||||
virtual ~FGPanelProtocol ();
|
||||
virtual void init ();
|
||||
virtual void reinit ();
|
||||
virtual void update (double dt);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
SGPropertyNode_ptr root;
|
||||
SGIOChannel * io;
|
||||
SGIOChannel *io;
|
||||
PropertySetterVector propertySetterVector;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
28
utils/fgpanel/FGPanelTransformation.cxx
Normal file
28
utils/fgpanel/FGPanelTransformation.cxx
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "FGPanelTransformation.hxx"
|
||||
|
||||
FGPanelTransformation::FGPanelTransformation () :
|
||||
table (0) {
|
||||
}
|
||||
|
||||
FGPanelTransformation::~FGPanelTransformation () {
|
||||
delete table;
|
||||
}
|
52
utils/fgpanel/FGPanelTransformation.hxx
Normal file
52
utils/fgpanel/FGPanelTransformation.hxx
Normal file
|
@ -0,0 +1,52 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGPANELTRANSFORMATION_HXX
|
||||
#define FGPANELTRANSFORMATION_HXX
|
||||
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
/**
|
||||
* A transformation for a layer.
|
||||
*/
|
||||
class FGPanelTransformation : public SGConditional {
|
||||
public:
|
||||
enum Type {
|
||||
XSHIFT,
|
||||
YSHIFT,
|
||||
ROTATION
|
||||
};
|
||||
|
||||
FGPanelTransformation ();
|
||||
virtual ~FGPanelTransformation ();
|
||||
|
||||
Type type;
|
||||
SGConstPropertyNode_ptr node;
|
||||
float min;
|
||||
float max;
|
||||
bool has_mod;
|
||||
float mod;
|
||||
float factor;
|
||||
float offset;
|
||||
SGInterpTable *table;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -25,23 +25,25 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "FGRGBTextureLoader.hxx"
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <GLUT/glut.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
typedef struct _rawImageRec
|
||||
{
|
||||
#include "FGRGBTextureLoader.hxx"
|
||||
|
||||
typedef struct _rawImageRec {
|
||||
unsigned short imagic;
|
||||
unsigned short type;
|
||||
unsigned short dim;
|
||||
|
@ -50,145 +52,138 @@ typedef struct _rawImageRec
|
|||
unsigned long wasteBytes;
|
||||
char name[80];
|
||||
unsigned long colorMap;
|
||||
std::istream *file;
|
||||
istream *file;
|
||||
unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
|
||||
unsigned long rleEnd;
|
||||
GLuint *rowStart;
|
||||
GLint *rowSize;
|
||||
GLenum swapFlag;
|
||||
short bpc;
|
||||
|
||||
typedef unsigned char * BytePtr;
|
||||
|
||||
bool needsBytesSwapped()
|
||||
{
|
||||
typedef unsigned char *BytePtr;
|
||||
|
||||
bool needsBytesSwapped () {
|
||||
union {
|
||||
int testWord;
|
||||
char testByte[sizeof(int)];
|
||||
}endianTest;
|
||||
char testByte[sizeof (int)];
|
||||
} endianTest;
|
||||
endianTest.testWord = 1;
|
||||
if( endianTest.testByte[0] == 1 )
|
||||
if (endianTest.testByte[0] == 1) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void swapBytes( T &s )
|
||||
{
|
||||
if( sizeof( T ) == 1 )
|
||||
return;
|
||||
inline void swapBytes (T &s) {
|
||||
if (sizeof (T) == 1) {
|
||||
return;
|
||||
}
|
||||
T d = s;
|
||||
BytePtr sptr ((BytePtr) &s);
|
||||
BytePtr dptr = &(((BytePtr) &d)[sizeof (T) - 1]);
|
||||
|
||||
T d = s;
|
||||
BytePtr sptr = (BytePtr)&s;
|
||||
BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
|
||||
|
||||
for( unsigned int i = 0; i < sizeof(T); i++ )
|
||||
*(sptr++) = *(dptr--);
|
||||
for (unsigned int i = 0; i < sizeof (T); i++) {
|
||||
*(sptr++) = *(dptr--);
|
||||
}
|
||||
}
|
||||
|
||||
void swapBytes()
|
||||
{
|
||||
swapBytes( imagic );
|
||||
swapBytes( type );
|
||||
swapBytes( dim );
|
||||
swapBytes( sizeX );
|
||||
swapBytes( sizeY );
|
||||
swapBytes( sizeZ );
|
||||
swapBytes( wasteBytes );
|
||||
swapBytes( min );
|
||||
swapBytes( max );
|
||||
swapBytes( colorMap );
|
||||
void swapBytes () {
|
||||
swapBytes (imagic);
|
||||
swapBytes (type);
|
||||
swapBytes (dim);
|
||||
swapBytes (sizeX);
|
||||
swapBytes (sizeY);
|
||||
swapBytes (sizeZ);
|
||||
swapBytes (wasteBytes);
|
||||
swapBytes (min);
|
||||
swapBytes (max);
|
||||
swapBytes (colorMap);
|
||||
}
|
||||
} rawImageRec;
|
||||
|
||||
static void ConvertShort(unsigned short *array, long length)
|
||||
{
|
||||
static void
|
||||
ConvertShort (unsigned short *array, long length) {
|
||||
unsigned long b1, b2;
|
||||
unsigned char *ptr;
|
||||
|
||||
ptr = (unsigned char *)array;
|
||||
while (length--)
|
||||
{
|
||||
b1 = *ptr++;
|
||||
b2 = *ptr++;
|
||||
*array++ = (unsigned short) ((b1 << 8) | (b2));
|
||||
unsigned char *ptr ((unsigned char *) array);
|
||||
while (length--) {
|
||||
b1 = *ptr++;
|
||||
b2 = *ptr++;
|
||||
*array++ = (unsigned short) ((b1 << 8) | (b2));
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertLong(GLuint *array, long length)
|
||||
{
|
||||
static void
|
||||
ConvertLong (GLuint *array, long length) {
|
||||
unsigned long b1, b2, b3, b4;
|
||||
unsigned char *ptr;
|
||||
|
||||
ptr = (unsigned char *)array;
|
||||
while (length--)
|
||||
{
|
||||
b1 = *ptr++;
|
||||
b2 = *ptr++;
|
||||
b3 = *ptr++;
|
||||
b4 = *ptr++;
|
||||
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
|
||||
unsigned char *ptr ((unsigned char *) array);
|
||||
while (length--) {
|
||||
b1 = *ptr++;
|
||||
b2 = *ptr++;
|
||||
b3 = *ptr++;
|
||||
b4 = *ptr++;
|
||||
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void RawImageClose(rawImageRec *raw)
|
||||
{
|
||||
if (raw)
|
||||
{
|
||||
|
||||
if (raw->tmp) delete [] raw->tmp;
|
||||
if (raw->tmpR) delete [] raw->tmpR;
|
||||
if (raw->tmpG) delete [] raw->tmpG;
|
||||
if (raw->tmpB) delete [] raw->tmpB;
|
||||
if (raw->tmpA) delete [] raw->tmpA;
|
||||
|
||||
if (raw->rowStart) delete [] raw->rowStart;
|
||||
if (raw->rowSize) delete [] raw->rowSize;
|
||||
|
||||
delete raw;
|
||||
static void
|
||||
RawImageClose (rawImageRec *raw) {
|
||||
if (raw) {
|
||||
if (raw->tmp) {
|
||||
delete []raw->tmp;
|
||||
}
|
||||
if (raw->tmpR) {
|
||||
delete []raw->tmpR;
|
||||
}
|
||||
if (raw->tmpG) {
|
||||
delete []raw->tmpG;
|
||||
}
|
||||
if (raw->tmpB) {
|
||||
delete []raw->tmpB;
|
||||
}
|
||||
if (raw->tmpA) {
|
||||
delete []raw->tmpA;
|
||||
}
|
||||
if (raw->rowStart) {
|
||||
delete []raw->rowStart;
|
||||
}
|
||||
if (raw->rowSize) {
|
||||
delete []raw->rowSize;
|
||||
}
|
||||
delete raw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static rawImageRec *RawImageOpen(std::istream& fin)
|
||||
{
|
||||
union
|
||||
{
|
||||
int testWord;
|
||||
char testByte[4];
|
||||
static rawImageRec *
|
||||
RawImageOpen (istream& fin) {
|
||||
union {
|
||||
int testWord;
|
||||
char testByte[4];
|
||||
} endianTest;
|
||||
rawImageRec *raw;
|
||||
int x;
|
||||
|
||||
raw = new rawImageRec;
|
||||
if (raw == NULL)
|
||||
{
|
||||
// notify(WARN)<< "Out of memory!"<< std::endl;
|
||||
return NULL;
|
||||
rawImageRec *raw = new rawImageRec;
|
||||
if (raw == NULL) {
|
||||
// notify(WARN)<< "Out of memory!"<< endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Set istream pointer
|
||||
raw->file = &fin;
|
||||
|
||||
endianTest.testWord = 1;
|
||||
if (endianTest.testByte[0] == 1)
|
||||
{
|
||||
raw->swapFlag = GL_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw->swapFlag = GL_FALSE;
|
||||
if (endianTest.testByte[0] == 1) {
|
||||
raw->swapFlag = GL_TRUE;
|
||||
} else {
|
||||
raw->swapFlag = GL_FALSE;
|
||||
}
|
||||
|
||||
fin.read((char*)raw,12);
|
||||
if (!fin.good())
|
||||
return NULL;
|
||||
|
||||
if (raw->swapFlag)
|
||||
{
|
||||
ConvertShort(&raw->imagic, 6);
|
||||
fin.read ((char*) raw, 12);
|
||||
if (!fin.good ()) {
|
||||
return NULL;
|
||||
}
|
||||
if (raw->swapFlag) {
|
||||
ConvertShort (&raw->imagic, 6);
|
||||
}
|
||||
|
||||
raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
|
||||
|
@ -196,259 +191,228 @@ static rawImageRec *RawImageOpen(std::istream& fin)
|
|||
raw->rowSize = 0;
|
||||
raw->bpc = (raw->type & 0x00FF);
|
||||
|
||||
raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
|
||||
if (raw->tmp == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
raw->tmp = new unsigned char[raw->sizeX * 256 * raw->bpc];
|
||||
if (raw->tmp == NULL ) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (raw->sizeZ >= 1) {
|
||||
if ((raw->tmpR = new unsigned char[raw->sizeX * raw->bpc]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (raw->sizeZ >= 2) {
|
||||
if ((raw->tmpG = new unsigned char[raw->sizeX * raw->bpc]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (raw->sizeZ >= 3) {
|
||||
if ((raw->tmpB = new unsigned char[raw->sizeX*raw->bpc]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (raw->sizeZ >= 4) {
|
||||
if ((raw->tmpA = new unsigned char[raw->sizeX * raw->bpc]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( raw->sizeZ >= 1 )
|
||||
{
|
||||
if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if( raw->sizeZ >= 2 )
|
||||
{
|
||||
if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if( raw->sizeZ >= 3 )
|
||||
{
|
||||
if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (raw->sizeZ >= 4)
|
||||
{
|
||||
if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((raw->type & 0xFF00) == 0x0100)
|
||||
{
|
||||
unsigned int ybyz = raw->sizeY * raw->sizeZ;
|
||||
if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
if ((raw->type & 0xFF00) == 0x0100) {
|
||||
unsigned int ybyz (raw->sizeY * raw->sizeZ);
|
||||
if ((raw->rowStart = new GLuint[ybyz]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (raw->rowSize = new GLint [ybyz]) == NULL )
|
||||
{
|
||||
// notify(FATAL)<< "Out of memory!"<< std::endl;
|
||||
RawImageClose(raw);
|
||||
return NULL;
|
||||
}
|
||||
x = ybyz * sizeof(GLuint);
|
||||
raw->rleEnd = 512 + (2 * x);
|
||||
fin.seekg(512,std::ios::beg);
|
||||
fin.read((char*)raw->rowStart,x);
|
||||
fin.read((char*)raw->rowSize,x);
|
||||
if (raw->swapFlag)
|
||||
{
|
||||
ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
|
||||
ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
|
||||
}
|
||||
if ((raw->rowSize = new GLint[ybyz]) == NULL) {
|
||||
// notify(FATAL)<< "Out of memory!"<< endl;
|
||||
RawImageClose (raw);
|
||||
return NULL;
|
||||
}
|
||||
int x (ybyz * sizeof (GLuint));
|
||||
raw->rleEnd = 512 + (2 * x);
|
||||
fin.seekg (512, ios::beg);
|
||||
fin.read ((char*) raw->rowStart, x);
|
||||
fin.read ((char*) raw->rowSize, x);
|
||||
if (raw->swapFlag) {
|
||||
ConvertLong (raw->rowStart, long (x / sizeof (GLuint)));
|
||||
ConvertLong ((GLuint *) raw->rowSize, long (x /sizeof (GLint)));
|
||||
}
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
|
||||
static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
|
||||
{
|
||||
unsigned char *iPtr, *oPtr;
|
||||
static void
|
||||
RawImageGetRow (rawImageRec *raw, unsigned char *buf, const int y, const int z) {
|
||||
unsigned short pixel;
|
||||
int count, done = 0;
|
||||
int done = 0;
|
||||
unsigned short *tempShort;
|
||||
|
||||
if ((raw->type & 0xFF00) == 0x0100)
|
||||
{
|
||||
raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
|
||||
raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
|
||||
if ((raw->type & 0xFF00) == 0x0100) {
|
||||
raw->file->seekg (long (raw->rowStart[y + z * raw->sizeY]), ios::beg);
|
||||
raw->file->read ((char*) raw->tmp, (unsigned int) (raw->rowSize[y + z * raw->sizeY]));
|
||||
|
||||
iPtr = raw->tmp;
|
||||
oPtr = buf;
|
||||
while (!done)
|
||||
{
|
||||
if (raw->bpc == 1)
|
||||
pixel = *iPtr++;
|
||||
else
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
|
||||
if(raw->bpc != 1)
|
||||
ConvertShort(&pixel, 1);
|
||||
|
||||
count = (int)(pixel & 0x7F);
|
||||
|
||||
// limit the count value to the remiaing row size
|
||||
if (oPtr + count*raw->bpc > buf + raw->sizeX*raw->bpc)
|
||||
{
|
||||
count = ( (buf + raw->sizeX*raw->bpc) - oPtr ) / raw->bpc;
|
||||
}
|
||||
|
||||
if (count<=0)
|
||||
{
|
||||
done = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixel & 0x80)
|
||||
{
|
||||
while (count--)
|
||||
{
|
||||
if(raw->bpc == 1)
|
||||
*oPtr++ = *iPtr++;
|
||||
else{
|
||||
tempShort = reinterpret_cast<unsigned short*>(iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
|
||||
ConvertShort(&pixel, 1);
|
||||
|
||||
tempShort = reinterpret_cast<unsigned short*>(oPtr);
|
||||
*tempShort = pixel;
|
||||
tempShort++;
|
||||
oPtr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (raw->bpc == 1)
|
||||
{
|
||||
pixel = *iPtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
if(raw->bpc != 1)
|
||||
ConvertShort(&pixel, 1);
|
||||
while (count--)
|
||||
{
|
||||
if(raw->bpc == 1)
|
||||
*oPtr++ = pixel;
|
||||
else
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(oPtr);
|
||||
*tempShort = pixel;
|
||||
tempShort++;
|
||||
oPtr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned char *iPtr = raw->tmp;
|
||||
unsigned char *oPtr = buf;
|
||||
while (!done) {
|
||||
if (raw->bpc == 1) {
|
||||
pixel = *iPtr++;
|
||||
} else {
|
||||
tempShort = reinterpret_cast<unsigned short*> (iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
|
||||
raw->file->read((char*)buf, raw->sizeX*raw->bpc);
|
||||
if(raw->swapFlag && raw->bpc != 1){
|
||||
ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
|
||||
|
||||
if (raw->bpc != 1) {
|
||||
ConvertShort (&pixel, 1);
|
||||
}
|
||||
int count (int (pixel & 0x7F));
|
||||
|
||||
// limit the count value to the remiaing row size
|
||||
if (oPtr + count * raw->bpc > buf + raw->sizeX * raw->bpc) {
|
||||
count = ((buf + raw->sizeX * raw->bpc) - oPtr) / raw->bpc;
|
||||
}
|
||||
|
||||
if (count <= 0) {
|
||||
done = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixel & 0x80) {
|
||||
while (count--) {
|
||||
if (raw->bpc == 1) {
|
||||
*oPtr++ = *iPtr++;
|
||||
} else {
|
||||
tempShort = reinterpret_cast<unsigned short*> (iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
|
||||
ConvertShort (&pixel, 1);
|
||||
|
||||
tempShort = reinterpret_cast<unsigned short*> (oPtr);
|
||||
*tempShort = pixel;
|
||||
tempShort++;
|
||||
oPtr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (raw->bpc == 1) {
|
||||
pixel = *iPtr++;
|
||||
} else {
|
||||
tempShort = reinterpret_cast<unsigned short*> (iPtr);
|
||||
pixel = *tempShort;
|
||||
tempShort++;
|
||||
iPtr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
if (raw->bpc != 1) {
|
||||
ConvertShort (&pixel, 1);
|
||||
}
|
||||
while (count--) {
|
||||
if (raw->bpc == 1) {
|
||||
*oPtr++ = pixel;
|
||||
} else {
|
||||
tempShort = reinterpret_cast<unsigned short*> (oPtr);
|
||||
*tempShort = pixel;
|
||||
tempShort++;
|
||||
oPtr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
raw->file->seekg (512 + (y * raw->sizeX * raw->bpc) + (z * raw->sizeX * raw->sizeY * raw->bpc), ios::beg);
|
||||
raw->file->read ((char*) buf, raw->sizeX * raw->bpc);
|
||||
if (raw->swapFlag && raw->bpc != 1) {
|
||||
ConvertShort (reinterpret_cast<unsigned short*> (buf), raw->sizeX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void RawImageGetData(rawImageRec *raw, unsigned char **data )
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int i, j;
|
||||
unsigned short *tempShort;
|
||||
static void
|
||||
RawImageGetData (rawImageRec *raw, unsigned char **data) {
|
||||
|
||||
// // round the width to a factor 4
|
||||
// int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
|
||||
// if (width!=raw->sizeX) width += 4;
|
||||
|
||||
// byte aligned.
|
||||
|
||||
// osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<std::endl;
|
||||
// osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<std::endl;
|
||||
// osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
|
||||
// osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<std::endl;
|
||||
|
||||
*data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
|
||||
|
||||
ptr = *data;
|
||||
for (i = 0; i < (int)(raw->sizeY); i++)
|
||||
{
|
||||
if( raw->sizeZ >= 1 )
|
||||
RawImageGetRow(raw, raw->tmpR, i, 0);
|
||||
if( raw->sizeZ >= 2 )
|
||||
RawImageGetRow(raw, raw->tmpG, i, 1);
|
||||
if( raw->sizeZ >= 3 )
|
||||
RawImageGetRow(raw, raw->tmpB, i, 2);
|
||||
if( raw->sizeZ >= 4 )
|
||||
RawImageGetRow(raw, raw->tmpA, i, 3);
|
||||
for (j = 0; j < (int)(raw->sizeX); j++)
|
||||
{
|
||||
if(raw->bpc == 1){
|
||||
if( raw->sizeZ >= 1 )
|
||||
*ptr++ = *(raw->tmpR + j);
|
||||
if( raw->sizeZ >= 2 )
|
||||
*ptr++ = *(raw->tmpG + j);
|
||||
if( raw->sizeZ >= 3 )
|
||||
*ptr++ = *(raw->tmpB + j);
|
||||
if( raw->sizeZ >= 4 )
|
||||
*ptr++ = *(raw->tmpA + j);
|
||||
}else{
|
||||
if( raw->sizeZ >= 1 )
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
if( raw->sizeZ >= 2 )
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
if( raw->sizeZ >= 3 )
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
if( raw->sizeZ >= 4 )
|
||||
{
|
||||
tempShort = reinterpret_cast<unsigned short*>(ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *>(tempShort);
|
||||
}
|
||||
// osg::notify(osg::INFO)<<"raw->sizeX = "<<raw->sizeX<<endl;
|
||||
// osg::notify(osg::INFO)<<"raw->sizeY = "<<raw->sizeY<<endl;
|
||||
// osg::notify(osg::INFO)<<"raw->sizeZ = "<<raw->sizeZ<<endl;
|
||||
// osg::notify(osg::INFO)<<"raw->bpc = "<<raw->bpc<<endl;
|
||||
|
||||
*data = new unsigned char [(raw->sizeX) * (raw->sizeY) * (raw->sizeZ) * (raw->bpc)];
|
||||
|
||||
unsigned char *ptr (*data);
|
||||
for (int i = 0; i < int (raw->sizeY); i++) {
|
||||
if (raw->sizeZ >= 1) {
|
||||
RawImageGetRow (raw, raw->tmpR, i, 0);
|
||||
}
|
||||
if (raw->sizeZ >= 2) {
|
||||
RawImageGetRow (raw, raw->tmpG, i, 1);
|
||||
}
|
||||
if (raw->sizeZ >= 3) {
|
||||
RawImageGetRow (raw, raw->tmpB, i, 2);
|
||||
}
|
||||
if (raw->sizeZ >= 4) {
|
||||
RawImageGetRow (raw, raw->tmpA, i, 3);
|
||||
}
|
||||
for (int j = 0; j < int (raw->sizeX); j++) {
|
||||
if (raw->bpc == 1) {
|
||||
if (raw->sizeZ >= 1) {
|
||||
*ptr++ = *(raw->tmpR + j);
|
||||
}
|
||||
if (raw->sizeZ >= 2) {
|
||||
*ptr++ = *(raw->tmpG + j);
|
||||
}
|
||||
if (raw->sizeZ >= 3) {
|
||||
*ptr++ = *(raw->tmpB + j);
|
||||
}
|
||||
if (raw->sizeZ >= 4) {
|
||||
*ptr++ = *(raw->tmpA + j);
|
||||
}
|
||||
} else {
|
||||
unsigned short *tempShort;
|
||||
if (raw->sizeZ >= 1) {
|
||||
tempShort = reinterpret_cast<unsigned short*> (ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*> (raw->tmpR) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
if (raw->sizeZ >= 2) {
|
||||
tempShort = reinterpret_cast<unsigned short*> (ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*> (raw->tmpG) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
if (raw->sizeZ >= 3) {
|
||||
tempShort = reinterpret_cast<unsigned short*> (ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*> (raw->tmpB) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
if (raw->sizeZ >= 4) {
|
||||
tempShort = reinterpret_cast<unsigned short*> (ptr);
|
||||
*tempShort = *(reinterpret_cast<unsigned short*> (raw->tmpA) + j);
|
||||
tempShort++;
|
||||
ptr = reinterpret_cast<unsigned char *> (tempShort);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // pad the image width with blanks to bring it up to the rounded width.
|
||||
// for(;j<width;++j) *ptr++ = 0;
|
||||
}
|
||||
|
@ -461,57 +425,53 @@ static void RawImageGetData(rawImageRec *raw, unsigned char **data )
|
|||
// supportsExtension("int","int image format");
|
||||
// supportsExtension("inta","inta image format");
|
||||
// supportsExtension("bw","bw image format");
|
||||
|
||||
GLuint readRGBStream(std::istream& fin)
|
||||
{
|
||||
rawImageRec *raw;
|
||||
|
||||
if( (raw = RawImageOpen(fin)) == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
GLuint
|
||||
readRGBStream (istream &fin) {
|
||||
rawImageRec * const raw (RawImageOpen (fin));
|
||||
|
||||
int s = raw->sizeX;
|
||||
int t = raw->sizeY;
|
||||
// int r = 1;
|
||||
if (raw == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
|
||||
raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
|
||||
#else
|
||||
// int internalFormat = raw->sizeZ;
|
||||
#endif
|
||||
unsigned int pixelFormat =
|
||||
raw->sizeZ == 1 ? GL_LUMINANCE :
|
||||
raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
|
||||
raw->sizeZ == 3 ? GL_RGB :
|
||||
raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
|
||||
GLint component = raw->sizeZ;
|
||||
const int s (raw->sizeX);
|
||||
const int t (raw->sizeY);
|
||||
// int r = 1;
|
||||
|
||||
unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
|
||||
GL_UNSIGNED_SHORT;
|
||||
#if 0
|
||||
int internalFormat = raw->sizeZ == 3 ? GL_RGB5 :
|
||||
raw->sizeZ == 4 ? GL_RGB5_A1 : GL_RGB;
|
||||
#else
|
||||
// int internalFormat = raw->sizeZ;
|
||||
#endif
|
||||
const unsigned int pixelFormat
|
||||
(raw->sizeZ == 1 ? GL_LUMINANCE :
|
||||
raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
|
||||
raw->sizeZ == 3 ? GL_RGB :
|
||||
raw->sizeZ == 4 ? GL_RGBA : (GLenum) - 1);
|
||||
|
||||
unsigned char *data;
|
||||
RawImageGetData(raw, &data);
|
||||
RawImageClose(raw);
|
||||
const unsigned int dataType (raw->bpc == 1 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT);
|
||||
|
||||
unsigned char *data;
|
||||
RawImageGetData (raw, &data);
|
||||
RawImageClose (raw);
|
||||
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
gluBuild2DMipmaps( GL_TEXTURE_2D, component, s, t, pixelFormat, dataType, (GLvoid*)data );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
|
||||
glGenTextures (1, &texture);
|
||||
glBindTexture (GL_TEXTURE_2D, texture);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, pixelFormat, s, t, 0, pixelFormat, dataType, (GLvoid*) data);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
delete []data;
|
||||
return texture;
|
||||
}
|
||||
|
||||
GLuint FGRGBTextureLoader::loadTexture( const std::string & filename )
|
||||
{
|
||||
GLuint texture = NOTEXTURE;
|
||||
std::ifstream istream(filename.c_str(), std::ios::in | std::ios::binary );
|
||||
texture = readRGBStream(istream);
|
||||
istream.close();
|
||||
delete []data;
|
||||
return texture;
|
||||
}
|
||||
|
||||
GLuint
|
||||
FGRGBTextureLoader::loadTexture (const string &filename) {
|
||||
GLuint texture = NOTEXTURE;
|
||||
ifstream istream (filename.c_str (), ios::in | ios::binary);
|
||||
texture = readRGBStream (istream);
|
||||
istream.close ();
|
||||
return texture;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -19,8 +20,9 @@
|
|||
|
||||
class FGRGBTextureLoader : public FGTextureLoaderInterface {
|
||||
public:
|
||||
virtual GLuint loadTexture( const std::string & filename );
|
||||
virtual GLuint loadTexture (const string &filename);
|
||||
|
||||
const static GLuint NOTEXTURE = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
37
utils/fgpanel/FGSwitchLayer.cxx
Normal file
37
utils/fgpanel/FGSwitchLayer.cxx
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "FGSwitchLayer.hxx"
|
||||
|
||||
FGSwitchLayer::FGSwitchLayer () :
|
||||
FGGroupLayer () {
|
||||
}
|
||||
|
||||
void
|
||||
FGSwitchLayer::draw () {
|
||||
if (test ()) {
|
||||
transform ();
|
||||
for (unsigned int i = 0; i < m_layers.size (); ++i) {
|
||||
if (m_layers[i]->test ()) {
|
||||
m_layers[i]->draw ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
utils/fgpanel/FGSwitchLayer.hxx
Normal file
38
utils/fgpanel/FGSwitchLayer.hxx
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGSWITCHLAYER_HXX
|
||||
#define FGSWITCHLAYER_HXX
|
||||
|
||||
#include "FGGroupLayer.hxx"
|
||||
|
||||
/**
|
||||
* A group layer that switches among its children.
|
||||
*
|
||||
* The first layer that passes its condition will be drawn, and
|
||||
* any following layers will be ignored.
|
||||
*/
|
||||
class FGSwitchLayer : public FGGroupLayer {
|
||||
public:
|
||||
// Transfer pointers!!
|
||||
FGSwitchLayer ();
|
||||
virtual void draw ();
|
||||
};
|
||||
|
||||
#endif
|
301
utils/fgpanel/FGTextLayer.cxx
Normal file
301
utils/fgpanel/FGTextLayer.cxx
Normal file
|
@ -0,0 +1,301 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGTextLayer.hxx"
|
||||
|
||||
SGPath FGTextLayer::The_Font_Path;
|
||||
|
||||
FGFontCache FGTextLayer::The_Font_Cache;
|
||||
|
||||
GLuint FGTextLayer::Text_Layer_Program_Object (0);
|
||||
GLint FGTextLayer::Text_Layer_Position_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Tex_Coord_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_MVP_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Sampler_Loc (0);
|
||||
GLint FGTextLayer::Text_Layer_Color_Loc (0);
|
||||
|
||||
bool
|
||||
FGTextLayer::Init () {
|
||||
const char V_Text_Layer_Shader_Str[] =
|
||||
#ifdef _GLES2
|
||||
"attribute vec4 a_position; \n"
|
||||
"attribute vec2 a_tex_coord; \n"
|
||||
#else
|
||||
"#version 330 \n"
|
||||
"in vec4 a_position; \n"
|
||||
"in vec2 a_tex_coord; \n"
|
||||
#endif
|
||||
"uniform mat4 u_mvp_matrix; \n"
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
"void main () { \n"
|
||||
" gl_Position = u_mvp_matrix * a_position; \n"
|
||||
" v_tex_coord = a_tex_coord; \n"
|
||||
"} \n";
|
||||
|
||||
const char F_Text_Layer_Shader_Str[] =
|
||||
#ifdef _GLES2
|
||||
"precision mediump float; \n"
|
||||
#endif
|
||||
"varying vec2 v_tex_coord; \n"
|
||||
"uniform sampler2D u_texture; \n"
|
||||
"uniform vec4 u_color; \n"
|
||||
"void main () { \n"
|
||||
" gl_FragColor = vec4 (1, 1, 1, \n"
|
||||
" texture2D (u_texture, v_tex_coord).a) * \n"
|
||||
" u_color; \n"
|
||||
"} \n";
|
||||
|
||||
Text_Layer_Program_Object = GL_utils::instance ().load_program (V_Text_Layer_Shader_Str,
|
||||
F_Text_Layer_Shader_Str);
|
||||
if (Text_Layer_Program_Object == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the attribute locations
|
||||
Text_Layer_Position_Loc = glGetAttribLocation (Text_Layer_Program_Object, "a_position");
|
||||
Text_Layer_Tex_Coord_Loc = glGetAttribLocation (Text_Layer_Program_Object, "a_tex_coord");
|
||||
|
||||
// Get the uniform locations
|
||||
Text_Layer_MVP_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_mvp_matrix");
|
||||
|
||||
// Get the sampler location
|
||||
Text_Layer_Sampler_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_texture");
|
||||
|
||||
// Get the color location
|
||||
Text_Layer_Color_Loc = glGetUniformLocation (Text_Layer_Program_Object, "u_color");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FGTextLayer::FGTextLayer (const int w, const int h) :
|
||||
FGInstrumentLayer (w, h),
|
||||
m_pointSize (0.0),
|
||||
m_font_name () {
|
||||
m_then.stamp ();
|
||||
m_color[0] = m_color[1] = m_color[2] = 0.0;
|
||||
m_color[3] = 1.0;
|
||||
}
|
||||
|
||||
FGTextLayer::~FGTextLayer () {
|
||||
for (chunk_list::iterator It = m_chunks.begin ();
|
||||
It != m_chunks.end ();
|
||||
++It) {
|
||||
delete *It;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::draw () {
|
||||
if (test ()) {
|
||||
glUseProgram (Text_Layer_Program_Object);
|
||||
glUniform4fv (Text_Layer_Color_Loc, 1, m_color);
|
||||
|
||||
transform ();
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Text_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
GLuint Glyph_Texture;
|
||||
if (!The_Font_Cache.Set_Font (m_font_name, m_pointSize, Glyph_Texture)) {
|
||||
SG_LOG (SG_COCKPIT, SG_ALERT, "Missing font : " << m_font_name << " " << m_pointSize);
|
||||
}
|
||||
|
||||
m_now.stamp ();
|
||||
const long diff ((m_now - m_then).toUSecs ());
|
||||
|
||||
if (diff > 100000 || diff < 0 ) {
|
||||
// ( diff < 0 ) is a sanity check and indicates our time stamp
|
||||
// difference math probably overflowed. We can handle a max
|
||||
// difference of 35.8 minutes since the returned value is in
|
||||
// usec. So if the panel is left off longer than that we can
|
||||
// over flow the math with it is turned back on. This (diff <
|
||||
// 0) catches that situation, get's us out of trouble, and
|
||||
// back on track.
|
||||
recalc_value ();
|
||||
m_then = m_now;
|
||||
}
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, Glyph_Texture);
|
||||
glUniform1i (Text_Layer_Sampler_Loc, 0);
|
||||
|
||||
int X (0);
|
||||
int Y (0);
|
||||
int Previous_X (0);
|
||||
int Previous_Y (0);
|
||||
int Left, Bottom, W, H;
|
||||
double X1, Y1, X2, Y2;
|
||||
|
||||
for (string::iterator It = m_value.begin (); It != m_value.end (); ++It) {
|
||||
if (The_Font_Cache.Get_Char (*It,
|
||||
X, Y,
|
||||
Left, Bottom,
|
||||
W, H,
|
||||
X1, Y1,
|
||||
X2, Y2)) {
|
||||
const GLfloat v_Vertices[] = {
|
||||
float (Previous_X + Left), float (Previous_Y + Bottom), 0.0f, // Position 0 (bottom left corner)
|
||||
float (X1), float (Y2), // TexCoord 0 (bottom left corner)
|
||||
float (Previous_X + Left + W), float (Previous_Y + Bottom), 0.0f, // Position 1 (bottom right corner)
|
||||
float (X2), float (Y2), // TexCoord 1 (bottom right corner)
|
||||
float (Previous_X + Left + W), float (Previous_Y + Bottom + H), 0.0f, // Position 2 (top right corner)
|
||||
float (X2), float (Y1), // TexCoord 2 (top right corner)
|
||||
float (Previous_X + Left), float (Previous_Y + Bottom + H), 0.0f, // Position 3 (top left corner)
|
||||
float (X1), float (Y1) }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Text_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices);
|
||||
glVertexAttribPointer (Text_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices[3]);
|
||||
|
||||
glEnableVertexAttribArray (Text_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Text_Layer_Tex_Coord_Loc);
|
||||
|
||||
const GLushort indices[] = {0, 1, 2, 0, 2, 3};
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
Previous_X = X;
|
||||
Previous_Y = Y;
|
||||
}
|
||||
}
|
||||
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::addChunk (FGTextLayer::Chunk * const chunk) {
|
||||
m_chunks.push_back (chunk);
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setColor (const float r,
|
||||
const float g,
|
||||
const float b) {
|
||||
m_color[0] = r;
|
||||
m_color[1] = g;
|
||||
m_color[2] = b;
|
||||
m_color[3] = 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setPointSize (const float size) {
|
||||
m_pointSize = size;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setFontName (const string &name) {
|
||||
if (The_Font_Path.isNull ()) {
|
||||
char *Env_Path = ::getenv ("FG_FONTS");
|
||||
if (Env_Path != NULL) {
|
||||
The_Font_Path = SGPath::fromEnv (Env_Path);
|
||||
} else {
|
||||
The_Font_Path = ApplicationProperties::GetRootPath ("Fonts");
|
||||
}
|
||||
}
|
||||
m_font_name = The_Font_Path.local8BitStr () + "/" + name + ".ttf";
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::recalc_value () const {
|
||||
m_value = "";
|
||||
for (chunk_list::const_iterator It = m_chunks.begin ();
|
||||
It != m_chunks.end ();
|
||||
++It) {
|
||||
m_value += (*It)->getValue ();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGTextLayer::Chunk.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGTextLayer::Chunk::Chunk (const string &text,
|
||||
const string &fmt) :
|
||||
m_type (FGTextLayer::TEXT),
|
||||
m_text (text),
|
||||
m_fmt (fmt),
|
||||
m_mult (1.0),
|
||||
m_offs (0.0),
|
||||
m_trunc (false) {
|
||||
if (m_fmt.empty ()) {
|
||||
m_fmt = "%s";
|
||||
}
|
||||
}
|
||||
|
||||
FGTextLayer::Chunk::Chunk (const ChunkType type,
|
||||
const SGPropertyNode *node,
|
||||
const string &fmt,
|
||||
const float mult,
|
||||
const float offs,
|
||||
const bool truncation) :
|
||||
m_type (type),
|
||||
m_node (node),
|
||||
m_fmt (fmt),
|
||||
m_mult (mult),
|
||||
m_offs (offs),
|
||||
m_trunc (truncation) {
|
||||
if (m_fmt.empty ()) {
|
||||
if (type == TEXT_VALUE) {
|
||||
m_fmt = "%s";
|
||||
} else {
|
||||
m_fmt = "%.2f";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
FGTextLayer::Chunk::getValue () const {
|
||||
if (test ()) {
|
||||
m_buf[0] = '\0';
|
||||
switch (m_type) {
|
||||
case TEXT:
|
||||
sprintf (m_buf, m_fmt.c_str (), m_text.c_str ());
|
||||
break;
|
||||
case TEXT_VALUE:
|
||||
sprintf (m_buf, m_fmt.c_str (), m_node->getStringValue ());
|
||||
break;
|
||||
case DOUBLE_VALUE:
|
||||
double d (m_offs + m_node->getFloatValue() * m_mult);
|
||||
if (m_trunc) {
|
||||
d = (d < 0) ? -floor (-d) : floor (d);
|
||||
}
|
||||
sprintf (m_buf, m_fmt.c_str(), d);
|
||||
break;
|
||||
}
|
||||
return m_buf;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
111
utils/fgpanel/FGTextLayer.hxx
Normal file
111
utils/fgpanel/FGTextLayer.hxx
Normal file
|
@ -0,0 +1,111 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGTEXTLAYER_HXX
|
||||
#define FGTEXTLAYER_HXX
|
||||
|
||||
#include <string>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
||||
#include "FGFontCache.hxx"
|
||||
#include "FGInstrumentLayer.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* A text layer of an instrument.
|
||||
*
|
||||
* This is a layer holding a string of static and/or generated text.
|
||||
* It is useful for instruments that have text displays, such as
|
||||
* a chronometer, GPS, or NavCom radio.
|
||||
*/
|
||||
|
||||
class FGTextLayer : public FGInstrumentLayer {
|
||||
public:
|
||||
enum ChunkType {
|
||||
TEXT,
|
||||
TEXT_VALUE,
|
||||
DOUBLE_VALUE
|
||||
};
|
||||
|
||||
class Chunk : public SGConditional {
|
||||
public:
|
||||
Chunk (const string &text,
|
||||
const string &fmt = "%s");
|
||||
Chunk (const ChunkType type,
|
||||
const SGPropertyNode *node,
|
||||
const string &fmt = "",
|
||||
const float mult = 1.0,
|
||||
const float offs = 0.0,
|
||||
const bool truncation = false);
|
||||
|
||||
const char *getValue () const;
|
||||
private:
|
||||
ChunkType m_type;
|
||||
string m_text;
|
||||
SGConstPropertyNode_ptr m_node;
|
||||
string m_fmt;
|
||||
float m_mult;
|
||||
float m_offs;
|
||||
bool m_trunc;
|
||||
mutable char m_buf[1024];
|
||||
|
||||
};
|
||||
|
||||
static bool Init ();
|
||||
|
||||
FGTextLayer (const int w = -1, const int h = -1);
|
||||
virtual ~FGTextLayer ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
// Transfer pointer!!
|
||||
virtual void addChunk (Chunk * const chunk);
|
||||
virtual void setColor (const float r,
|
||||
const float g,
|
||||
const float b);
|
||||
virtual void setPointSize (const float size);
|
||||
virtual void setFontName (const string &name);
|
||||
|
||||
private:
|
||||
|
||||
void recalc_value () const;
|
||||
|
||||
typedef vector<Chunk *> chunk_list;
|
||||
chunk_list m_chunks;
|
||||
float m_color[4];
|
||||
|
||||
float m_pointSize;
|
||||
static SGPath The_Font_Path;
|
||||
mutable string m_font_name;
|
||||
mutable string m_value;
|
||||
mutable SGTimeStamp m_then;
|
||||
mutable SGTimeStamp m_now;
|
||||
|
||||
static FGFontCache The_Font_Cache;
|
||||
|
||||
static GLuint Text_Layer_Program_Object;
|
||||
static GLint Text_Layer_Position_Loc;
|
||||
static GLint Text_Layer_Tex_Coord_Loc;
|
||||
static GLint Text_Layer_MVP_Loc;
|
||||
static GLint Text_Layer_Sampler_Loc;
|
||||
static GLint Text_Layer_Color_Loc;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -17,15 +17,25 @@
|
|||
//
|
||||
#ifndef __FGTEXTURELOADERINTERFACE_HXX
|
||||
#define __FGTEXTURELOADERINTERFACE_HXX
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
#include <string>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class FGTextureLoaderInterface {
|
||||
public:
|
||||
virtual GLuint loadTexture( const std::string & filename ) = 0;
|
||||
virtual GLuint loadTexture (const string &filename) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
124
utils/fgpanel/FGTexturedLayer.cxx
Normal file
124
utils/fgpanel/FGTexturedLayer.cxx
Normal file
|
@ -0,0 +1,124 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include "GL_utils.hxx"
|
||||
#include "FGTexturedLayer.hxx"
|
||||
|
||||
GLuint FGTexturedLayer::Textured_Layer_Program_Object (0);
|
||||
GLint FGTexturedLayer::Textured_Layer_Position_Loc (0);
|
||||
GLint FGTexturedLayer::Textured_Layer_Tex_Coord_Loc (0);
|
||||
GLint FGTexturedLayer::Textured_Layer_MVP_Loc (0);
|
||||
GLint FGTexturedLayer::Textured_Layer_Sampler_Loc (0);
|
||||
|
||||
void
|
||||
FGTexturedLayer::Init (const GLuint Program_Object,
|
||||
const GLint Position_Loc,
|
||||
const GLint Tex_Coord_Loc,
|
||||
const GLint MVP_Loc,
|
||||
const GLint Sampler_Loc) {
|
||||
Textured_Layer_Program_Object = Program_Object;
|
||||
Textured_Layer_Position_Loc = Position_Loc;
|
||||
Textured_Layer_Tex_Coord_Loc = Tex_Coord_Loc;
|
||||
Textured_Layer_MVP_Loc = MVP_Loc;
|
||||
Textured_Layer_Sampler_Loc = Sampler_Loc;
|
||||
}
|
||||
|
||||
FGTexturedLayer::FGTexturedLayer (const int w, const int h) :
|
||||
FGInstrumentLayer (w, h) {
|
||||
}
|
||||
|
||||
FGTexturedLayer::FGTexturedLayer (const FGCroppedTexture_ptr texture, const int w, const int h) :
|
||||
FGInstrumentLayer (w, h),
|
||||
m_texture (texture),
|
||||
m_emissive (false) {
|
||||
}
|
||||
|
||||
FGTexturedLayer::~FGTexturedLayer () {
|
||||
}
|
||||
|
||||
void
|
||||
FGTexturedLayer::draw () {
|
||||
if (test ()) {
|
||||
transform ();
|
||||
getDisplayList ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTexturedLayer::setTexture (const FGCroppedTexture_ptr texture) {
|
||||
m_texture = texture;
|
||||
}
|
||||
|
||||
FGCroppedTexture_ptr
|
||||
FGTexturedLayer::getTexture () const {
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
void
|
||||
FGTexturedLayer::setEmissive (const bool emissive) {
|
||||
m_emissive = emissive;
|
||||
}
|
||||
|
||||
void
|
||||
FGTexturedLayer::getDisplayList () {
|
||||
int w2 = m_w / 2;
|
||||
int h2 = m_h / 2;
|
||||
|
||||
glUseProgram (Textured_Layer_Program_Object);
|
||||
m_texture->bind (Textured_Layer_Sampler_Loc);
|
||||
const GLfloat v_Vertices[] = {
|
||||
float (-w2), float (-h2), 0.0f, // Position 0 (bottom left corner)
|
||||
m_texture->getMinX (), m_texture->getMinY (), // TexCoord 0 (bottom left corner)
|
||||
float ( w2), float (-h2), 0.0f, // Position 1 (bottom right corner)
|
||||
m_texture->getMaxX (), m_texture->getMinY (), // TexCoord 1 (bottom right corner)
|
||||
float ( w2), float ( h2), 0.0f, // Position 2 (top right corner)
|
||||
m_texture->getMaxX (), m_texture->getMaxY (), // TexCoord 2 (top right corner)
|
||||
float (-w2), float ( h2), 0.0f, // Position 3 (top left corner)
|
||||
m_texture->getMinX (), m_texture->getMaxY () }; // TexCoord 3 (top left corner)
|
||||
glVertexAttribPointer (Textured_Layer_Position_Loc,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
v_Vertices);
|
||||
glVertexAttribPointer (Textured_Layer_Tex_Coord_Loc,
|
||||
2,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
5 * sizeof (GLfloat),
|
||||
&v_Vertices[3]);
|
||||
|
||||
glEnableVertexAttribArray (Textured_Layer_Position_Loc);
|
||||
glEnableVertexAttribArray (Textured_Layer_Tex_Coord_Loc);
|
||||
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_PROJECTION);
|
||||
GL_utils::instance ().glPushMatrix ();
|
||||
GL_utils::instance ().glMultMatrixf
|
||||
(*reinterpret_cast <GLfloat (*)[4][4]>
|
||||
(GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_MODELVIEW)));
|
||||
glUniformMatrix4fv (Textured_Layer_MVP_Loc,
|
||||
1,
|
||||
GL_FALSE,
|
||||
GL_utils::instance ().get_top_matrix (GL_utils::GL_UTILS_PROJECTION));
|
||||
|
||||
const GLushort indices[] = {0, 1, 2, 0, 2, 3};
|
||||
glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
|
||||
GL_utils::instance ().glPopMatrix ();
|
||||
GL_utils::instance ().glMatrixMode (GL_utils::GL_UTILS_MODELVIEW);
|
||||
}
|
65
utils/fgpanel/FGTexturedLayer.hxx
Normal file
65
utils/fgpanel/FGTexturedLayer.hxx
Normal file
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef FGTEXTUREDLAYER_HXX
|
||||
#define FGTEXTUREDLAYER_HXX
|
||||
|
||||
#include "FGCroppedTexture.hxx"
|
||||
#include "FGInstrumentLayer.hxx"
|
||||
|
||||
/**
|
||||
* A textured layer of an instrument.
|
||||
*
|
||||
* This is a layer holding a single texture. Normally, the texture's
|
||||
* backgound should be transparent so that lower layers and the panel
|
||||
* background can show through.
|
||||
*/
|
||||
class FGTexturedLayer : public FGInstrumentLayer {
|
||||
public:
|
||||
static void Init (const GLuint Program_Object,
|
||||
const GLint Position_Loc,
|
||||
const GLint Tex_Coord_Loc,
|
||||
const GLint MVP_Loc,
|
||||
const GLint Sampler_Loc);
|
||||
|
||||
FGTexturedLayer (const int w = -1, const int h = -1);
|
||||
FGTexturedLayer (const FGCroppedTexture_ptr texture, const int w = -1, const int h = -1);
|
||||
virtual ~FGTexturedLayer ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
virtual void setTexture (const FGCroppedTexture_ptr texture);
|
||||
FGCroppedTexture_ptr getTexture () const;
|
||||
|
||||
void setEmissive (const bool emissive);
|
||||
|
||||
private:
|
||||
void getDisplayList ();
|
||||
|
||||
FGCroppedTexture_ptr m_texture;
|
||||
bool m_emissive;
|
||||
|
||||
static GLuint Textured_Layer_Program_Object;
|
||||
static GLint Textured_Layer_Position_Loc;
|
||||
static GLint Textured_Layer_Tex_Coord_Loc;
|
||||
static GLint Textured_Layer_MVP_Loc;
|
||||
static GLint Textured_Layer_Sampler_Loc;
|
||||
};
|
||||
|
||||
#endif
|
385
utils/fgpanel/GLES_utils.cxx
Normal file
385
utils/fgpanel/GLES_utils.cxx
Normal file
|
@ -0,0 +1,385 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef _RPI
|
||||
#include <bcm_host.h>
|
||||
#else
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#endif
|
||||
|
||||
#include "GLES_utils.hxx"
|
||||
|
||||
/// esCreateWindow flag - RGB color buffer
|
||||
#define GLES_UTILS_WINDOW_RGB 0
|
||||
/// esCreateWindow flag - ALPHA color buffer
|
||||
#define GLES_UTILS_WINDOW_ALPHA 1
|
||||
/// esCreateWindow flag - depth buffer
|
||||
#define GLES_UTILS_WINDOW_DEPTH 2
|
||||
/// esCreateWindow flag - stencil buffer
|
||||
#define GLES_UTILS_WINDOW_STENCIL 4
|
||||
/// esCreateWindow flat - multi-sample buffer
|
||||
#define GLES_UTILS_WINDOW_MULTISAMPLE 8
|
||||
|
||||
GLES_utils::GLES_utils () :
|
||||
m_State (),
|
||||
display_func (NULL),
|
||||
idle_func (NULL),
|
||||
keyboard_func (NULL),
|
||||
reshape_func (NULL) {}
|
||||
|
||||
GLES_utils::~GLES_utils () {}
|
||||
|
||||
GLES_utils&
|
||||
GLES_utils::instance () {
|
||||
static GLES_utils* const The_Instance (new GLES_utils);
|
||||
return *The_Instance;
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::init (const string &title) {
|
||||
#ifdef _RPI
|
||||
bcm_host_init ();
|
||||
init_dispmanx (m_State.native_window);
|
||||
#else
|
||||
init_display (m_State, title);
|
||||
#endif
|
||||
init_egl (m_State, GLES_UTILS_WINDOW_RGB);
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::print_config_info (const int n, const EGLDisplay &display, EGLConfig &config) {
|
||||
int size;
|
||||
|
||||
cout << "EGL Configuration " << n << " is" << endl;
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_RED_SIZE, &size);
|
||||
cout << "EGL Red size is " << size << endl;
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_BLUE_SIZE, &size);
|
||||
cout << "EGL Blue size is " << size << endl;
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_GREEN_SIZE, &size);
|
||||
cout << "EGL Green size is " << size << endl;
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_BUFFER_SIZE, &size);
|
||||
cout << "EGL Buffer size is " << size << endl;
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_BIND_TO_TEXTURE_RGB , &size);
|
||||
if (size == EGL_TRUE) {
|
||||
cout << "EGL Can be bound to RGB texture" << endl;
|
||||
} else {
|
||||
cout << "EGL Can't be bound to RGB texture" << endl;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib (display, config, EGL_BIND_TO_TEXTURE_RGBA , &size);
|
||||
if (size == EGL_TRUE) {
|
||||
cout << "EGL Can be bound to RGBA texture" << endl;
|
||||
} else {
|
||||
cout << "EGL Can't be bound to RGBA texture" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::init_egl (EGL_STATE_T &state, const GLuint flags) {
|
||||
EGLBoolean result;
|
||||
|
||||
static const EGLint attribute_list[] = {
|
||||
EGL_RED_SIZE, 5,
|
||||
EGL_GREEN_SIZE, 6,
|
||||
EGL_BLUE_SIZE, 5,
|
||||
EGL_ALPHA_SIZE, (flags & GLES_UTILS_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,
|
||||
EGL_DEPTH_SIZE, (flags & GLES_UTILS_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,
|
||||
EGL_STENCIL_SIZE, (flags & GLES_UTILS_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,
|
||||
EGL_SAMPLE_BUFFERS, (flags & GLES_UTILS_WINDOW_MULTISAMPLE) ? 1 : 0,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
static const EGLint context_attributes[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
#ifndef _RPI
|
||||
, EGL_NONE
|
||||
#endif
|
||||
};
|
||||
|
||||
EGLConfig *configs;
|
||||
|
||||
// get an EGL display connection
|
||||
#ifdef _RPI
|
||||
state.display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
|
||||
#else
|
||||
state.display = eglGetDisplay ((EGLNativeDisplayType) state.x_display);
|
||||
#endif
|
||||
assert (state.display != EGL_NO_DISPLAY);
|
||||
|
||||
// initialize the EGL display connection
|
||||
result = eglInitialize (state.display, &(state.major_version), &(state.minor_version));
|
||||
assert (result != EGL_FALSE);
|
||||
|
||||
result = eglGetConfigs (state.display, NULL, 0, &(state.num_configs));
|
||||
assert (result != EGL_FALSE);
|
||||
|
||||
configs = (EGLConfig *) calloc (state.num_configs, sizeof (*configs));
|
||||
result = eglGetConfigs (state.display, configs, state.num_configs, &(state.num_configs));
|
||||
assert (result != EGL_FALSE);
|
||||
|
||||
cout << "EGL version = " << state.major_version << "." << state.minor_version << endl;
|
||||
cout << "EGL has " << state.num_configs << " configs" << endl;
|
||||
for (int i = 0; i < state.num_configs; ++i) {
|
||||
print_config_info (i, state.display, configs[i]);
|
||||
}
|
||||
|
||||
// get an appropriate EGL frame buffer configuration
|
||||
result = eglChooseConfig (state.display, attribute_list, &(state.config), 1, &(state.num_configs));
|
||||
assert (result != EGL_FALSE);
|
||||
|
||||
// Choose the OpenGL ES API
|
||||
result = eglBindAPI (EGL_OPENGL_ES_API);
|
||||
assert (result != EGL_FALSE);
|
||||
|
||||
#ifdef _RPI
|
||||
state.surface = eglCreateWindowSurface (state.display,
|
||||
state.config,
|
||||
(EGLNativeWindowType) &(state.native_window),
|
||||
NULL);
|
||||
#else
|
||||
state.surface = eglCreateWindowSurface (state.display,
|
||||
state.config,
|
||||
state.native_window,
|
||||
NULL);
|
||||
#endif
|
||||
assert (state.surface != EGL_NO_SURFACE);
|
||||
|
||||
// create an EGL rendering context
|
||||
state.context = eglCreateContext (state.display, state.config, EGL_NO_CONTEXT, context_attributes);
|
||||
assert (state.context != EGL_NO_CONTEXT);
|
||||
|
||||
// connect the context to the surface
|
||||
result = eglMakeCurrent (state.display, state.surface, state.surface, state.context);
|
||||
assert (result != EGL_FALSE);
|
||||
}
|
||||
|
||||
#ifdef _RPI
|
||||
void
|
||||
GLES_utils::init_dispmanx (EGL_DISPMANX_WINDOW_T &native_window) {
|
||||
int32_t success = 0;
|
||||
uint32_t screen_width;
|
||||
uint32_t screen_height;
|
||||
|
||||
DISPMANX_ELEMENT_HANDLE_T dispman_element;
|
||||
DISPMANX_DISPLAY_HANDLE_T dispman_display;
|
||||
DISPMANX_UPDATE_HANDLE_T dispman_update;
|
||||
VC_RECT_T dst_rect;
|
||||
VC_RECT_T src_rect;
|
||||
|
||||
// create an EGL window surface
|
||||
success = graphics_get_display_size (0 /* LCD */,
|
||||
&screen_width,
|
||||
&screen_height);
|
||||
assert (success >= 0);
|
||||
|
||||
dst_rect.x = 0;
|
||||
dst_rect.y = 0;
|
||||
dst_rect.width = screen_width;
|
||||
dst_rect.height = screen_height;
|
||||
|
||||
src_rect.x = 0;
|
||||
src_rect.y = 0;
|
||||
src_rect.width = screen_width << 16;
|
||||
src_rect.height = screen_height << 16;
|
||||
|
||||
dispman_display = vc_dispmanx_display_open (0 /* LCD */);
|
||||
dispman_update = vc_dispmanx_update_start (0);
|
||||
|
||||
dispman_element = vc_dispmanx_element_add (dispman_update,
|
||||
dispman_display,
|
||||
0 /*layer*/,
|
||||
&dst_rect,
|
||||
0 /*src*/,
|
||||
&src_rect,
|
||||
DISPMANX_PROTECTION_NONE,
|
||||
0 /*alpha*/,
|
||||
0 /*clamp*/,
|
||||
DISPMANX_TRANSFORM_T (0) /*transform*/);
|
||||
|
||||
// Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window
|
||||
native_window.element = dispman_element;
|
||||
native_window.width = screen_width;
|
||||
native_window.height = screen_height;
|
||||
vc_dispmanx_update_submit_sync (dispman_update);
|
||||
|
||||
cout << "Got a Dispmanx window" << endl;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
GLES_utils::user_interrupt () {
|
||||
return GL_FALSE;
|
||||
}
|
||||
#else
|
||||
void
|
||||
GLES_utils::init_display (EGL_STATE_T &state, const string &title) {
|
||||
Window root;
|
||||
XSetWindowAttributes swa;
|
||||
XSetWindowAttributes xattr;
|
||||
Atom wm_state;
|
||||
XWMHints hints;
|
||||
XEvent xev;
|
||||
Window win;
|
||||
|
||||
state.width = 1024;
|
||||
state.height = 768;
|
||||
|
||||
/*
|
||||
* X11 native display initialization
|
||||
*/
|
||||
|
||||
state.x_display = XOpenDisplay (NULL);
|
||||
assert (state.x_display != NULL);
|
||||
|
||||
root = DefaultRootWindow (state.x_display);
|
||||
|
||||
swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask;
|
||||
win = XCreateWindow (state.x_display,
|
||||
root,
|
||||
0,
|
||||
0,
|
||||
state.width,
|
||||
state.height,
|
||||
0,
|
||||
CopyFromParent,
|
||||
InputOutput,
|
||||
CopyFromParent,
|
||||
CWEventMask,
|
||||
&swa);
|
||||
|
||||
xattr.override_redirect = false;
|
||||
XChangeWindowAttributes (state.x_display, win, CWOverrideRedirect, &xattr);
|
||||
|
||||
hints.input = true;
|
||||
hints.flags = InputHint;
|
||||
XSetWMHints (state.x_display, win, &hints);
|
||||
|
||||
// make the window visible on the screen
|
||||
XMapWindow (state.x_display, win);
|
||||
XStoreName (state.x_display, win, title.c_str ());
|
||||
|
||||
// get identifiers for the provided atom name strings
|
||||
wm_state = XInternAtom (state.x_display, "_NET_WM_STATE", false);
|
||||
|
||||
memset (&xev, 0, sizeof (xev));
|
||||
xev.type = ClientMessage;
|
||||
xev.xclient.window = win;
|
||||
xev.xclient.message_type = wm_state;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 1;
|
||||
xev.xclient.data.l[1] = false;
|
||||
XSendEvent (state.x_display, DefaultRootWindow (state.x_display), false, SubstructureNotifyMask, &xev);
|
||||
|
||||
state.native_window = (EGLNativeWindowType) win;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
GLES_utils::user_interrupt () {
|
||||
XEvent xev;
|
||||
KeySym key;
|
||||
GLboolean user_interrupt = GL_FALSE;
|
||||
char text;
|
||||
|
||||
// Pump all messages from X server. Keypresses are directed to keyfunc (if defined)
|
||||
while (XPending (m_State.x_display)) {
|
||||
XNextEvent (m_State.x_display, &xev);
|
||||
if (xev.type == KeyPress) {
|
||||
if (XLookupString (&xev.xkey, &text, 1, &key, 0) == 1) {
|
||||
if (keyboard_func != NULL) {
|
||||
keyboard_func (text, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xev.type == DestroyNotify) {
|
||||
user_interrupt = GL_TRUE;
|
||||
}
|
||||
}
|
||||
return user_interrupt;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
GLES_utils::register_display_func (void (*display_func) ()) {
|
||||
this->display_func = display_func;
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::register_idle_func (void (*idle_func) ()) {
|
||||
this->idle_func = idle_func;
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::register_keyboard_func (void (*keyboard_func) (unsigned char, int, int)) {
|
||||
this->keyboard_func = keyboard_func;
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::register_reshape_func (void (*reshape_func) (int, int)) {
|
||||
this->reshape_func = reshape_func;
|
||||
}
|
||||
|
||||
void
|
||||
GLES_utils::main_loop () {
|
||||
struct timeval t1, t2;
|
||||
struct timezone tz;
|
||||
float delta_time;
|
||||
float total_time = 0.0f;
|
||||
unsigned int frames = 0;
|
||||
|
||||
gettimeofday (&t1 , &tz);
|
||||
|
||||
while (user_interrupt () == GL_FALSE) {
|
||||
gettimeofday (&t2, &tz);
|
||||
delta_time = (float) (t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);
|
||||
t1 = t2;
|
||||
|
||||
if (reshape_func != NULL) {
|
||||
#ifdef _RPI
|
||||
reshape_func (m_State.native_window.width, m_State.native_window.height);
|
||||
#else
|
||||
reshape_func (m_State.width, m_State.height);
|
||||
#endif
|
||||
}
|
||||
if (idle_func != NULL) {
|
||||
idle_func ();
|
||||
}
|
||||
if (display_func != NULL) {
|
||||
display_func ();
|
||||
}
|
||||
|
||||
eglSwapBuffers (m_State.display, m_State.surface);
|
||||
|
||||
total_time += delta_time;
|
||||
++frames;
|
||||
if (total_time > 2.0f) {
|
||||
cout << frames << " frames rendered in " << total_time << " seconds -> FPS = " << (frames / total_time) << endl;
|
||||
total_time -= 2.0f;
|
||||
frames = 0;
|
||||
}
|
||||
}
|
||||
}
|
81
utils/fgpanel/GLES_utils.hxx
Normal file
81
utils/fgpanel/GLES_utils.hxx
Normal file
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef GLES_UTILS_HXX
|
||||
#define GLES_UTILS_HXX
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class GLES_utils : private boost::noncopyable {
|
||||
public:
|
||||
static GLES_utils& instance ();
|
||||
|
||||
void init (const string &title);
|
||||
|
||||
void register_display_func (void (*display_func) ());
|
||||
void register_idle_func (void (*idle_func) ());
|
||||
void register_keyboard_func (void (*keyboard_func) (unsigned char, int, int));
|
||||
void register_reshape_func (void (*reshape_func) (int, int));
|
||||
|
||||
void main_loop ();
|
||||
|
||||
private:
|
||||
explicit GLES_utils ();
|
||||
virtual ~GLES_utils ();
|
||||
|
||||
typedef struct {
|
||||
#ifdef _RPI
|
||||
EGL_DISPMANX_WINDOW_T native_window;
|
||||
#else
|
||||
EGLNativeWindowType native_window;
|
||||
Display *x_display;
|
||||
GLint width;
|
||||
GLint height;
|
||||
#endif
|
||||
EGLint major_version;
|
||||
EGLint minor_version;
|
||||
EGLint num_configs;
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
EGLConfig config;
|
||||
} EGL_STATE_T;
|
||||
|
||||
EGL_STATE_T m_State;
|
||||
|
||||
void (*display_func) ();
|
||||
void (*idle_func) ();
|
||||
void (*keyboard_func) (unsigned char, int, int);
|
||||
void (*reshape_func) (int, int);
|
||||
|
||||
void print_config_info (const int n, const EGLDisplay &display, EGLConfig &config);
|
||||
void init_egl (EGL_STATE_T &state, const GLuint flags);
|
||||
#ifdef _RPI
|
||||
void init_dispmanx (EGL_DISPMANX_WINDOW_T &native_window);
|
||||
#else
|
||||
void init_display (EGL_STATE_T &state, const string &title);
|
||||
#endif
|
||||
GLboolean user_interrupt ();
|
||||
};
|
||||
|
||||
#endif
|
374
utils/fgpanel/GL_utils.cxx
Normal file
374
utils/fgpanel/GL_utils.cxx
Normal file
|
@ -0,0 +1,374 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "GL_utils.hxx"
|
||||
|
||||
const float PI (3.1415926535897932384626433832795);
|
||||
|
||||
GL_utils::GL_utils () {
|
||||
Matrix Tmp;
|
||||
memset (&Tmp, 0x0, sizeof (Matrix));
|
||||
int i;
|
||||
for (i = GL_UTILS_MODELVIEW; i < GL_UTILS_LAST; ++i) {
|
||||
m_Current_Matrix_Mode = (GLenum_Mode) i;
|
||||
m_Matrix[m_Current_Matrix_Mode].push (Tmp);
|
||||
glLoadIdentity ();
|
||||
}
|
||||
m_Current_Matrix_Mode = GL_utils::GL_UTILS_UNSET;
|
||||
}
|
||||
|
||||
GL_utils::~GL_utils () {}
|
||||
|
||||
GL_utils&
|
||||
GL_utils::instance () {
|
||||
static GL_utils* const The_Instance (new GL_utils);
|
||||
return *The_Instance;
|
||||
}
|
||||
|
||||
//
|
||||
///
|
||||
/// \brief Load a shader, check for compile errors, print error messages to std error
|
||||
/// \param type Type of shader (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER)
|
||||
/// \param shader_src Shader source string
|
||||
/// \return A new shader object on success, 0 on failure
|
||||
//
|
||||
GLuint
|
||||
GL_utils::load_shader (GLenum type, const char *shader_src) {
|
||||
GLint compiled;
|
||||
|
||||
// Create the shader object
|
||||
GLuint shader (glCreateShader (type));
|
||||
|
||||
if (shader == 0) {
|
||||
cerr << "Error creating shader" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load the shader source
|
||||
glShaderSource (shader, 1, &shader_src, NULL);
|
||||
|
||||
// Compile the shader
|
||||
glCompileShader (shader);
|
||||
|
||||
// Check the compile status
|
||||
glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled);
|
||||
|
||||
if (!compiled) {
|
||||
GLint info_len (0);
|
||||
|
||||
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &info_len);
|
||||
|
||||
if (info_len > 1) {
|
||||
char* info_log ((char *) malloc (sizeof (char) * info_len));
|
||||
|
||||
glGetShaderInfoLog (shader, info_len, NULL, info_log);
|
||||
cerr << "Error compiling shader:" << endl << info_log << endl;
|
||||
|
||||
free (info_log);
|
||||
}
|
||||
|
||||
glDeleteShader (shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
//
|
||||
///
|
||||
/// \brief Load a vertex and fragment shader, create a program object, link program.
|
||||
// Errors output to std error.
|
||||
/// \param vertShaderSrc Vertex shader source code
|
||||
/// \param fragShaderSrc Fragment shader source code
|
||||
/// \return A new program object linked with the vertex/fragment shader pair, 0 on failure
|
||||
//
|
||||
GLuint
|
||||
GL_utils::load_program (const char *vert_shader_src, const char *frag_shader_src) {
|
||||
GLint linked;
|
||||
|
||||
// Load the vertex/fragment shaders
|
||||
GLuint vertex_shader (load_shader (GL_VERTEX_SHADER, vert_shader_src));
|
||||
if (vertex_shader == 0) {
|
||||
cerr << "Error loading vertex shader" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint fragment_shader (load_shader (GL_FRAGMENT_SHADER, frag_shader_src));
|
||||
if (fragment_shader == 0) {
|
||||
cerr << "Error loading fragment shader" << endl;
|
||||
glDeleteShader (vertex_shader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create the program object
|
||||
GLuint program_object (glCreateProgram ());
|
||||
|
||||
if (program_object == 0) {
|
||||
cerr << "Error creating program" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
glAttachShader (program_object, vertex_shader);
|
||||
glAttachShader (program_object, fragment_shader);
|
||||
|
||||
// Link the program
|
||||
glLinkProgram (program_object);
|
||||
|
||||
// Check the link status
|
||||
glGetProgramiv (program_object, GL_LINK_STATUS, &linked);
|
||||
|
||||
if (!linked) {
|
||||
GLint info_len (0);
|
||||
|
||||
glGetProgramiv (program_object, GL_INFO_LOG_LENGTH, &info_len);
|
||||
|
||||
if (info_len > 1) {
|
||||
char* info_log ((char *) malloc (sizeof (char) * info_len));
|
||||
|
||||
glGetProgramInfoLog (program_object, info_len, NULL, info_log);
|
||||
cerr << "Error linking program:" << endl << info_log << endl;
|
||||
|
||||
free (info_log);
|
||||
}
|
||||
|
||||
glDeleteProgram (program_object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free up no longer needed shader resources
|
||||
glDeleteShader (vertex_shader);
|
||||
glDeleteShader (fragment_shader);
|
||||
|
||||
return program_object;
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glMatrixMode (const GLenum_Mode mode) {
|
||||
if (mode < GL_UTILS_LAST) {
|
||||
m_Current_Matrix_Mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glLoadIdentity () {
|
||||
if (m_Current_Matrix_Mode < GL_UTILS_LAST) {
|
||||
memset (&(m_Matrix[m_Current_Matrix_Mode].top ()), 0x0, sizeof (Matrix));
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[0][0] = 1.0f;
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[1][1] = 1.0f;
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[2][2] = 1.0f;
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[3][3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::gluOrtho2D (const GLfloat left,
|
||||
const GLfloat right,
|
||||
const GLfloat bottom,
|
||||
const GLfloat top) {
|
||||
GL_utils::glOrtho (left, right, bottom, top, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glOrtho (const GLfloat left,
|
||||
const GLfloat right,
|
||||
const GLfloat bottom,
|
||||
const GLfloat top,
|
||||
const GLfloat nearVal,
|
||||
const GLfloat farVal) {
|
||||
const GLfloat Delta_X (right - left);
|
||||
const GLfloat Delta_Y (top - bottom);
|
||||
const GLfloat Delta_Z (farVal - nearVal);
|
||||
Matrix Ortho;
|
||||
|
||||
if ((Delta_X == 0.0f) || (Delta_Y == 0.0f) || (Delta_Z == 0.0f) || (m_Current_Matrix_Mode < GL_UTILS_LAST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset (&Ortho, 0x0, sizeof (Matrix));
|
||||
Ortho.m[0][0] = 2.0f / Delta_X;
|
||||
Ortho.m[3][0] = -(right + left) / Delta_X;
|
||||
Ortho.m[1][1] = 2.0f / Delta_Y;
|
||||
Ortho.m[3][1] = -(top + bottom) / Delta_Y;
|
||||
Ortho.m[2][2] = -2.0f / Delta_Z;
|
||||
Ortho.m[3][2] = -(nearVal + farVal) / Delta_Z;
|
||||
Ortho.m[3][3] = 1.0f;
|
||||
|
||||
GL_utils::glMultMatrixf (Ortho.m);
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glTranslatef (const GLfloat x, const GLfloat y, const GLfloat z) {
|
||||
if (m_Current_Matrix_Mode < GL_UTILS_LAST) {
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[3][0] += (m_Matrix[m_Current_Matrix_Mode].top ().m[0][0] * x +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[1][0] * y +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[2][0] * z);
|
||||
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[3][1] += (m_Matrix[m_Current_Matrix_Mode].top ().m[0][1] * x +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[1][1] * y +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[2][1] * z);
|
||||
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[3][2] += (m_Matrix[m_Current_Matrix_Mode].top ().m[0][2] * x +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[1][2] * y +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[2][2] * z);
|
||||
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[3][3] += (m_Matrix[m_Current_Matrix_Mode].top ().m[0][3] * x +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[1][3] * y +
|
||||
m_Matrix[m_Current_Matrix_Mode].top ().m[2][3] * z);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glRotatef (const GLfloat angle, const GLfloat x, const GLfloat y, const GLfloat z) {
|
||||
const GLfloat xx (x * x);
|
||||
const GLfloat yy (y * y);
|
||||
const GLfloat zz (z * z);
|
||||
const GLfloat Mag (sqrtf (xx + yy + zz));
|
||||
|
||||
if ((Mag > 0.0f) && (m_Current_Matrix_Mode < GL_UTILS_LAST)) {
|
||||
const GLfloat Sin_Angle (sinf (-angle * PI / 180.0f));
|
||||
const GLfloat Cos_Angle (cosf (angle * PI / 180.0f));
|
||||
const GLfloat xy (x * y);
|
||||
const GLfloat yz (y * z);
|
||||
const GLfloat zx (z * x);
|
||||
const GLfloat xs (x * Sin_Angle);
|
||||
const GLfloat ys (y * Sin_Angle);
|
||||
const GLfloat zs (z * Sin_Angle);
|
||||
const GLfloat One_Minus_Cos (1.0f - Cos_Angle);
|
||||
Matrix Rot;
|
||||
|
||||
// x /= mag;
|
||||
// y /= mag;
|
||||
// z /= mag;
|
||||
|
||||
Rot.m[0][0] = (One_Minus_Cos * xx) + Cos_Angle;
|
||||
Rot.m[0][1] = (One_Minus_Cos * xy) - zs;
|
||||
Rot.m[0][2] = (One_Minus_Cos * zx) + ys;
|
||||
Rot.m[0][3] = 0.0f;
|
||||
|
||||
Rot.m[1][0] = (One_Minus_Cos * xy) + zs;
|
||||
Rot.m[1][1] = (One_Minus_Cos * yy) + Cos_Angle;
|
||||
Rot.m[1][2] = (One_Minus_Cos * yz) - xs;
|
||||
Rot.m[1][3] = 0.0f;
|
||||
|
||||
Rot.m[2][0] = (One_Minus_Cos * zx) - ys;
|
||||
Rot.m[2][1] = (One_Minus_Cos * yz) + xs;
|
||||
Rot.m[2][2] = (One_Minus_Cos * zz) + Cos_Angle;
|
||||
Rot.m[2][3] = 0.0f;
|
||||
|
||||
Rot.m[3][0] = 0.0f;
|
||||
Rot.m[3][1] = 0.0f;
|
||||
Rot.m[3][2] = 0.0f;
|
||||
Rot.m[3][3] = 1.0f;
|
||||
|
||||
GL_utils::glMultMatrixf (Rot.m);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glScalef (GLfloat x, GLfloat y, GLfloat z) {
|
||||
if (m_Current_Matrix_Mode < GL_UTILS_LAST) {
|
||||
Matrix Scale;
|
||||
Scale.m[0][0] = x;
|
||||
Scale.m[0][1] = 0.0f;
|
||||
Scale.m[0][2] = 0.0f;
|
||||
Scale.m[0][3] = 0.0f;
|
||||
|
||||
Scale.m[1][0] = 0.0f;
|
||||
Scale.m[1][1] = y;
|
||||
Scale.m[1][2] = 0.0f;
|
||||
Scale.m[1][3] = 0.0f;
|
||||
|
||||
Scale.m[2][0] = 0.0f;
|
||||
Scale.m[2][1] = 0.0f;
|
||||
Scale.m[2][2] = z;
|
||||
Scale.m[2][3] = 0.0f;
|
||||
|
||||
Scale.m[3][0] = 0.0f;
|
||||
Scale.m[3][1] = 0.0f;
|
||||
Scale.m[3][2] = 0.0f;
|
||||
Scale.m[3][3] = 1.0f;
|
||||
|
||||
GL_utils::glMultMatrixf (Scale.m);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glMultMatrixf (const GLfloat m[4][4]) {
|
||||
Matrix Tmp;
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
Tmp.m[i][0] = (m[i][0] * m_Matrix[m_Current_Matrix_Mode].top ().m[0][0] +
|
||||
m[i][1] * m_Matrix[m_Current_Matrix_Mode].top ().m[1][0] +
|
||||
m[i][2] * m_Matrix[m_Current_Matrix_Mode].top ().m[2][0] +
|
||||
m[i][3] * m_Matrix[m_Current_Matrix_Mode].top ().m[3][0]);
|
||||
|
||||
Tmp.m[i][1] = (m[i][0] * m_Matrix[m_Current_Matrix_Mode].top ().m[0][1] +
|
||||
m[i][1] * m_Matrix[m_Current_Matrix_Mode].top ().m[1][1] +
|
||||
m[i][2] * m_Matrix[m_Current_Matrix_Mode].top ().m[2][1] +
|
||||
m[i][3] * m_Matrix[m_Current_Matrix_Mode].top ().m[3][1]);
|
||||
|
||||
Tmp.m[i][2] = (m[i][0] * m_Matrix[m_Current_Matrix_Mode].top ().m[0][2] +
|
||||
m[i][1] * m_Matrix[m_Current_Matrix_Mode].top ().m[1][2] +
|
||||
m[i][2] * m_Matrix[m_Current_Matrix_Mode].top ().m[2][2] +
|
||||
m[i][3] * m_Matrix[m_Current_Matrix_Mode].top ().m[3][2]);
|
||||
|
||||
Tmp.m[i][3] = (m[i][0] * m_Matrix[m_Current_Matrix_Mode].top ().m[0][3] +
|
||||
m[i][1] * m_Matrix[m_Current_Matrix_Mode].top ().m[1][3] +
|
||||
m[i][2] * m_Matrix[m_Current_Matrix_Mode].top ().m[2][3] +
|
||||
m[i][3] * m_Matrix[m_Current_Matrix_Mode].top ().m[3][3]);
|
||||
}
|
||||
memcpy (&(m_Matrix[m_Current_Matrix_Mode].top ()), &Tmp, sizeof (Matrix));
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glPushMatrix () {
|
||||
if (m_Current_Matrix_Mode < GL_UTILS_LAST) {
|
||||
m_Matrix[m_Current_Matrix_Mode].push (m_Matrix[m_Current_Matrix_Mode].top ());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::glPopMatrix () {
|
||||
if (m_Current_Matrix_Mode < GL_UTILS_LAST) {
|
||||
m_Matrix[m_Current_Matrix_Mode].pop ();
|
||||
}
|
||||
}
|
||||
|
||||
GLfloat*
|
||||
GL_utils::get_top_matrix (const GL_utils::GLenum_Mode mode) {
|
||||
if (mode < GL_UTILS_LAST) {
|
||||
return &(m_Matrix[mode].top ().m[0][0]);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GL_utils::Debug (const GL_utils::GLenum_Mode mode) const {
|
||||
if (mode < GL_UTILS_LAST) {
|
||||
for (int l = 0; l < 4; ++l) {
|
||||
cout << " ";
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
cout << m_Matrix[mode].top ().m[c][l] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
}
|
85
utils/fgpanel/GL_utils.hxx
Normal file
85
utils/fgpanel/GL_utils.hxx
Normal file
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef GL_UTILS_HXX
|
||||
#define GL_UTILS_HXX
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <stack>
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <OpenGL/gl.h>
|
||||
#elif defined (_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#else
|
||||
#include <GL/glew.h> // Must be included before <GL/gl.h>
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
class GL_utils : private boost::noncopyable {
|
||||
public:
|
||||
static GL_utils& instance ();
|
||||
|
||||
enum GLenum_Mode {
|
||||
GL_UTILS_MODELVIEW,
|
||||
GL_UTILS_PROJECTION,
|
||||
GL_UTILS_TEXTURE,
|
||||
GL_UTILS_COLOR,
|
||||
GL_UTILS_LAST,
|
||||
GL_UTILS_UNSET
|
||||
};
|
||||
|
||||
GLuint load_program (const char *vert_shader_src, const char *frag_shader_src);
|
||||
|
||||
void glMatrixMode (const GL_utils::GLenum_Mode mode);
|
||||
void glLoadIdentity ();
|
||||
void gluOrtho2D (const GLfloat left,
|
||||
const GLfloat right,
|
||||
const GLfloat bottom,
|
||||
const GLfloat top);
|
||||
void glOrtho (const GLfloat left,
|
||||
const GLfloat right,
|
||||
const GLfloat bottom,
|
||||
const GLfloat top,
|
||||
const GLfloat nearVal,
|
||||
const GLfloat farVal);
|
||||
void glTranslatef (const GLfloat x, const GLfloat y, const GLfloat z);
|
||||
void glRotatef (const GLfloat angle, const GLfloat x, const GLfloat y, const GLfloat z);
|
||||
void glScalef (const GLfloat x, const GLfloat y, const GLfloat z);
|
||||
// C' = C X M
|
||||
void glMultMatrixf (const GLfloat m[4][4]);
|
||||
void glPushMatrix ();
|
||||
void glPopMatrix ();
|
||||
GLfloat* get_top_matrix (const GL_utils::GLenum_Mode mode);
|
||||
void Debug (const GL_utils::GLenum_Mode mode) const;
|
||||
|
||||
private:
|
||||
explicit GL_utils ();
|
||||
virtual ~GL_utils ();
|
||||
|
||||
GLuint load_shader (GLenum type, const char *shader_src);
|
||||
|
||||
typedef struct {
|
||||
GLfloat m[4][4];
|
||||
} Matrix;
|
||||
|
||||
stack <Matrix> m_Matrix[GL_UTILS_LAST];
|
||||
GLenum_Mode m_Current_Matrix_Mode;
|
||||
};
|
||||
|
||||
#endif
|
44
utils/fgpanel/README.RPi
Normal file
44
utils/fgpanel/README.RPi
Normal file
|
@ -0,0 +1,44 @@
|
|||
This is the FGPanel for the Raspberry Pi running Raspbian.
|
||||
It should work with other Linux distributions but it has not been tested.
|
||||
|
||||
INSTALLATION
|
||||
============
|
||||
|
||||
1. Build SimGear as usual.
|
||||
OSG, Plib, GLUT,... will be required even they are not strictly needed to run FGPanel.
|
||||
|
||||
2. Configure FlightGear using CMake as usual.
|
||||
CMakeLists.txt is used to compile FGPanel with OpenGL 2.0.
|
||||
This should make FGPanel faster on modern graphics cards.
|
||||
|
||||
CMakeLists.txt is used to compile FGPanel with OpenGL ES 2.0 for the Raspberry Pi.
|
||||
The source code of FGPanel can easily be adapted to other embedded devices supporting OpenGL ES 2.0.
|
||||
|
||||
3. Build FGPanel only (don't build all components on the Raspberry Pi as this will take ages!!!):
|
||||
make -- fgpanel
|
||||
|
||||
USAGE
|
||||
=====
|
||||
|
||||
1. Increase the amount of GPU memory by editing the /boot/config.txt file.
|
||||
Add the following line (this is for Raspberry Pi model 1B with 512 Mb of memory):
|
||||
gpu_mem_512=256
|
||||
|
||||
2. Reboot and check the amount of GPU memory:
|
||||
vcgencmd get_mem gpu
|
||||
|
||||
3. Stop X server. FGPanel runs in the console (Linux framebuffer).
|
||||
|
||||
4. Start FGPanel as usual but as ROOT or use the 'sudo' command (see README):
|
||||
sudo -- utils/fgpanel/fgpanel --fg-root=/path/to/fg/data --panel=Aircraft/MyAircraft/Panels/MyPanel.xml
|
||||
|
||||
ROOT privileges are required to access the GPU of the Raspberry Pi.
|
||||
|
||||
FEATURES
|
||||
========
|
||||
|
||||
- Use OpenGL 2.0 instead of OpenGL 1.0 (fixed pipeline) using CMakeLists.txt.
|
||||
- Use OpenGL ES 2.0 to run on the Raspberry Pi using CMakeLists.txt.
|
||||
- Use VideoCore 4 graphics hardware acceleration (GPU) of the Raspberry Pi.
|
||||
- Run at 30 frames per second.
|
||||
- Don't use PLib anymore for the font rendering.
|
|
@ -5,7 +5,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -17,14 +17,14 @@
|
|||
//
|
||||
#include "FGPanelApplication.hxx"
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
int
|
||||
main (int argc, char ** argv) {
|
||||
try {
|
||||
FGPanelApplication app(argc,argv);
|
||||
app.Run();
|
||||
FGPanelApplication app (argc,argv);
|
||||
app.Run ();
|
||||
return 0;
|
||||
}
|
||||
catch( ... ) {
|
||||
catch (...) {
|
||||
cerr << "Sorry, your program terminated." << endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,971 +0,0 @@
|
|||
// panel.cxx - default, 2D single-engine prop instrument panel
|
||||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id: panel.cxx,v 1.44 2006/09/05 20:28:48 curt Exp $
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> // sprintf
|
||||
#include <string.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#if defined (SG_MAC)
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
|
||||
#include <plib/fnt.h>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include "panel.hxx"
|
||||
#include "ApplicationProperties.hxx"
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Local functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FGDummyTextureLoader : public FGTextureLoaderInterface {
|
||||
public:
|
||||
virtual GLuint loadTexture( const string & filename );
|
||||
};
|
||||
|
||||
GLuint FGDummyTextureLoader::loadTexture( const string & filename )
|
||||
{
|
||||
GLuint _texture = 0;
|
||||
glGenTextures( 1, &_texture );
|
||||
glBindTexture( GL_TEXTURE_2D, _texture );
|
||||
|
||||
// glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
|
||||
// glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) ;
|
||||
// glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ) ;
|
||||
// glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ) ;
|
||||
// glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ) ;
|
||||
|
||||
GLubyte image[ 2 * 2 * 3 ] ;
|
||||
|
||||
/* Red and white chequerboard */
|
||||
image [ 0 ] = 255 ; image [ 1 ] = 0 ; image [ 2 ] = 0 ;
|
||||
image [ 3 ] = 255 ; image [ 4 ] = 255 ; image [ 5 ] = 255 ;
|
||||
image [ 6 ] = 255 ; image [ 7 ] = 255 ; image [ 8 ] = 255 ;
|
||||
image [ 9 ] = 255 ; image [ 10] = 0 ; image [ 11] = 0 ;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, 2, 2, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image);
|
||||
|
||||
return _texture;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGCropped Texture.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLuint FGCroppedTexture::current_bound_texture = 0;
|
||||
map<string,GLuint> FGCroppedTexture::cache;
|
||||
map<string,FGTextureLoaderInterface*> FGCroppedTexture::textureLoader;
|
||||
static FGDummyTextureLoader dummyTextureLoader;
|
||||
|
||||
FGCroppedTexture::FGCroppedTexture (const string &path,
|
||||
float minX, float minY,
|
||||
float maxX, float maxY)
|
||||
: _path(path),
|
||||
_minX(minX), _minY(minY), _maxX(maxX), _maxY(maxY), _texture(0)
|
||||
{
|
||||
}
|
||||
|
||||
FGCroppedTexture::~FGCroppedTexture ()
|
||||
{
|
||||
}
|
||||
|
||||
void FGCroppedTexture::bind( bool doGLBind )
|
||||
{
|
||||
if( _texture == 0 ) {
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "First bind of texture " << _path );
|
||||
if( cache.count(_path) > 0 ) {
|
||||
_texture = cache[_path];
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Using texture " << _path << " from cache (#" << _texture << ")" );
|
||||
} else {
|
||||
SGPath tpath = ApplicationProperties::GetRootPath(_path.c_str());
|
||||
string extension = tpath.extension();
|
||||
FGTextureLoaderInterface * loader = &dummyTextureLoader;
|
||||
if( textureLoader.count( extension ) == 0 ) {
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Can't handle textures of type " << extension );
|
||||
} else {
|
||||
loader = textureLoader[extension];
|
||||
}
|
||||
|
||||
_texture = loader->loadTexture( tpath.local8BitStr() );
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Texture " << tpath << " loaded from file as #" << _texture );
|
||||
|
||||
cache[_path] = _texture;
|
||||
}
|
||||
}
|
||||
|
||||
if( !doGLBind || current_bound_texture == _texture )
|
||||
return;
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, _texture );
|
||||
current_bound_texture = _texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGPanel.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
FGPanel::FGPanel ( SGPropertyNode_ptr root)
|
||||
: _root(root),
|
||||
_flipx(root->getNode("/sim/panel/flip-x", true)),
|
||||
_rotate(root->getNode("/sim/panel/rotate-deg", true)),
|
||||
_bg_width(1.0), _bg_height(1.0),
|
||||
initDisplayList(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
FGPanel::~FGPanel ()
|
||||
{
|
||||
for (instrument_list_type::iterator it = _instruments.begin();
|
||||
it != _instruments.end();
|
||||
it++) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an instrument to the panel.
|
||||
*/
|
||||
void
|
||||
FGPanel::addInstrument (FGPanelInstrument * instrument)
|
||||
{
|
||||
_instruments.push_back(instrument);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the panel.
|
||||
*/
|
||||
void
|
||||
FGPanel::init ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind panel properties.
|
||||
*/
|
||||
void
|
||||
FGPanel::bind ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unbind panel properties.
|
||||
*/
|
||||
void
|
||||
FGPanel::unbind ()
|
||||
{
|
||||
}
|
||||
|
||||
GLuint FGPanel::getInitDisplayList()
|
||||
{
|
||||
if( initDisplayList != 0 ) return initDisplayList;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if ( _flipx->getBoolValue() ) {
|
||||
gluOrtho2D( _width, 0, _height, 0 ); /* up side down */
|
||||
} else {
|
||||
gluOrtho2D( 0, _width, 0, _height ); /* right side up */
|
||||
}
|
||||
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glClear( GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// save some state
|
||||
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT
|
||||
| GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE
|
||||
| GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Draw the background
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if (_bg != NULL) {
|
||||
_bg->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);
|
||||
glTexCoord2f(_bg_width, 0.0); glVertex2f(_width, 0);
|
||||
glTexCoord2f(_bg_width, _bg_height); glVertex2f(_width, _height);
|
||||
glTexCoord2f(0.0, _bg_height); glVertex2f(0, _height);
|
||||
glEnd();
|
||||
} else if( _mbg[0] != NULL ) {
|
||||
for (int i = 0; i < 4; i ++) {
|
||||
// top row of textures...(1,3,5,7)
|
||||
_mbg[i*2]->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(i*_width/4, _height/2);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f((i+1)*_width/4, _height/2);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f((i+1)*_width/4, _height);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(i*_width/4, _height);
|
||||
glEnd();
|
||||
// bottom row of textures...(2,4,6,8)
|
||||
_mbg[i*2+1]->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f( i*_width/4, 0);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f( (i+1)*_width/4, 0);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f( (i+1)*_width/4, _height/2);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f( i*_width/4, _height/2);
|
||||
glEnd();
|
||||
}
|
||||
} else {
|
||||
float c[4];
|
||||
glGetFloatv( GL_CURRENT_COLOR, c );
|
||||
glColor4f( 0.0, 0.0, 0.0, 1.0 );
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(_width, 0);
|
||||
glVertex2f(_width, _height);
|
||||
glVertex2f(0, _height);
|
||||
glEnd();
|
||||
glColor4fv( c );
|
||||
}
|
||||
|
||||
|
||||
return initDisplayList;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::update (double dt)
|
||||
{
|
||||
/*glCallList*/(getInitDisplayList());
|
||||
|
||||
// Draw the instruments.
|
||||
// Syd Adams: added instrument clipping
|
||||
instrument_list_type::const_iterator current = _instruments.begin();
|
||||
instrument_list_type::const_iterator end = _instruments.end();
|
||||
|
||||
GLdouble blx[4]={1.0,0.0,0.0,0.0};
|
||||
GLdouble bly[4]={0.0,1.0,0.0,0.0};
|
||||
GLdouble urx[4]={-1.0,0.0,0.0,0.0};
|
||||
GLdouble ury[4]={0.0,-1.0,0.0,0.0};
|
||||
|
||||
for ( ; current != end; current++) {
|
||||
FGPanelInstrument * instr = *current;
|
||||
glPushMatrix();
|
||||
glTranslated(instr->getXPos(), instr->getYPos(), 0);
|
||||
|
||||
int ix= instr->getWidth();
|
||||
int iy= instr->getHeight();
|
||||
glPushMatrix();
|
||||
glTranslated(-ix/2,-iy/2,0);
|
||||
glClipPlane(GL_CLIP_PLANE0,blx);
|
||||
glClipPlane(GL_CLIP_PLANE1,bly);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
glEnable(GL_CLIP_PLANE1);
|
||||
|
||||
glTranslated(ix,iy,0);
|
||||
glClipPlane(GL_CLIP_PLANE2,urx);
|
||||
glClipPlane(GL_CLIP_PLANE3,ury);
|
||||
glEnable(GL_CLIP_PLANE2);
|
||||
glEnable(GL_CLIP_PLANE3);
|
||||
glPopMatrix();
|
||||
instr->draw();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
|
||||
// restore some original state
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Update the panel.
|
||||
*/
|
||||
void
|
||||
FGPanel::update (double dt)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
if ( _flipx->getBoolValue() ) {
|
||||
gluOrtho2D( _width, 0, _height, 0 ); /* up side down */
|
||||
} else {
|
||||
gluOrtho2D( 0, _width, 0, _height ); /* right side up */
|
||||
}
|
||||
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
void FGPanel::draw()
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// save some state
|
||||
glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT
|
||||
| GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE
|
||||
| GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Draw the background
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if (_bg != NULL) {
|
||||
_bg->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(0, 0);
|
||||
glTexCoord2f(_bg_width, 0.0); glVertex2f(_width, 0);
|
||||
glTexCoord2f(_bg_width, _bg_height); glVertex2f(_width, _height);
|
||||
glTexCoord2f(0.0, _bg_height); glVertex2f(0, _height);
|
||||
glEnd();
|
||||
} else if( _mbg[0] != NULL ) {
|
||||
for (int i = 0; i < 4; i ++) {
|
||||
// top row of textures...(1,3,5,7)
|
||||
_mbg[i*2]->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(i*_width/4, _height/2);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f((i+1)*_width/4, _height/2);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f((i+1)*_width/4, _height);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f(i*_width/4, _height);
|
||||
glEnd();
|
||||
// bottom row of textures...(2,4,6,8)
|
||||
_mbg[i*2+1]->bind();
|
||||
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f( i*_width/4, 0);
|
||||
glTexCoord2f(1.0, 0.0); glVertex2f( (i+1)*_width/4, 0);
|
||||
glTexCoord2f(1.0, 1.0); glVertex2f( (i+1)*_width/4, _height/2);
|
||||
glTexCoord2f(0.0, 1.0); glVertex2f( i*_width/4, _height/2);
|
||||
glEnd();
|
||||
}
|
||||
} else {
|
||||
float c[4];
|
||||
glGetFloatv( GL_CURRENT_COLOR, c );
|
||||
glColor4f( 0.0, 0.0, 0.0, 1.0 );
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(_width, 0);
|
||||
glVertex2f(_width, _height);
|
||||
glVertex2f(0, _height);
|
||||
glEnd();
|
||||
glColor4fv( c );
|
||||
}
|
||||
|
||||
// Draw the instruments.
|
||||
// Syd Adams: added instrument clipping
|
||||
instrument_list_type::const_iterator current = _instruments.begin();
|
||||
instrument_list_type::const_iterator end = _instruments.end();
|
||||
|
||||
GLdouble blx[4]={1.0,0.0,0.0,0.0};
|
||||
GLdouble bly[4]={0.0,1.0,0.0,0.0};
|
||||
GLdouble urx[4]={-1.0,0.0,0.0,0.0};
|
||||
GLdouble ury[4]={0.0,-1.0,0.0,0.0};
|
||||
|
||||
for ( ; current != end; current++) {
|
||||
FGPanelInstrument * instr = *current;
|
||||
glPushMatrix();
|
||||
glTranslated(instr->getXPos(), instr->getYPos(), 0);
|
||||
|
||||
int ix= instr->getWidth();
|
||||
int iy= instr->getHeight();
|
||||
glPushMatrix();
|
||||
glTranslated(-ix/2,-iy/2,0);
|
||||
glClipPlane(GL_CLIP_PLANE0,blx);
|
||||
glClipPlane(GL_CLIP_PLANE1,bly);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
glEnable(GL_CLIP_PLANE1);
|
||||
|
||||
glTranslated(ix,iy,0);
|
||||
glClipPlane(GL_CLIP_PLANE2,urx);
|
||||
glClipPlane(GL_CLIP_PLANE3,ury);
|
||||
glEnable(GL_CLIP_PLANE2);
|
||||
glEnable(GL_CLIP_PLANE3);
|
||||
glPopMatrix();
|
||||
instr->draw();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
glDisable(GL_CLIP_PLANE1);
|
||||
glDisable(GL_CLIP_PLANE2);
|
||||
glDisable(GL_CLIP_PLANE3);
|
||||
|
||||
// restore some original state
|
||||
glPopAttrib();
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set the panel's background texture.
|
||||
*/
|
||||
void
|
||||
FGPanel::setBackground (FGCroppedTexture_ptr texture)
|
||||
{
|
||||
_bg = texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the panel's multiple background textures.
|
||||
*/
|
||||
void
|
||||
FGPanel::setMultiBackground (FGCroppedTexture_ptr texture, int idx)
|
||||
{
|
||||
_bg = 0;
|
||||
_mbg[idx] = texture;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGPanelTransformation.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGPanelTransformation::FGPanelTransformation ()
|
||||
: table(0)
|
||||
{
|
||||
}
|
||||
|
||||
FGPanelTransformation::~FGPanelTransformation ()
|
||||
{
|
||||
delete table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGPanelInstrument.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FGPanelInstrument::FGPanelInstrument ()
|
||||
{
|
||||
setPosition(0, 0);
|
||||
setSize(0, 0);
|
||||
}
|
||||
|
||||
FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
|
||||
{
|
||||
setPosition(x, y);
|
||||
setSize(w, h);
|
||||
}
|
||||
|
||||
FGPanelInstrument::~FGPanelInstrument ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FGPanelInstrument::setPosition (int x, int y)
|
||||
{
|
||||
_x = x;
|
||||
_y = y;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanelInstrument::setSize (int w, int h)
|
||||
{
|
||||
_w = w;
|
||||
_h = h;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getXPos () const
|
||||
{
|
||||
return _x;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getYPos () const
|
||||
{
|
||||
return _y;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getWidth () const
|
||||
{
|
||||
return _w;
|
||||
}
|
||||
|
||||
int
|
||||
FGPanelInstrument::getHeight () const
|
||||
{
|
||||
return _h;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGLayeredInstrument.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
|
||||
: FGPanelInstrument(x, y, w, h)
|
||||
{
|
||||
}
|
||||
|
||||
FGLayeredInstrument::~FGLayeredInstrument ()
|
||||
{
|
||||
for (layer_list::iterator it = _layers.begin(); it != _layers.end(); it++) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGLayeredInstrument::draw ()
|
||||
{
|
||||
if (!test())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < (int)_layers.size(); i++) {
|
||||
glPushMatrix();
|
||||
_layers[i]->draw();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
|
||||
{
|
||||
int n = _layers.size();
|
||||
if (layer->getWidth() == -1) {
|
||||
layer->setWidth(getWidth());
|
||||
}
|
||||
if (layer->getHeight() == -1) {
|
||||
layer->setHeight(getHeight());
|
||||
}
|
||||
_layers.push_back(layer);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
FGLayeredInstrument::addLayer (FGCroppedTexture_ptr texture, int w, int h)
|
||||
{
|
||||
return addLayer(new FGTexturedLayer(texture, w, h));
|
||||
}
|
||||
|
||||
void
|
||||
FGLayeredInstrument::addTransformation (FGPanelTransformation * transformation)
|
||||
{
|
||||
int layer = _layers.size() - 1;
|
||||
_layers[layer]->addTransformation(transformation);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGInstrumentLayer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGInstrumentLayer::FGInstrumentLayer (int w, int h)
|
||||
: _w(w),
|
||||
_h(h)
|
||||
{
|
||||
}
|
||||
|
||||
FGInstrumentLayer::~FGInstrumentLayer ()
|
||||
{
|
||||
for (transformation_list::iterator it = _transformations.begin();
|
||||
it != _transformations.end();
|
||||
it++) {
|
||||
delete *it;
|
||||
*it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::transform () const
|
||||
{
|
||||
transformation_list::const_iterator it = _transformations.begin();
|
||||
transformation_list::const_iterator last = _transformations.end();
|
||||
while (it != last) {
|
||||
FGPanelTransformation *t = *it;
|
||||
if (t->test()) {
|
||||
float val = (t->node == 0 ? 0.0 : t->node->getFloatValue());
|
||||
|
||||
if (t->has_mod)
|
||||
val = fmod(val, t->mod);
|
||||
if (val < t->min) {
|
||||
val = t->min;
|
||||
} else if (val > t->max) {
|
||||
val = t->max;
|
||||
}
|
||||
|
||||
if (t->table==0) {
|
||||
val = val * t->factor + t->offset;
|
||||
} else {
|
||||
val = t->table->interpolate(val) * t->factor + t->offset;
|
||||
}
|
||||
|
||||
switch (t->type) {
|
||||
case FGPanelTransformation::XSHIFT:
|
||||
glTranslatef(val, 0.0, 0.0);
|
||||
break;
|
||||
case FGPanelTransformation::YSHIFT:
|
||||
glTranslatef(0.0, val, 0.0);
|
||||
break;
|
||||
case FGPanelTransformation::ROTATION:
|
||||
glRotatef(-val, 0.0, 0.0, 1.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGInstrumentLayer::addTransformation (FGPanelTransformation * transformation)
|
||||
{
|
||||
_transformations.push_back(transformation);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGGroupLayer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGGroupLayer::FGGroupLayer ()
|
||||
{
|
||||
}
|
||||
|
||||
FGGroupLayer::~FGGroupLayer ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _layers.size(); i++)
|
||||
delete _layers[i];
|
||||
}
|
||||
|
||||
void
|
||||
FGGroupLayer::draw ()
|
||||
{
|
||||
if (test()) {
|
||||
transform();
|
||||
int nLayers = _layers.size();
|
||||
for (int i = 0; i < nLayers; i++)
|
||||
_layers[i]->draw( );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGGroupLayer::addLayer (FGInstrumentLayer * layer)
|
||||
{
|
||||
_layers.push_back(layer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGTexturedLayer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FGTexturedLayer::FGTexturedLayer (FGCroppedTexture_ptr texture, int w, int h)
|
||||
: FGInstrumentLayer(w, h),
|
||||
_emissive(false),
|
||||
displayList(0)
|
||||
{
|
||||
setTexture(texture);
|
||||
}
|
||||
|
||||
|
||||
FGTexturedLayer::~FGTexturedLayer ()
|
||||
{
|
||||
}
|
||||
|
||||
GLuint
|
||||
FGTexturedLayer::getDisplayList()
|
||||
{
|
||||
if( displayList != 0 )
|
||||
return displayList;
|
||||
|
||||
int w2 = _w / 2;
|
||||
int h2 = _h / 2;
|
||||
|
||||
_texture->bind( false );
|
||||
displayList = glGenLists(1);
|
||||
glNewList(displayList,GL_COMPILE_AND_EXECUTE);
|
||||
glBindTexture( GL_TEXTURE_2D, _texture->getTexture() );
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(_texture->getMinX(), _texture->getMinY()); glVertex2f(-w2, -h2);
|
||||
glTexCoord2f(_texture->getMaxX(), _texture->getMinY()); glVertex2f(w2, -h2);
|
||||
glTexCoord2f(_texture->getMaxX(), _texture->getMaxY()); glVertex2f(w2, h2);
|
||||
glTexCoord2f(_texture->getMinX(), _texture->getMaxY()); glVertex2f(-w2, h2);
|
||||
glEnd();
|
||||
glEndList();
|
||||
|
||||
return displayList;
|
||||
}
|
||||
|
||||
void
|
||||
FGTexturedLayer::draw ( )
|
||||
{
|
||||
if (test()) {
|
||||
transform();
|
||||
glCallList(getDisplayList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGTextLayer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
fntRenderer FGTextLayer::text_renderer;
|
||||
|
||||
FGTextLayer::FGTextLayer (int w, int h)
|
||||
: FGInstrumentLayer(w, h), _pointSize(14.0), _font_name("Helvetica.txf")
|
||||
{
|
||||
_then.stamp();
|
||||
_color[0] = _color[1] = _color[2] = 0.0;
|
||||
_color[3] = 1.0;
|
||||
}
|
||||
|
||||
FGTextLayer::~FGTextLayer ()
|
||||
{
|
||||
chunk_list::iterator it = _chunks.begin();
|
||||
chunk_list::iterator last = _chunks.end();
|
||||
for ( ; it != last; it++) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::draw ()
|
||||
{
|
||||
if (test()) {
|
||||
float c[4];
|
||||
glGetFloatv( GL_CURRENT_COLOR, c );
|
||||
glColor4fv(_color);
|
||||
transform();
|
||||
|
||||
text_renderer.setFont(ApplicationProperties::fontCache.getTexFont(_font_name.c_str()));
|
||||
if (!text_renderer.getFont())
|
||||
{
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Missing font file: " << _font_name );
|
||||
return;
|
||||
}
|
||||
|
||||
text_renderer.setPointSize(_pointSize);
|
||||
text_renderer.begin();
|
||||
text_renderer.start3f(0, 0, 0);
|
||||
|
||||
_now.stamp();
|
||||
long diff = (_now - _then).toUSecs();
|
||||
|
||||
if (diff > 100000 || diff < 0 ) {
|
||||
// ( diff < 0 ) is a sanity check and indicates our time stamp
|
||||
// difference math probably overflowed. We can handle a max
|
||||
// difference of 35.8 minutes since the returned value is in
|
||||
// usec. So if the panel is left off longer than that we can
|
||||
// over flow the math with it is turned back on. This (diff <
|
||||
// 0) catches that situation, get's us out of trouble, and
|
||||
// back on track.
|
||||
recalc_value();
|
||||
_then = _now;
|
||||
}
|
||||
|
||||
// Something is goofy. The code in this file renders only CCW
|
||||
// polygons, and I have verified that the font code in plib
|
||||
// renders only CCW trianbles. Yet they come out backwards.
|
||||
// Something around here or in plib is either changing the winding
|
||||
// order or (more likely) pushing a left-handed matrix onto the
|
||||
// stack. But I can't find it; get out the chainsaw...
|
||||
glFrontFace(GL_CW);
|
||||
text_renderer.puts((char *)(_value.c_str()));
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
text_renderer.end();
|
||||
glColor4fv( c );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
|
||||
{
|
||||
_chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setColor (float r, float g, float b)
|
||||
{
|
||||
_color[0] = r;
|
||||
_color[1] = g;
|
||||
_color[2] = b;
|
||||
_color[3] = 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setPointSize (float size)
|
||||
{
|
||||
_pointSize = size;
|
||||
}
|
||||
|
||||
void
|
||||
FGTextLayer::setFontName(const string &name)
|
||||
{
|
||||
_font_name = name + ".txf";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FGTextLayer::setFont(fntFont * font)
|
||||
{
|
||||
FGTextLayer::text_renderer.setFont(font);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FGTextLayer::recalc_value () const
|
||||
{
|
||||
_value = "";
|
||||
chunk_list::const_iterator it = _chunks.begin();
|
||||
chunk_list::const_iterator last = _chunks.end();
|
||||
for ( ; it != last; it++) {
|
||||
_value += (*it)->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGTextLayer::Chunk.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGTextLayer::Chunk::Chunk (const string &text, const string &fmt)
|
||||
: _type(FGTextLayer::TEXT), _fmt(fmt)
|
||||
{
|
||||
_text = text;
|
||||
if (_fmt.empty())
|
||||
_fmt = "%s";
|
||||
}
|
||||
|
||||
FGTextLayer::Chunk::Chunk (ChunkType type, const SGPropertyNode * node,
|
||||
const string &fmt, float mult, float offs,
|
||||
bool truncation)
|
||||
: _type(type), _fmt(fmt), _mult(mult), _offs(offs), _trunc(truncation)
|
||||
{
|
||||
if (_fmt.empty()) {
|
||||
if (type == TEXT_VALUE)
|
||||
_fmt = "%s";
|
||||
else
|
||||
_fmt = "%.2f";
|
||||
}
|
||||
_node = node;
|
||||
}
|
||||
|
||||
const char *
|
||||
FGTextLayer::Chunk::getValue () const
|
||||
{
|
||||
if (test()) {
|
||||
_buf[0] = '\0';
|
||||
switch (_type) {
|
||||
case TEXT:
|
||||
sprintf(_buf, _fmt.c_str(), _text.c_str());
|
||||
return _buf;
|
||||
case TEXT_VALUE:
|
||||
sprintf(_buf, _fmt.c_str(), _node->getStringValue());
|
||||
break;
|
||||
case DOUBLE_VALUE:
|
||||
double d = _offs + _node->getFloatValue() * _mult;
|
||||
if (_trunc) d = (d < 0) ? -floor(-d) : floor(d);
|
||||
sprintf(_buf, _fmt.c_str(), d);
|
||||
break;
|
||||
}
|
||||
return _buf;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGSwitchLayer.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FGSwitchLayer::FGSwitchLayer ()
|
||||
: FGGroupLayer()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
FGSwitchLayer::draw ()
|
||||
{
|
||||
if (test()) {
|
||||
transform();
|
||||
int nLayers = _layers.size();
|
||||
for (int i = 0; i < nLayers; i++) {
|
||||
if (_layers[i]->test()) {
|
||||
_layers[i]->draw();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end of panel.cxx
|
|
@ -1,452 +0,0 @@
|
|||
// panel.hxx - generic support classes for a 2D panel.
|
||||
//
|
||||
// Written by David Megginson, started January 2000.
|
||||
// Adopted for standalone fgpanel application by Torsten Dreyer, August 2009
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#ifndef __PANEL_HXX
|
||||
#define __PANEL_HXX
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <plib/fnt.h>
|
||||
|
||||
#include <simgear/props/propsfwd.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include "FGTextureLoaderInterface.hxx"
|
||||
|
||||
class FGPanelInstrument;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Texture management.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FGCroppedTexture;
|
||||
typedef SGSharedPtr<FGCroppedTexture> FGCroppedTexture_ptr;
|
||||
/**
|
||||
* Cropped texture (should migrate out into FGFS).
|
||||
*
|
||||
* This structure wraps an SSG texture with cropping information.
|
||||
*/
|
||||
class FGCroppedTexture : public SGReferenced
|
||||
{
|
||||
public:
|
||||
FGCroppedTexture (const string &path,
|
||||
float _minX = 0.0, float _minY = 0.0,
|
||||
float _maxX = 1.0, float _maxY = 1.0);
|
||||
|
||||
virtual ~FGCroppedTexture ();
|
||||
|
||||
virtual void setPath (const string &path) { _path = path; }
|
||||
|
||||
virtual const string &getPath () const { return _path; }
|
||||
|
||||
virtual void setCrop (float minX, float minY, float maxX, float maxY) {
|
||||
_minX = minX; _minY = minY; _maxX = maxX; _maxY = maxY;
|
||||
}
|
||||
|
||||
static void registerTextureLoader( const string & extension, FGTextureLoaderInterface * loader ) {
|
||||
if( textureLoader.count( extension ) == 0 )
|
||||
textureLoader[extension] = loader;
|
||||
}
|
||||
|
||||
virtual float getMinX () const { return _minX; }
|
||||
virtual float getMinY () const { return _minY; }
|
||||
virtual float getMaxX () const { return _maxX; }
|
||||
virtual float getMaxY () const { return _maxY; }
|
||||
GLuint getTexture() const { return _texture; }
|
||||
|
||||
virtual void bind( bool doGLBind = true );
|
||||
|
||||
private:
|
||||
string _path;
|
||||
float _minX, _minY, _maxX, _maxY;
|
||||
|
||||
GLuint _texture;
|
||||
static GLuint current_bound_texture;
|
||||
static map<string,GLuint> cache;
|
||||
static map<string,FGTextureLoaderInterface*> textureLoader;
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Top-level panel.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Instrument panel class.
|
||||
*
|
||||
* The panel is a container that has a background texture and holds
|
||||
* zero or more instruments. The panel will order the instruments to
|
||||
* redraw themselves when necessary, and will pass mouse clicks on to
|
||||
* the appropriate instruments for processing.
|
||||
*/
|
||||
class FGPanel : public SGSubsystem
|
||||
{
|
||||
public:
|
||||
|
||||
FGPanel ( SGPropertyNode_ptr root );
|
||||
virtual ~FGPanel ();
|
||||
|
||||
// Update the panel (every frame).
|
||||
virtual void init ();
|
||||
virtual void bind ();
|
||||
virtual void unbind ();
|
||||
// virtual void draw ();
|
||||
virtual void update (double dt);
|
||||
|
||||
// transfer pointer ownership!!!
|
||||
virtual void addInstrument (FGPanelInstrument * instrument);
|
||||
|
||||
// Background texture.
|
||||
virtual void setBackground (FGCroppedTexture_ptr texture);
|
||||
inline void setBackgroundWidth( double d ) {
|
||||
_bg_width = d;
|
||||
}
|
||||
|
||||
inline void setBackgroundHeight( double d ) {
|
||||
_bg_height = d;
|
||||
}
|
||||
|
||||
// Background multiple textures.
|
||||
virtual void setMultiBackground (FGCroppedTexture_ptr texture , int idx);
|
||||
|
||||
// Full width of panel.
|
||||
virtual void setWidth (int width) { _width = width; }
|
||||
virtual int getWidth () const { return _width; }
|
||||
|
||||
// Full height of panel.
|
||||
virtual void setHeight (int height) { _height = height; }
|
||||
virtual int getHeight () const { return _height; }
|
||||
|
||||
private:
|
||||
|
||||
typedef vector<FGPanelInstrument *> instrument_list_type;
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
SGPropertyNode_ptr _root;
|
||||
SGPropertyNode_ptr _flipx;
|
||||
SGPropertyNode_ptr _rotate;
|
||||
|
||||
FGCroppedTexture_ptr _bg;
|
||||
double _bg_width;
|
||||
double _bg_height;
|
||||
FGCroppedTexture_ptr _mbg[8];
|
||||
// List of instruments in panel.
|
||||
instrument_list_type _instruments;
|
||||
|
||||
GLuint initDisplayList;
|
||||
|
||||
GLuint getInitDisplayList();
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Transformations.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A transformation for a layer.
|
||||
*/
|
||||
class FGPanelTransformation : public SGConditional
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
XSHIFT,
|
||||
YSHIFT,
|
||||
ROTATION
|
||||
};
|
||||
|
||||
FGPanelTransformation ();
|
||||
virtual ~FGPanelTransformation ();
|
||||
|
||||
Type type;
|
||||
SGConstPropertyNode_ptr node;
|
||||
float min;
|
||||
float max;
|
||||
bool has_mod;
|
||||
float mod;
|
||||
float factor;
|
||||
float offset;
|
||||
SGInterpTable * table;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Layers
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A single layer of a multi-layered instrument.
|
||||
*
|
||||
* Each layer can be subject to a series of transformations based
|
||||
* on current FGFS instrument readings: for example, a texture
|
||||
* representing a needle can rotate to show the airspeed.
|
||||
*/
|
||||
class FGInstrumentLayer : public SGConditional
|
||||
{
|
||||
public:
|
||||
|
||||
FGInstrumentLayer (int w = -1, int h = -1);
|
||||
virtual ~FGInstrumentLayer ();
|
||||
|
||||
virtual void draw () = 0;
|
||||
virtual void transform () const;
|
||||
|
||||
virtual int getWidth () const { return _w; }
|
||||
virtual int getHeight () const { return _h; }
|
||||
virtual void setWidth (int w) { _w = w; }
|
||||
virtual void setHeight (int h) { _h = h; }
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
// DEPRECATED
|
||||
virtual void addTransformation (FGPanelTransformation * transformation);
|
||||
|
||||
protected:
|
||||
int _w, _h;
|
||||
|
||||
typedef vector<FGPanelTransformation *> transformation_list;
|
||||
transformation_list _transformations;
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Instruments.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class for a panel instrument.
|
||||
*
|
||||
* A panel instrument consists of zero or more actions, associated
|
||||
* with mouse clicks in rectangular areas. Currently, the only
|
||||
* concrete class derived from this is FGLayeredInstrument, but others
|
||||
* may show up in the future (some complex instruments could be
|
||||
* entirely hand-coded, for example).
|
||||
*/
|
||||
class FGPanelInstrument : public SGConditional
|
||||
{
|
||||
public:
|
||||
FGPanelInstrument ();
|
||||
FGPanelInstrument (int x, int y, int w, int h);
|
||||
virtual ~FGPanelInstrument ();
|
||||
|
||||
virtual void draw () = 0;
|
||||
|
||||
virtual void setPosition(int x, int y);
|
||||
virtual void setSize(int w, int h);
|
||||
|
||||
virtual int getXPos () const;
|
||||
virtual int getYPos () const;
|
||||
virtual int getWidth () const;
|
||||
virtual int getHeight () const;
|
||||
|
||||
protected:
|
||||
int _x, _y, _w, _h;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instrument constructed of multiple layers.
|
||||
*
|
||||
* Each individual layer can be rotated or shifted to correspond
|
||||
* to internal FGFS instrument readings.
|
||||
*/
|
||||
class FGLayeredInstrument : public FGPanelInstrument
|
||||
{
|
||||
public:
|
||||
FGLayeredInstrument (int x, int y, int w, int h);
|
||||
virtual ~FGLayeredInstrument ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
virtual int addLayer (FGInstrumentLayer *layer);
|
||||
virtual int addLayer (FGCroppedTexture_ptr texture, int w = -1, int h = -1);
|
||||
|
||||
// Transfer pointer ownership!!
|
||||
virtual void addTransformation (FGPanelTransformation * transformation);
|
||||
|
||||
protected:
|
||||
typedef vector<FGInstrumentLayer *> layer_list;
|
||||
layer_list _layers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instrument layer containing a group of sublayers.
|
||||
*
|
||||
* This class is useful for gathering together a group of related
|
||||
* layers, either to hold in an external file or to work under
|
||||
* the same condition.
|
||||
*/
|
||||
class FGGroupLayer : public FGInstrumentLayer
|
||||
{
|
||||
public:
|
||||
FGGroupLayer ();
|
||||
virtual ~FGGroupLayer ();
|
||||
virtual void draw ();
|
||||
// transfer pointer ownership
|
||||
virtual void addLayer (FGInstrumentLayer * layer);
|
||||
protected:
|
||||
vector<FGInstrumentLayer *> _layers;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A textured layer of an instrument.
|
||||
*
|
||||
* This is a layer holding a single texture. Normally, the texture's
|
||||
* backgound should be transparent so that lower layers and the panel
|
||||
* background can show through.
|
||||
*/
|
||||
class FGTexturedLayer : public FGInstrumentLayer
|
||||
{
|
||||
public:
|
||||
FGTexturedLayer (int w = -1, int h = -1) : FGInstrumentLayer(w, h) {}
|
||||
FGTexturedLayer (FGCroppedTexture_ptr texture, int w = -1, int h = -1);
|
||||
virtual ~FGTexturedLayer ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
virtual void setTexture (FGCroppedTexture_ptr texture) {
|
||||
_texture = texture;
|
||||
}
|
||||
FGCroppedTexture_ptr getTexture() { return _texture; }
|
||||
|
||||
void setEmissive(bool e) { _emissive = e; }
|
||||
|
||||
private:
|
||||
GLuint getDisplayList();
|
||||
|
||||
FGCroppedTexture_ptr _texture;
|
||||
bool _emissive;
|
||||
GLuint displayList;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A text layer of an instrument.
|
||||
*
|
||||
* This is a layer holding a string of static and/or generated text.
|
||||
* It is useful for instruments that have text displays, such as
|
||||
* a chronometer, GPS, or NavCom radio.
|
||||
*/
|
||||
class FGTextLayer : public FGInstrumentLayer
|
||||
{
|
||||
public:
|
||||
enum ChunkType {
|
||||
TEXT,
|
||||
TEXT_VALUE,
|
||||
DOUBLE_VALUE
|
||||
};
|
||||
|
||||
class Chunk : public SGConditional
|
||||
{
|
||||
public:
|
||||
Chunk (const string &text, const string &fmt = "%s");
|
||||
Chunk (ChunkType type, const SGPropertyNode * node,
|
||||
const string &fmt = "", float mult = 1.0, float offs = 0.0,
|
||||
bool truncation = false);
|
||||
|
||||
const char * getValue () const;
|
||||
private:
|
||||
ChunkType _type;
|
||||
string _text;
|
||||
SGConstPropertyNode_ptr _node;
|
||||
string _fmt;
|
||||
float _mult;
|
||||
float _offs;
|
||||
bool _trunc;
|
||||
mutable char _buf[1024];
|
||||
|
||||
};
|
||||
|
||||
FGTextLayer (int w = -1, int h = -1);
|
||||
virtual ~FGTextLayer ();
|
||||
|
||||
virtual void draw ();
|
||||
|
||||
// Transfer pointer!!
|
||||
virtual void addChunk (Chunk * chunk);
|
||||
virtual void setColor (float r, float g, float b);
|
||||
virtual void setPointSize (float size);
|
||||
virtual void setFontName ( const string &name );
|
||||
virtual void setFont (fntFont * font);
|
||||
|
||||
private:
|
||||
|
||||
void recalc_value () const;
|
||||
|
||||
typedef vector<Chunk *> chunk_list;
|
||||
chunk_list _chunks;
|
||||
float _color[4];
|
||||
|
||||
float _pointSize;
|
||||
mutable string _font_name;
|
||||
mutable string _value;
|
||||
mutable SGTimeStamp _then;
|
||||
mutable SGTimeStamp _now;
|
||||
|
||||
static fntRenderer text_renderer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A group layer that switches among its children.
|
||||
*
|
||||
* The first layer that passes its condition will be drawn, and
|
||||
* any following layers will be ignored.
|
||||
*/
|
||||
class FGSwitchLayer : public FGGroupLayer
|
||||
{
|
||||
public:
|
||||
// Transfer pointers!!
|
||||
FGSwitchLayer ();
|
||||
virtual void draw ();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // __PANEL_HXX
|
||||
|
||||
// end of panel.hxx
|
||||
|
||||
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -16,17 +16,17 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id: panel_io.cxx,v 1.26 2006/08/10 11:12:39 mfranz Exp $
|
||||
// $Id: panel_io.cxx,v 1.3 2016/08/25 23:41:34 allaert Exp $
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string.h> // for strcmp()
|
||||
#include <string.h> // for strcmp()
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
@ -36,9 +36,13 @@
|
|||
#include <simgear/props/condition.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include "panel.hxx"
|
||||
#include "panel_io.hxx"
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "FGGroupLayer.hxx"
|
||||
#include "FGLayeredInstrument.hxx"
|
||||
#include "FGSwitchLayer.hxx"
|
||||
#include "FGTextLayer.hxx"
|
||||
#include "FGTexturedLayer.hxx"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,7 +60,7 @@
|
|||
//
|
||||
// A layer contains zero or more transformations.
|
||||
//
|
||||
// Some special types of layers also contain other objects, such as
|
||||
// Some special types of layers also contain other objects, such as
|
||||
// chunks of text or other layers.
|
||||
//
|
||||
// There are currently four types of layers:
|
||||
|
@ -96,14 +100,13 @@
|
|||
* texture, x1=0.0, y1=0.0, x2=0.5, y2=0.5.
|
||||
*/
|
||||
static FGCroppedTexture_ptr
|
||||
readTexture (const SGPropertyNode * node)
|
||||
{
|
||||
return new FGCroppedTexture(node->getStringValue("path"),
|
||||
node->getFloatValue("x1"),
|
||||
node->getFloatValue("y1"),
|
||||
node->getFloatValue("x2", 1.0),
|
||||
node->getFloatValue("y2", 1.0));
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Read texture " << node->getName());
|
||||
readTexture (const SGPropertyNode *node) {
|
||||
return new FGCroppedTexture (node->getStringValue ("path"),
|
||||
node->getFloatValue ("x1"),
|
||||
node->getFloatValue ("y1"),
|
||||
node->getFloatValue ("x2", 1.0),
|
||||
node->getFloatValue ("y2", 1.0));
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Read texture " << node->getName ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,17 +118,15 @@ readTexture (const SGPropertyNode * node)
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
readConditions (SGConditional *component, const SGPropertyNode *node)
|
||||
{
|
||||
const SGPropertyNode * conditionNode = node->getChild("condition");
|
||||
if (conditionNode != 0)
|
||||
// The top level is implicitly AND
|
||||
component->setCondition(sgReadCondition(ApplicationProperties::Properties,
|
||||
conditionNode) );
|
||||
;
|
||||
readConditions (SGConditional *component, const SGPropertyNode *node) {
|
||||
const SGPropertyNode * conditionNode (node->getChild ("condition"));
|
||||
if (conditionNode != 0) {
|
||||
// The top level is implicitly AND
|
||||
component->setCondition (sgReadCondition (ApplicationProperties::Properties,
|
||||
conditionNode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read a transformation from the instrument's property list.
|
||||
*
|
||||
|
@ -152,91 +153,90 @@ readConditions (SGConditional *component, const SGPropertyNode *node)
|
|||
* appear to be applied backwards.
|
||||
*/
|
||||
static FGPanelTransformation *
|
||||
readTransformation (const SGPropertyNode * node, float w_scale, float h_scale)
|
||||
{
|
||||
FGPanelTransformation * t = new FGPanelTransformation;
|
||||
readTransformation (const SGPropertyNode *node, const float w_scale, const float h_scale) {
|
||||
FGPanelTransformation *t (new FGPanelTransformation);
|
||||
|
||||
string name = node->getName();
|
||||
string type = node->getStringValue("type");
|
||||
string propName = node->getStringValue("property", "");
|
||||
const SGPropertyNode * target = 0;
|
||||
const string name (node->getName ());
|
||||
string type (node->getStringValue ("type"));
|
||||
const string propName (node->getStringValue ("property", ""));
|
||||
const SGPropertyNode *target (0);
|
||||
|
||||
if (type.empty()) {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO,
|
||||
"No type supplied for transformation " << name
|
||||
<< " assuming \"rotation\"" );
|
||||
if (type.empty ()) {
|
||||
SG_LOG(SG_COCKPIT, SG_INFO,
|
||||
"No type supplied for transformation " << name
|
||||
<< " assuming \"rotation\"");
|
||||
type = "rotation";
|
||||
}
|
||||
|
||||
if (!propName.empty())
|
||||
target = ApplicationProperties::Properties->getNode(propName.c_str(), true);
|
||||
|
||||
if (!propName.empty ()) {
|
||||
target = ApplicationProperties::Properties->getNode (propName.c_str (), true);
|
||||
}
|
||||
t->node = target;
|
||||
t->min = node->getFloatValue("min", -9999999);
|
||||
t->max = node->getFloatValue("max", 99999999);
|
||||
t->has_mod = node->hasChild("modulator");
|
||||
if (t->has_mod)
|
||||
t->mod = node->getFloatValue("modulator");
|
||||
t->factor = node->getFloatValue("scale", 1.0);
|
||||
t->offset = node->getFloatValue("offset", 0.0);
|
||||
t->min = node->getFloatValue ("min", -9999999);
|
||||
t->max = node->getFloatValue ("max", 99999999);
|
||||
t->has_mod = node->hasChild ("modulator");
|
||||
if (t->has_mod) {
|
||||
t->mod = node->getFloatValue ("modulator");
|
||||
}
|
||||
t->factor = node->getFloatValue ("scale", 1.0);
|
||||
t->offset = node->getFloatValue ("offset", 0.0);
|
||||
|
||||
|
||||
// Check for an interpolation table
|
||||
const SGPropertyNode * trans_table = node->getNode("interpolation");
|
||||
// Check for an interpolation table
|
||||
const SGPropertyNode *trans_table (node->getNode ("interpolation"));
|
||||
if (trans_table != 0) {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Found interpolation table with "
|
||||
<< trans_table->nChildren() << " children" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Found interpolation table with "
|
||||
<< trans_table->nChildren() << " children");
|
||||
t->table = new SGInterpTable();
|
||||
for (int i = 0; i < trans_table->nChildren(); i++) {
|
||||
const SGPropertyNode * node = trans_table->getChild(i);
|
||||
if (!strcmp(node->getName(), "entry")) {
|
||||
double ind = node->getDoubleValue("ind", 0.0);
|
||||
double dep = node->getDoubleValue("dep", 0.0);
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Adding interpolation entry "
|
||||
<< ind << "==>" << dep );
|
||||
t->table->addEntry(ind, dep);
|
||||
double ind = node->getDoubleValue("ind", 0.0);
|
||||
double dep = node->getDoubleValue("dep", 0.0);
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Adding interpolation entry "
|
||||
<< ind << "==>" << dep);
|
||||
t->table->addEntry(ind, dep);
|
||||
} else {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in interpolation" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in interpolation");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
t->table = 0;
|
||||
}
|
||||
|
||||
// Move the layer horizontally.
|
||||
|
||||
// Move the layer horizontally.
|
||||
if (type == "x-shift") {
|
||||
t->type = FGPanelTransformation::XSHIFT;
|
||||
// t->min *= w_scale; //removed by Martin Dressler
|
||||
// t->max *= w_scale; //removed by Martin Dressler
|
||||
t->offset *= w_scale;
|
||||
t->factor *= w_scale; //Added by Martin Dressler
|
||||
}
|
||||
}
|
||||
|
||||
// Move the layer vertically.
|
||||
// Move the layer vertically.
|
||||
else if (type == "y-shift") {
|
||||
t->type = FGPanelTransformation::YSHIFT;
|
||||
//t->min *= h_scale; //removed
|
||||
//t->max *= h_scale; //removed
|
||||
t->offset *= h_scale;
|
||||
t->factor *= h_scale; //Added
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate the layer. The rotation
|
||||
// is in degrees, and does not need
|
||||
// to scale with the instrument size.
|
||||
// Rotate the layer. The rotation
|
||||
// is in degrees, and does not need
|
||||
// to scale with the instrument size.
|
||||
else if (type == "rotation") {
|
||||
t->type = FGPanelTransformation::ROTATION;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized transformation type " << type );
|
||||
SG_LOG(SG_COCKPIT, SG_ALERT, "Unrecognized transformation type " << type);
|
||||
delete t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
readConditions(t, node);
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Read transformation " << name );
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Read transformation " << name);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -258,56 +258,48 @@ readTransformation (const SGPropertyNode * node, float w_scale, float h_scale)
|
|||
* All three may also include a printf-style format string.
|
||||
*/
|
||||
FGTextLayer::Chunk *
|
||||
readTextChunk (const SGPropertyNode * node)
|
||||
{
|
||||
FGTextLayer::Chunk * chunk;
|
||||
string name = node->getStringValue("name");
|
||||
string type = node->getStringValue("type");
|
||||
string format = node->getStringValue("format");
|
||||
readTextChunk (const SGPropertyNode *node) {
|
||||
FGTextLayer::Chunk *chunk;
|
||||
const string name (node->getStringValue ("name"));
|
||||
string type (node->getStringValue ("type"));
|
||||
const string format (node->getStringValue ("format"));
|
||||
|
||||
// Default to literal text.
|
||||
if (type.empty()) {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "No type provided for text chunk " << name
|
||||
<< " assuming \"literal\"");
|
||||
// Default to literal text.
|
||||
if (type.empty ()) {
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "No type provided for text chunk " << name
|
||||
<< " assuming \"literal\"");
|
||||
type = "literal";
|
||||
}
|
||||
|
||||
// A literal text string.
|
||||
// A literal text string.
|
||||
if (type == "literal") {
|
||||
string text = node->getStringValue("text");
|
||||
chunk = new FGTextLayer::Chunk(text, format);
|
||||
}
|
||||
|
||||
// The value of a string property.
|
||||
else if (type == "text-value") {
|
||||
SGPropertyNode * target =
|
||||
ApplicationProperties::Properties->getNode( node->getStringValue("property"), true);
|
||||
chunk = new FGTextLayer::Chunk(FGTextLayer::TEXT_VALUE, target, format);
|
||||
}
|
||||
|
||||
// The value of a float property.
|
||||
else if (type == "number-value") {
|
||||
string propName = node->getStringValue("property");
|
||||
float scale = node->getFloatValue("scale", 1.0);
|
||||
float offset = node->getFloatValue("offset", 0.0);
|
||||
bool truncation = node->getBoolValue("truncate", false);
|
||||
SGPropertyNode * target = ApplicationProperties::Properties->getNode(propName.c_str(), true);
|
||||
chunk = new FGTextLayer::Chunk(FGTextLayer::DOUBLE_VALUE, target,
|
||||
format, scale, offset, truncation);
|
||||
}
|
||||
|
||||
// Unknown type.
|
||||
else {
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized type " << type
|
||||
<< " for text chunk " << name );
|
||||
const string text (node->getStringValue ("text"));
|
||||
chunk = new FGTextLayer::Chunk (text, format);
|
||||
} else if (type == "text-value") {
|
||||
// The value of a string property.
|
||||
const SGPropertyNode *target
|
||||
(ApplicationProperties::Properties->getNode (node->getStringValue ("property"), true));
|
||||
chunk = new FGTextLayer::Chunk (FGTextLayer::TEXT_VALUE, target, format);
|
||||
} else if (type == "number-value") {
|
||||
// The value of a float property.
|
||||
const string propName (node->getStringValue ("property"));
|
||||
const float scale (node->getFloatValue ("scale", 1.0));
|
||||
const float offset (node->getFloatValue ("offset", 0.0));
|
||||
const bool truncation (node->getBoolValue ("truncate", false));
|
||||
const SGPropertyNode *target (ApplicationProperties::Properties->getNode (propName.c_str (), true));
|
||||
chunk = new FGTextLayer::Chunk (FGTextLayer::DOUBLE_VALUE, target,
|
||||
format, scale, offset, truncation);
|
||||
} else {
|
||||
// Unknown type.
|
||||
SG_LOG(SG_COCKPIT, SG_ALERT, "Unrecognized type " << type
|
||||
<< " for text chunk " << name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
readConditions(chunk, node);
|
||||
readConditions (chunk, node);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read a single layer from an instrument's property list.
|
||||
*
|
||||
|
@ -330,254 +322,251 @@ readTextChunk (const SGPropertyNode * node)
|
|||
* Currently, the only built-in layer class is "compass-ribbon".
|
||||
*/
|
||||
static FGInstrumentLayer *
|
||||
readLayer (const SGPropertyNode * node, float w_scale, float h_scale)
|
||||
{
|
||||
FGInstrumentLayer * layer = NULL;
|
||||
string name = node->getStringValue("name");
|
||||
string type = node->getStringValue("type");
|
||||
int w = node->getIntValue("w", -1);
|
||||
int h = node->getIntValue("h", -1);
|
||||
bool emissive = node->getBoolValue("emissive", false);
|
||||
if (w != -1)
|
||||
w = int(w * w_scale);
|
||||
if (h != -1)
|
||||
h = int(h * h_scale);
|
||||
|
||||
|
||||
if (type.empty()) {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO,
|
||||
"No type supplied for layer " << name
|
||||
<< " assuming \"texture\"" );
|
||||
readLayer (const SGPropertyNode *node, const float w_scale, const float h_scale) {
|
||||
FGInstrumentLayer *layer (NULL);
|
||||
const string name (node->getStringValue ("name"));
|
||||
string type (node->getStringValue ("type"));
|
||||
int w (node->getIntValue ("w", -1));
|
||||
int h (node->getIntValue ("h", -1));
|
||||
const bool emissive (node->getBoolValue ("emissive", false));
|
||||
if (w != -1) {
|
||||
w = int (w * w_scale);
|
||||
}
|
||||
if (h != -1) {
|
||||
h = int (h * h_scale);
|
||||
}
|
||||
if (type.empty ()) {
|
||||
SG_LOG(SG_COCKPIT, SG_INFO,
|
||||
"No type supplied for layer " << name
|
||||
<< " assuming \"texture\"");
|
||||
type = "texture";
|
||||
}
|
||||
|
||||
|
||||
// A textured instrument layer.
|
||||
// A textured instrument layer.
|
||||
if (type == "texture") {
|
||||
FGCroppedTexture_ptr texture = readTexture(node->getNode("texture"));
|
||||
layer = new FGTexturedLayer(texture, w, h);
|
||||
const FGCroppedTexture_ptr texture (readTexture (node->getNode ("texture")));
|
||||
layer = new FGTexturedLayer (texture, w, h);
|
||||
if (emissive) {
|
||||
FGTexturedLayer *tl=(FGTexturedLayer*)layer;
|
||||
tl->setEmissive(true);
|
||||
FGTexturedLayer *tl = (FGTexturedLayer*) layer;
|
||||
tl->setEmissive (true);
|
||||
}
|
||||
|
||||
}
|
||||
// A group of sublayers.
|
||||
else if (type == "group") {
|
||||
layer = new FGGroupLayer();
|
||||
} else if (type == "group") {
|
||||
// A group of sublayers.
|
||||
layer = new FGGroupLayer ();
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
const SGPropertyNode * child = node->getChild(i);
|
||||
if (!strcmp(child->getName(), "layer"))
|
||||
((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale));
|
||||
const SGPropertyNode *child = node->getChild (i);
|
||||
if (!strcmp (child->getName (), "layer")) {
|
||||
((FGGroupLayer *) layer)->addLayer (readLayer (child, w_scale, h_scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == "text") {
|
||||
// A textual instrument layer.
|
||||
FGTextLayer *tlayer (new FGTextLayer (w, h)); // FIXME
|
||||
|
||||
// Set the text color.
|
||||
const float red (node->getFloatValue ("color/red", 0.0));
|
||||
const float green (node->getFloatValue ("color/green", 0.0));
|
||||
const float blue (node->getFloatValue ("color/blue", 0.0));
|
||||
tlayer->setColor (red, green, blue);
|
||||
|
||||
// A textual instrument layer.
|
||||
else if (type == "text") {
|
||||
FGTextLayer * tlayer = new FGTextLayer(w, h); // FIXME
|
||||
// Set the point size.
|
||||
const float pointSize (node->getFloatValue ("point-size", 10.0) * w_scale);
|
||||
tlayer->setPointSize (pointSize);
|
||||
|
||||
// Set the text color.
|
||||
float red = node->getFloatValue("color/red", 0.0);
|
||||
float green = node->getFloatValue("color/green", 0.0);
|
||||
float blue = node->getFloatValue("color/blue", 0.0);
|
||||
tlayer->setColor(red, green, blue);
|
||||
// Set the font.
|
||||
const string fontName (node->getStringValue ("font", "7-Segment"));
|
||||
tlayer->setFontName (fontName);
|
||||
|
||||
// Set the point size.
|
||||
float pointSize = node->getFloatValue("point-size", 10.0) * w_scale;
|
||||
tlayer->setPointSize(pointSize);
|
||||
|
||||
// Set the font.
|
||||
string fontName = node->getStringValue("font", "Helvetica");
|
||||
tlayer->setFontName(fontName);
|
||||
|
||||
const SGPropertyNode * chunk_group = node->getNode("chunks");
|
||||
const SGPropertyNode *chunk_group (node->getNode ("chunks"));
|
||||
if (chunk_group != 0) {
|
||||
int nChunks = chunk_group->nChildren();
|
||||
const int nChunks (chunk_group->nChildren ());
|
||||
for (int i = 0; i < nChunks; i++) {
|
||||
const SGPropertyNode * node = chunk_group->getChild(i);
|
||||
if (!strcmp(node->getName(), "chunk")) {
|
||||
FGTextLayer::Chunk * chunk = readTextChunk(node);
|
||||
if (chunk != 0)
|
||||
tlayer->addChunk(chunk);
|
||||
} else {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in chunks" );
|
||||
}
|
||||
const SGPropertyNode *node (chunk_group->getChild (i));
|
||||
if (!strcmp(node->getName (), "chunk")) {
|
||||
FGTextLayer::Chunk * const chunk (readTextChunk (node));
|
||||
if (chunk != 0) {
|
||||
tlayer->addChunk (chunk);
|
||||
}
|
||||
} else {
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in chunks");
|
||||
}
|
||||
}
|
||||
layer = tlayer;
|
||||
}
|
||||
}
|
||||
|
||||
// A switch instrument layer.
|
||||
else if (type == "switch") {
|
||||
layer = new FGSwitchLayer();
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
const SGPropertyNode * child = node->getChild(i);
|
||||
if (!strcmp(child->getName(), "layer"))
|
||||
((FGGroupLayer *)layer)->addLayer(readLayer(child, w_scale, h_scale));
|
||||
} else if (type == "switch") {
|
||||
// A switch instrument layer.
|
||||
layer = new FGSwitchLayer ();
|
||||
for (int i = 0; i < node->nChildren (); i++) {
|
||||
const SGPropertyNode *child (node->getChild (i));
|
||||
if (!strcmp (child->getName (), "layer")) {
|
||||
((FGGroupLayer *) layer)->addLayer (readLayer (child, w_scale, h_scale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An unknown type.
|
||||
else {
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT, "Unrecognized layer type " << type );
|
||||
} else {
|
||||
// An unknown type.
|
||||
SG_LOG(SG_COCKPIT, SG_ALERT, "Unrecognized layer type " << type);
|
||||
delete layer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Get the transformations for each layer.
|
||||
//
|
||||
const SGPropertyNode * trans_group = node->getNode("transformations");
|
||||
const SGPropertyNode *trans_group (node->getNode ("transformations"));
|
||||
if (trans_group != 0) {
|
||||
int nTransformations = trans_group->nChildren();
|
||||
const int nTransformations (trans_group->nChildren ());
|
||||
for (int i = 0; i < nTransformations; i++) {
|
||||
const SGPropertyNode * node = trans_group->getChild(i);
|
||||
if (!strcmp(node->getName(), "transformation")) {
|
||||
FGPanelTransformation * t = readTransformation(node, w_scale, h_scale);
|
||||
if (t != 0)
|
||||
layer->addTransformation(t);
|
||||
const SGPropertyNode *node (trans_group->getChild (i));
|
||||
if (!strcmp(node->getName (), "transformation")) {
|
||||
FGPanelTransformation * const t (readTransformation (node, w_scale, h_scale));
|
||||
if (t != 0) {
|
||||
layer->addTransformation (t);
|
||||
}
|
||||
} else {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in transformations" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in transformations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readConditions(layer, node);
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Read layer " << name );
|
||||
readConditions (layer, node);
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Read layer " << name);
|
||||
return layer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read an instrument from a property list.
|
||||
*
|
||||
* The instrument consists of a preferred width and height
|
||||
* (the panel may override these), together with a list of layers
|
||||
* and a list of actions to be performed when the user clicks
|
||||
* and a list of actions to be performed when the user clicks
|
||||
* the mouse over the instrument. All co-ordinates are relative
|
||||
* to the instrument's position, so instruments are fully relocatable;
|
||||
* likewise, co-ordinates for actions and transformations will be
|
||||
* scaled automatically if the instrument is not at its preferred size.
|
||||
*/
|
||||
static FGPanelInstrument *
|
||||
readInstrument (const SGPropertyNode * node)
|
||||
{
|
||||
const string name = node->getStringValue("name");
|
||||
int x = node->getIntValue("x", -1);
|
||||
int y = node->getIntValue("y", -1);
|
||||
int real_w = node->getIntValue("w", -1);
|
||||
int real_h = node->getIntValue("h", -1);
|
||||
int w = node->getIntValue("w-base", -1);
|
||||
int h = node->getIntValue("h-base", -1);
|
||||
readInstrument (const SGPropertyNode *node) {
|
||||
const string name (node->getStringValue ("name"));
|
||||
const int x (node->getIntValue ("x", -1));
|
||||
const int y (node->getIntValue ("y", -1));
|
||||
const int real_w (node->getIntValue ("w", -1));
|
||||
const int real_h (node->getIntValue ("h", -1));
|
||||
int w (node->getIntValue ("w-base", -1));
|
||||
int h (node->getIntValue ("h-base", -1));
|
||||
|
||||
if (x == -1 || y == -1) {
|
||||
SG_LOG( SG_COCKPIT, SG_ALERT,
|
||||
"x and y positions must be specified and > 0" );
|
||||
SG_LOG(SG_COCKPIT, SG_ALERT,
|
||||
"x and y positions must be specified and > 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
float w_scale = 1.0;
|
||||
float h_scale = 1.0;
|
||||
float w_scale (1.0);
|
||||
float h_scale (1.0);
|
||||
if (real_w != -1) {
|
||||
w_scale = float(real_w) / float(w);
|
||||
w_scale = float (real_w) / float (w);
|
||||
w = real_w;
|
||||
}
|
||||
if (real_h != -1) {
|
||||
h_scale = float(real_h) / float(h);
|
||||
h_scale = float (real_h) / float (h);
|
||||
h = real_h;
|
||||
}
|
||||
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Reading instrument " << name );
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Reading instrument " << name);
|
||||
|
||||
FGLayeredInstrument * instrument =
|
||||
new FGLayeredInstrument(x, y, w, h);
|
||||
FGLayeredInstrument * const instrument
|
||||
(new FGLayeredInstrument (x, y, w, h));
|
||||
|
||||
//
|
||||
// Get the layers for the instrument.
|
||||
//
|
||||
const SGPropertyNode * layer_group = node->getNode("layers");
|
||||
const SGPropertyNode *layer_group (node->getNode ("layers"));
|
||||
if (layer_group != 0) {
|
||||
int nLayers = layer_group->nChildren();
|
||||
const int nLayers (layer_group->nChildren ());
|
||||
for (int i = 0; i < nLayers; i++) {
|
||||
const SGPropertyNode * node = layer_group->getChild(i);
|
||||
if (!strcmp(node->getName(), "layer")) {
|
||||
FGInstrumentLayer * layer = readLayer(node, w_scale, h_scale);
|
||||
if (layer != 0)
|
||||
instrument->addLayer(layer);
|
||||
const SGPropertyNode *node (layer_group->getChild (i));
|
||||
if (!strcmp (node->getName (), "layer")) {
|
||||
FGInstrumentLayer * const layer (readLayer (node, w_scale, h_scale));
|
||||
if (layer != 0) {
|
||||
instrument->addLayer (layer);
|
||||
}
|
||||
} else {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in layers" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Skipping " << node->getName ()
|
||||
<< " in layers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readConditions(instrument, node);
|
||||
SG_LOG( SG_COCKPIT, SG_DEBUG, "Done reading instrument " << name );
|
||||
readConditions (instrument, node);
|
||||
SG_LOG(SG_COCKPIT, SG_DEBUG, "Done reading instrument " << name);
|
||||
return instrument;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct the panel from a property tree.
|
||||
*/
|
||||
SGSharedPtr<FGPanel>
|
||||
FGReadablePanel::read(SGPropertyNode_ptr root)
|
||||
{
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Reading properties for panel " <<
|
||||
root->getStringValue("name", "[Unnamed Panel]") );
|
||||
FGReadablePanel::read (SGPropertyNode_ptr root) {
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Reading properties for panel " <<
|
||||
root->getStringValue ("name", "[Unnamed Panel]"));
|
||||
|
||||
FGPanel * panel = new FGPanel(root);
|
||||
panel->setWidth(root->getIntValue("w", 1024));
|
||||
panel->setHeight(root->getIntValue("h", 443));
|
||||
FGPanel * const panel (new FGPanel (root));
|
||||
panel->setWidth (root->getIntValue ("w", 1024));
|
||||
panel->setHeight (root->getIntValue ("h", 443));
|
||||
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Size=" << panel->getWidth() << "x" << panel->getHeight() );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Size=" << panel->getWidth () << "x" << panel->getHeight ());
|
||||
|
||||
// Assign the background texture, if any, or a bogus chequerboard.
|
||||
//
|
||||
string bgTexture = root->getStringValue("background");
|
||||
if( !bgTexture.empty() )
|
||||
panel->setBackground( new FGCroppedTexture( bgTexture ) );
|
||||
panel->setBackgroundWidth( root->getDoubleValue( "background-width", 1.0 ) );
|
||||
panel->setBackgroundHeight( root->getDoubleValue( "background-height", 1.0 ) );
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Set background texture to " << bgTexture );
|
||||
const string bgTexture (root->getStringValue ("background"));
|
||||
if (!bgTexture.empty ()) {
|
||||
panel->setBackground (new FGCroppedTexture (bgTexture));
|
||||
}
|
||||
panel->setBackgroundWidth (root->getDoubleValue( "background-width", 1.0));
|
||||
panel->setBackgroundHeight (root->getDoubleValue( "background-height", 1.0));
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Set background texture to " << bgTexture);
|
||||
|
||||
//
|
||||
// Get multibackground if any...
|
||||
//
|
||||
for( int i = 0; i < 8; i++ ) {
|
||||
SGPropertyNode * mbgNode = root->getChild( "multibackground", i );
|
||||
for (int i = 0; i < 8; i++) {
|
||||
SGPropertyNode * const mbgNode (root->getChild ("multibackground", i));
|
||||
string mbgTexture;
|
||||
if( mbgNode != NULL ) mbgTexture = mbgNode->getStringValue();
|
||||
if( mbgTexture.empty() ) {
|
||||
if( i == 0 ) break; // if first texture is missing, ignore the rest
|
||||
else mbgTexture = "FOO"; // if others are missing - set default texture
|
||||
if (mbgNode != NULL) {
|
||||
mbgTexture = mbgNode->getStringValue ();
|
||||
}
|
||||
panel->setMultiBackground( new FGCroppedTexture(mbgTexture), i );
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Set multi-background texture" << i << " to " << mbgTexture );
|
||||
if (mbgTexture.empty ()) {
|
||||
if (i == 0) {
|
||||
break; // if first texture is missing, ignore the rest
|
||||
} else {
|
||||
mbgTexture = "FOO"; // if others are missing - set default texture
|
||||
}
|
||||
}
|
||||
panel->setMultiBackground (new FGCroppedTexture (mbgTexture), i);
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Set multi-background texture" << i << " to " << mbgTexture);
|
||||
}
|
||||
//
|
||||
// Create each instrument.
|
||||
//
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Reading panel instruments" );
|
||||
const SGPropertyNode * instrument_group = root->getChild("instruments");
|
||||
const SGPropertyNode *instrument_group (root->getChild ("instruments"));
|
||||
if (instrument_group != 0) {
|
||||
int nInstruments = instrument_group->nChildren();
|
||||
const int nInstruments (instrument_group->nChildren ());
|
||||
for (int i = 0; i < nInstruments; i++) {
|
||||
const SGPropertyNode * node = instrument_group->getChild(i);
|
||||
if (!strcmp(node->getName(), "instrument")) {
|
||||
FGPanelInstrument * instrument = readInstrument(node);
|
||||
if (instrument != 0)
|
||||
panel->addInstrument(instrument);
|
||||
const SGPropertyNode *node = instrument_group->getChild (i);
|
||||
if (!strcmp (node->getName (), "instrument")) {
|
||||
FGPanelInstrument * const instrument (readInstrument (node));
|
||||
if (instrument != 0) {
|
||||
panel->addInstrument (instrument);
|
||||
}
|
||||
} else {
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in instruments section" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Skipping " << node->getName()
|
||||
<< " in instruments section");
|
||||
}
|
||||
}
|
||||
}
|
||||
SG_LOG( SG_COCKPIT, SG_INFO, "Done reading panel instruments" );
|
||||
SG_LOG(SG_COCKPIT, SG_INFO, "Done reading panel instruments");
|
||||
|
||||
|
||||
//
|
||||
|
@ -587,6 +576,3 @@ FGReadablePanel::read(SGPropertyNode_ptr root)
|
|||
}
|
||||
|
||||
// end of panel_io.cxx
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
//
|
||||
// This program 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 GNU
|
||||
|
@ -16,25 +16,24 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id: panel_io.hxx,v 1.6 2006/04/17 13:03:43 mfranz Exp $
|
||||
// $Id: panel_io.hxx,v 1.2 2016/07/20 22:01:32 allaert Exp $
|
||||
|
||||
#ifndef __PANEL_IO_HXX
|
||||
#define __PANEL_IO_HXX
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "panel.hxx"
|
||||
#include "FGPanel.hxx"
|
||||
|
||||
class FGReadablePanel : public FGPanel {
|
||||
public:
|
||||
static SGSharedPtr<FGPanel> read(SGPropertyNode_ptr root);
|
||||
static SGSharedPtr<FGPanel> read (SGPropertyNode_ptr root);
|
||||
};
|
||||
|
||||
|
||||
#endif // __PANEL_IO_HXX
|
||||
|
|
Loading…
Add table
Reference in a new issue