Import Geant4 11.1.0.beta source tree
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_OpenGL
|
||||
#define toolx_OpenGL
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#include <OpenGLES/ES1/gl.h>
|
||||
#elif defined(ANDROID)
|
||||
#include <GLES/gl.h>
|
||||
#elif _WIN32
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#elif __APPLE__
|
||||
#if defined(TOOLX_USE_GL_GL_H) || defined(TOOLS_USE_GL_GL_H)
|
||||
#include <GL/gl.h> //Macports X11 GL.
|
||||
#else
|
||||
#include <OpenGL/gl.h> //Apple/OpenGL.
|
||||
#endif
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Qt_glarea
|
||||
#define toolx_Qt_glarea
|
||||
|
||||
#include "../sg/GL_viewer"
|
||||
|
||||
#include <QtOpenGL/qgl.h>
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
#include <tools/sg/device_interactor>
|
||||
|
||||
namespace toolx {
|
||||
namespace Qt {
|
||||
|
||||
class glarea : public QGLWidget {
|
||||
typedef QGLWidget parent;
|
||||
public:
|
||||
virtual void initialieGL() {}
|
||||
virtual void resizeGL(int a_w,int a_h){
|
||||
//::printf("debug : resize : %d %d\n",a_w,a_h);
|
||||
#if QT_VERSION < 0x050000
|
||||
#else
|
||||
m_width = a_w;
|
||||
m_height = a_h;
|
||||
#endif
|
||||
}
|
||||
//virtual void paintGL();
|
||||
virtual void paintGL() {
|
||||
#if QT_VERSION < 0x050000
|
||||
//::printf("debug : toolx::Qt::glarea::paintGL %d %d\n",width(),height());
|
||||
m_viewer.set_size(width(),height());
|
||||
#else
|
||||
//::printf("debug : toolx::Qt::glarea::paintGL %d %d\n",m_width,m_height);
|
||||
m_viewer.set_size(m_width,m_height);
|
||||
#endif
|
||||
m_viewer.render();
|
||||
}
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::key_down_event event(convert(a_event->key()));
|
||||
m_interactor->key_press(event);
|
||||
}
|
||||
virtual void keyReleaseEvent(QKeyEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::key_up_event event(convert(a_event->key()));
|
||||
m_interactor->key_release(event);
|
||||
}
|
||||
virtual void mousePressEvent(QMouseEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::mouse_down_event event(a_event->x(),a_event->y());
|
||||
m_interactor->mouse_press(event);
|
||||
}
|
||||
virtual void mouseReleaseEvent(QMouseEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::mouse_up_event event(a_event->x(),a_event->y());
|
||||
m_interactor->mouse_release(event);
|
||||
}
|
||||
virtual void mouseMoveEvent(QMouseEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::mouse_move_event event(a_event->x(),a_event->y(),0,0,false);
|
||||
m_interactor->mouse_move(event);
|
||||
}
|
||||
//virtual void mouseDoubleClickEvent(QMouseEvent* a_event) {
|
||||
// if(!m_interactor) return;
|
||||
// tools::sg::mouse_double_click_event event(a_event->x(),a_event->y());
|
||||
// m_interactor->mouse_double_click(event);
|
||||
//}
|
||||
virtual void wheelEvent(QWheelEvent* a_event) {
|
||||
if(!m_interactor) return;
|
||||
tools::sg::wheel_rotate_event event(a_event->angleDelta().y());
|
||||
m_interactor->wheel_rotate(event);
|
||||
}
|
||||
|
||||
public:
|
||||
glarea(QWidget* a_parent,toolx::sg::GL_viewer& a_viewer):parent(a_parent),m_viewer(a_viewer),m_interactor(0){}
|
||||
virtual ~glarea(){}
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
|
||||
protected:
|
||||
tools::key_code convert(/*Qt::Key*/int a_key) {return a_key;}
|
||||
protected:
|
||||
toolx::sg::GL_viewer& m_viewer;
|
||||
#if QT_VERSION < 0x050000
|
||||
#else
|
||||
protected:
|
||||
int m_width;
|
||||
int m_height;
|
||||
#endif
|
||||
tools::sg::device_interactor* m_interactor;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Qt_session
|
||||
#define toolx_Qt_session
|
||||
|
||||
// pure Qt code, no GL.
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include <QtCore/qglobal.h> //For QT_VERSION.
|
||||
#include <QtCore/qnamespace.h>
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QtGui/qapplication.h>
|
||||
#include <QtGui/qwidget.h>
|
||||
#else
|
||||
#include <QtWidgets/qapplication.h>
|
||||
#include <QtWidgets/qwidget.h>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace Qt {
|
||||
|
||||
class session {
|
||||
public:
|
||||
session(std::ostream& a_out,int& a_argc,char** a_argv)
|
||||
:m_out(a_out)
|
||||
,m_qapp(0)
|
||||
,m_own_qapp(false)
|
||||
{
|
||||
if(qApp) {
|
||||
m_qapp = qApp;
|
||||
m_own_qapp = false;
|
||||
} else {
|
||||
m_qapp = new QApplication(a_argc,a_argv);
|
||||
m_own_qapp = true;
|
||||
}
|
||||
}
|
||||
virtual ~session() {
|
||||
if(m_own_qapp && m_qapp) delete m_qapp;
|
||||
m_qapp = 0;
|
||||
m_own_qapp = false;
|
||||
}
|
||||
protected:
|
||||
session(const session& a_from)
|
||||
:m_out(a_from.m_out)
|
||||
,m_qapp(0)
|
||||
,m_own_qapp(false)
|
||||
{}
|
||||
session& operator=(const session& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
bool is_valid() const {return m_qapp?true:false;}
|
||||
bool steer() {
|
||||
if(!m_qapp) return false;
|
||||
m_qapp->exec();
|
||||
return true;
|
||||
}
|
||||
bool sync() {
|
||||
if(!m_qapp) return false;
|
||||
//m_qapp->exec();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
QApplication* qapp() const {return m_qapp;}
|
||||
QWidget* create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
|
||||
if(!m_qapp) return 0;
|
||||
#ifdef _MSC_VER
|
||||
if(a_y<=0) a_y = 60;
|
||||
#endif
|
||||
QWidget* top = new QWidget();
|
||||
top->setWindowFlags(::Qt::CustomizeWindowHint
|
||||
| ::Qt::WindowTitleHint
|
||||
| ::Qt::WindowMinMaxButtonsHint
|
||||
// | ::Qt::WindowSystemMenuHint
|
||||
// | ::Qt::WindowFullscreenButtonHint
|
||||
);
|
||||
top->setGeometry(a_x,a_y,a_width,a_height);
|
||||
top->setWindowTitle(s2q(a_title));
|
||||
//top->setAttribute(Qt::WA_DeleteOnClose,false);
|
||||
return top;
|
||||
}
|
||||
void delete_window(QWidget* a_window) const {
|
||||
if(!m_qapp) return;
|
||||
delete a_window;
|
||||
}
|
||||
protected:
|
||||
QString s2q(const std::string& a_s) {
|
||||
#if QT_VERSION < 0x050000
|
||||
return QString::fromAscii(a_s.c_str());
|
||||
#else
|
||||
return QString::fromLatin1(a_s.c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
QApplication* m_qapp;
|
||||
bool m_own_qapp;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Qt_sg_viewer
|
||||
#define toolx_Qt_sg_viewer
|
||||
|
||||
#include "glarea"
|
||||
|
||||
#include "session"
|
||||
|
||||
#include <QtCore/qglobal.h> //For QT_VERSION.
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
#include <QtGui/qboxlayout.h>
|
||||
#else
|
||||
#include <QtWidgets/qboxlayout.h>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace Qt {
|
||||
|
||||
class sg_viewer : public sg::GL_viewer {
|
||||
typedef sg::GL_viewer parent;
|
||||
public:
|
||||
sg_viewer(session& a_session,
|
||||
int a_x = 0,int a_y = 0,
|
||||
unsigned int a_width = 500,unsigned int a_height = 500,
|
||||
const std::string& a_win_title = "")
|
||||
:parent(a_session.out(),a_width,a_height)
|
||||
,m_session(a_session)
|
||||
,m_shell(0)
|
||||
,m_own_shell(false)
|
||||
,m_glarea(0)
|
||||
{
|
||||
if(!m_session.is_valid()) return; //throw
|
||||
m_shell = m_session.create_window(a_win_title.c_str(),a_x,a_y,a_width,a_height);
|
||||
if(!m_shell) return; //throw
|
||||
m_own_shell = true;
|
||||
|
||||
m_glarea = new Qt::glarea(0,*this);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
layout->addWidget(m_glarea);
|
||||
m_shell->setLayout(layout);
|
||||
}
|
||||
virtual ~sg_viewer() {
|
||||
if(m_glarea) m_glarea->set_device_interactor(0);
|
||||
if(m_shell && m_own_shell) {
|
||||
m_session.delete_window(m_shell);
|
||||
//m_session.sync();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
sg_viewer(const sg_viewer& a_from)
|
||||
:parent(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_shell(0)
|
||||
,m_own_shell(false)
|
||||
,m_glarea(0)
|
||||
{}
|
||||
sg_viewer& operator=(const sg_viewer& a_from){
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool has_window() const {return m_shell?true:false;} //for SWIG
|
||||
|
||||
bool show() {
|
||||
if(!m_shell) return false;
|
||||
m_shell->show();
|
||||
return true;
|
||||
}
|
||||
|
||||
void win_render() {
|
||||
if(!m_glarea) return;
|
||||
m_glarea->update();
|
||||
}
|
||||
public:
|
||||
QWidget* shell() {return m_shell;}
|
||||
void set_own_shell(bool a_value) {m_own_shell = a_value;}
|
||||
Qt::glarea* glarea() {return m_glarea;}
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) { //we do not have ownership.
|
||||
if(!m_glarea) return;
|
||||
m_glarea->set_device_interactor(a_interactor);
|
||||
}
|
||||
void enable_keyboard_focus() {
|
||||
if(!m_glarea) return;
|
||||
m_glarea->setFocusPolicy(::Qt::StrongFocus);
|
||||
}
|
||||
protected:
|
||||
session& m_session;
|
||||
QWidget* m_shell;
|
||||
bool m_own_shell;
|
||||
Qt::glarea* m_glarea;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_glarea
|
||||
#define toolx_Windows_glarea
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <wingdi.h>
|
||||
|
||||
#include <tools/sg/device_interactor>
|
||||
#include <tools/sg/keys>
|
||||
//#include <tools/log_file>
|
||||
|
||||
#include <string>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#else
|
||||
#define TOOLX_WINDOWS_TOUCH
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
inline bool is_message_touch_event() {
|
||||
// from https://stackoverflow.com/questions/29857587/detect-if-wm-mousemove-is-caused-by-touch-pen.
|
||||
static const LONG_PTR c_SIGNATURE_MASK = 0xFFFFFF00;
|
||||
static const LONG_PTR c_MOUSEEVENTF_FROMTOUCH = 0xFF515700;
|
||||
LONG_PTR extraInfo = ::GetMessageExtraInfo();
|
||||
return ( ( extraInfo & c_SIGNATURE_MASK ) == c_MOUSEEVENTF_FROMTOUCH );
|
||||
}
|
||||
#endif
|
||||
|
||||
class glarea {
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::Windows::glarea");
|
||||
return s_v;
|
||||
}
|
||||
static void register_class(){
|
||||
static bool s_done = false; //not const, then not thread safe.
|
||||
if(!s_done) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC)proc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = ::GetModuleHandle(NULL);
|
||||
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
|
||||
wc.lpszMenuName = s_class().c_str();
|
||||
wc.lpszClassName = s_class().c_str();
|
||||
::RegisterClass(&wc);
|
||||
s_done = true;
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual void resize(unsigned int,unsigned int){}
|
||||
virtual void paint(unsigned int a_w,unsigned int a_h) {}
|
||||
virtual void close(){}
|
||||
|
||||
virtual void left_button_up(unsigned int a_x,unsigned int a_y) {}
|
||||
virtual void left_button_down(unsigned int a_x,unsigned int a_y) {}
|
||||
virtual void mouse_move(unsigned int a_x,unsigned int a_y,bool) {}
|
||||
public:
|
||||
glarea(HWND a_parent)
|
||||
:m_parent(a_parent)
|
||||
,m_hwnd(0)
|
||||
,m_context(0)
|
||||
,m_HDC(0)
|
||||
,m_touch_available(false)
|
||||
,m_interactor(0)
|
||||
{
|
||||
register_class();
|
||||
// The WS_BORDER is needed. Else probleme of size at startup.
|
||||
RECT rect;
|
||||
::GetClientRect(m_parent,&rect);
|
||||
//printf("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
|
||||
//toolx::log_file::get().writef("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
0,0,
|
||||
rect.right-rect.left,
|
||||
rect.bottom-rect.top,
|
||||
m_parent,NULL,
|
||||
GetWindowInstance(m_parent),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
|
||||
// initialize OpenGL rendering :
|
||||
m_HDC = ::GetDC(m_hwnd);
|
||||
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
|
||||
m_context = ::wglCreateContext(m_HDC);
|
||||
}
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
{BYTE digitizer_status = (BYTE)::GetSystemMetrics(SM_DIGITIZER);
|
||||
if((digitizer_status & (0x80 + 0x40)) == 0) {
|
||||
m_touch_available = false;
|
||||
} else {
|
||||
//BYTE nInputs = (BYTE)::GetSystemMetrics(SM_MAXIMUMTOUCHES);
|
||||
m_touch_available = true;
|
||||
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
|
||||
}}
|
||||
#endif
|
||||
|
||||
}
|
||||
virtual ~glarea(){
|
||||
if(::wglGetCurrentContext()!=NULL) ::wglMakeCurrent(NULL,NULL);
|
||||
if(m_context) {
|
||||
::wglDeleteContext(m_context);
|
||||
m_context = 0;
|
||||
}
|
||||
if(m_HDC && m_hwnd) ::ReleaseDC(m_hwnd,m_HDC);
|
||||
if(m_hwnd) {
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
::DestroyWindow(m_hwnd);
|
||||
m_hwnd = 0;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
glarea(const glarea& a_from)
|
||||
:m_parent(a_from.m_parent)
|
||||
,m_hwnd(0)
|
||||
,m_context(0)
|
||||
,m_HDC(0)
|
||||
,m_touch_available(a_from.m_touch_available)
|
||||
,m_interactor(0)
|
||||
{
|
||||
if(!m_parent) return;
|
||||
register_class();
|
||||
RECT rect;
|
||||
::GetClientRect(m_parent,&rect);
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_CHILD | WS_VISIBLE,
|
||||
0,0,
|
||||
rect.right-rect.left,
|
||||
rect.bottom-rect.top,
|
||||
m_parent,NULL,
|
||||
GetWindowInstance(m_parent),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
|
||||
// initialize OpenGL rendering :
|
||||
m_HDC = ::GetDC(m_hwnd);
|
||||
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
|
||||
m_context = ::wglCreateContext(m_HDC);
|
||||
}
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
if(a_from.m_touch_available) {
|
||||
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
glarea& operator=(const glarea&){return *this;}
|
||||
public:
|
||||
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
|
||||
RECT rect;
|
||||
::GetClientRect(m_hwnd,&rect);
|
||||
::MoveWindow(m_hwnd,rect.left,rect.top,a_w,a_h,TRUE);
|
||||
}
|
||||
HWND hwnd() const {return m_hwnd;}
|
||||
void post_WM_PAINT() const {
|
||||
::PostMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
|
||||
}
|
||||
void send_WM_PAINT() const {
|
||||
::SendMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
|
||||
}
|
||||
void wm_paint() {
|
||||
PAINTSTRUCT ps;
|
||||
//HDC hDC =
|
||||
BeginPaint(m_hwnd,&ps);
|
||||
if(m_HDC && m_context) {
|
||||
::wglMakeCurrent(m_HDC,m_context);
|
||||
|
||||
RECT rect;
|
||||
::GetClientRect(m_hwnd,&rect);
|
||||
unsigned int w = rect.right-rect.left;
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
|
||||
//printf("debug : glarea : paint : %d %d\n",w,h);
|
||||
//toolx::log_file::get().writef("debug : glarea : paint : %d %d\n",w,h);
|
||||
|
||||
paint(w,h);
|
||||
|
||||
::SwapBuffers(m_HDC);
|
||||
::wglMakeCurrent(m_HDC,0);
|
||||
}
|
||||
EndPaint(m_hwnd,&ps);
|
||||
}
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
|
||||
protected:
|
||||
bool is_touch_event() {
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
if(!m_touch_available) return false;
|
||||
return is_message_touch_event();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
|
||||
switch (a_msg) {
|
||||
case WM_SIZE:{
|
||||
int width = LOWORD(a_lparam);
|
||||
int height = HIWORD(a_lparam);
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
_this->resize(width,height);
|
||||
} else {
|
||||
// CreateWindow send a WM_SIZE but GWLP_USERDATA not yet set.
|
||||
}
|
||||
}return 0;
|
||||
case WM_PAINT:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->wm_paint();
|
||||
}return 0;
|
||||
|
||||
case WM_KEYDOWN:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::key_down_event event(_this->convert(a_wparam));
|
||||
_this->m_interactor->key_press(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
case WM_KEYUP:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::key_up_event event(_this->convert(a_wparam));
|
||||
_this->m_interactor->key_release(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
|
||||
case WM_LBUTTONDOWN:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_down_event event(LOWORD(a_lparam),HIWORD(a_lparam));
|
||||
_this->m_interactor->mouse_press(event);
|
||||
} else {
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->left_button_down(LOWORD(a_lparam),h-HIWORD(a_lparam));
|
||||
}
|
||||
}
|
||||
}return 0;
|
||||
case WM_LBUTTONUP:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_up_event event(LOWORD(a_lparam),HIWORD(a_lparam));
|
||||
_this->m_interactor->mouse_release(event);
|
||||
} else {
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->left_button_up(LOWORD(a_lparam),h-HIWORD(a_lparam));
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
case WM_MOUSEMOVE:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::mouse_move_event event(LOWORD(a_lparam),HIWORD(a_lparam),0,0,false);
|
||||
_this->m_interactor->mouse_move(event);
|
||||
} else {
|
||||
WPARAM state = a_wparam;
|
||||
bool ldown = ((state & MK_LBUTTON)==MK_LBUTTON)?true:false;
|
||||
RECT rect;
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
if(!_this->is_touch_event()) _this->mouse_move(LOWORD(a_lparam),h-HIWORD(a_lparam),ldown);
|
||||
}
|
||||
}
|
||||
|
||||
}return 0;
|
||||
|
||||
case WM_MOUSEWHEEL:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
if(_this->m_interactor) {
|
||||
tools::sg::wheel_rotate_event event(GET_WHEEL_DELTA_WPARAM(a_wparam));
|
||||
_this->m_interactor->wheel_rotate(event);
|
||||
}
|
||||
}
|
||||
} return 0;
|
||||
|
||||
#ifdef TOOLX_WINDOWS_TOUCH
|
||||
case WM_TOUCH:{
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this && _this->m_touch_available) {
|
||||
RECT rect;
|
||||
//::GetWindowRect(hwnd,&rect); ???
|
||||
::GetClientRect(a_hwnd,&rect);
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
|
||||
unsigned int num_inputs = (int)a_wparam;
|
||||
//::printf("debug : WM_TOUCH : 001 : %d\n",num_inputs);
|
||||
TOUCHINPUT* ti = new TOUCHINPUT[num_inputs];
|
||||
POINT p;
|
||||
if(::GetTouchInputInfo((HTOUCHINPUT)a_lparam,num_inputs,ti,sizeof(TOUCHINPUT))) {
|
||||
for(unsigned int i=0;i<num_inputs; ++i) {
|
||||
p.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
|
||||
p.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
|
||||
if(!::ScreenToClient(a_hwnd,&p)) {}
|
||||
if(ti[i].dwFlags & TOUCHEVENTF_DOWN) {
|
||||
//::printf("debug : TOUCHEVENTF_DOWN %lu %lu\n",p.x,p.y);
|
||||
_this->left_button_down(p.x,h-p.y);
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
|
||||
//::printf("debug : TOUCHEVENTF_UP %lu %lu\n",p.x,p.y);
|
||||
_this->left_button_up(p.x,h-p.y);
|
||||
} else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
|
||||
bool ldown = true; //we assume that a TOUCHEVENT_DOWN had been done.
|
||||
//::printf("debug : TOUCHEVENTF_MOVE %lu %lu\n",p.x,p.y);
|
||||
_this->mouse_move(p.x,h-p.y,ldown);
|
||||
}
|
||||
}
|
||||
}
|
||||
::CloseTouchInputHandle((HTOUCHINPUT)a_lparam);
|
||||
delete [] ti;
|
||||
}
|
||||
}return 0;
|
||||
#endif //TOOLX_WINDOWS_TOUCH
|
||||
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
|
||||
}
|
||||
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
|
||||
}
|
||||
static bool SetWindowPixelFormat(HDC a_HDC){
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags =
|
||||
PFD_DRAW_TO_WINDOW |
|
||||
PFD_SUPPORT_OPENGL |
|
||||
PFD_DOUBLEBUFFER |
|
||||
PFD_STEREO_DONTCARE;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cRedShift = 16;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cGreenShift = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cBlueShift = 0;
|
||||
pfd.cAlphaBits = 0;
|
||||
pfd.cAlphaShift = 0;
|
||||
pfd.cAccumBits = 64;
|
||||
pfd.cAccumRedBits = 16;
|
||||
pfd.cAccumGreenBits = 16;
|
||||
pfd.cAccumBlueBits = 16;
|
||||
pfd.cAccumAlphaBits = 0;
|
||||
pfd.cDepthBits = 32;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.cAuxBuffers = 0;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
pfd.bReserved = 0;
|
||||
pfd.dwLayerMask = 0;
|
||||
pfd.dwVisibleMask = 0;
|
||||
pfd.dwDamageMask = 0;
|
||||
|
||||
int pixelIndex = ::ChoosePixelFormat(a_HDC,&pfd);
|
||||
if (pixelIndex==0) {
|
||||
// Let's choose a default index.
|
||||
pixelIndex = 1;
|
||||
if (::DescribePixelFormat(a_HDC,
|
||||
pixelIndex,
|
||||
sizeof(PIXELFORMATDESCRIPTOR),
|
||||
&pfd)==0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (::SetPixelFormat(a_HDC,pixelIndex,&pfd)==FALSE) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
static void wm__destroy(HWND a_hwnd) {
|
||||
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) { //How to be sure that we have a glarea* ???
|
||||
_this->close();
|
||||
if(_this->m_hwnd!=a_hwnd) {
|
||||
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
|
||||
}
|
||||
_this->m_hwnd = 0;
|
||||
}
|
||||
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
}
|
||||
protected:
|
||||
tools::key_code convert(WPARAM a_key) {
|
||||
if(a_key==VK_SHIFT) return tools::sg::key_shift();
|
||||
return (tools::key_code)a_key;
|
||||
}
|
||||
protected:
|
||||
HWND m_parent;
|
||||
HWND m_hwnd;
|
||||
HGLRC m_context;
|
||||
HDC m_HDC;
|
||||
bool m_touch_available;
|
||||
tools::sg::device_interactor* m_interactor;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_session
|
||||
#define toolx_Windows_session
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class session {
|
||||
public:
|
||||
session(std::ostream& a_out):m_out(a_out){}
|
||||
virtual ~session() {}
|
||||
protected:
|
||||
session(const session& a_from):m_out(a_from.m_out){}
|
||||
session& operator=(const session&){return *this;}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
|
||||
bool is_valid() const {return true;}
|
||||
|
||||
bool steer() {
|
||||
while(true) {
|
||||
MSG event;
|
||||
BOOL status = ::GetMessage(&event,NULL,0,0);
|
||||
if(status == -1) { // This may happen (dixit Microsoft doc).
|
||||
break;
|
||||
} else if(status == 0) { //WM_QUIT
|
||||
break;
|
||||
} else {
|
||||
::TranslateMessage(&event);
|
||||
::DispatchMessage (&event);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sync() {
|
||||
MSG event;
|
||||
while(::PeekMessage(&event,NULL,0,0,PM_REMOVE)) {
|
||||
if(event.message==WM_QUIT) return false;
|
||||
::TranslateMessage(&event);
|
||||
::DispatchMessage(&event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void show_window(HWND a_hwnd){
|
||||
::SetForegroundWindow(a_hwnd);
|
||||
::ShowWindow(a_hwnd,SW_SHOWDEFAULT);
|
||||
::UpdateWindow(a_hwnd);
|
||||
::DrawMenuBar(a_hwnd);
|
||||
}
|
||||
|
||||
void set_size(HWND a_hwnd,unsigned int a_width,unsigned int a_height) {
|
||||
::MoveWindow(a_hwnd,0,0,a_width,a_height,TRUE);
|
||||
}
|
||||
|
||||
//void post(HWND a_hwnd,LPARAM a_msg){
|
||||
// ::PostMessage(a_hwnd,WM_USER,(WPARAM)0,a_msg);
|
||||
//}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_sg_viewer
|
||||
#define toolx_Windows_sg_viewer
|
||||
|
||||
#include "session"
|
||||
#include "window"
|
||||
#include "glarea"
|
||||
|
||||
#include "../sg/GL_viewer"
|
||||
|
||||
// disable the warning about the usage of "this" in the constructor.
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class sg_viewer : public window, public sg::GL_viewer {
|
||||
typedef window parent_window;
|
||||
typedef sg::GL_viewer parent_viewer;
|
||||
public:
|
||||
virtual void close() {}
|
||||
public:
|
||||
sg_viewer(session& a_session,
|
||||
int a_x = 0,int a_y = 0,
|
||||
unsigned int a_width = 500,unsigned int a_height = 500,
|
||||
const std::string& a_title = "")
|
||||
:parent_window(a_title.c_str(),a_x,a_y,a_width,a_height)
|
||||
,parent_viewer(a_session.out(),a_width,a_height)
|
||||
,m_session(a_session)
|
||||
,m_glarea(m_hwnd,*this)
|
||||
{
|
||||
parent_window::set_focus_hwnd(m_glarea.hwnd());
|
||||
}
|
||||
virtual ~sg_viewer() {}
|
||||
protected:
|
||||
sg_viewer(const sg_viewer& a_from)
|
||||
:parent_window(a_from)
|
||||
,parent_viewer(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_glarea(a_from.m_glarea)
|
||||
{}
|
||||
sg_viewer& operator=(const sg_viewer& a_from){
|
||||
parent_window::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool has_window() const {return m_hwnd?true:false;} //for SWIG
|
||||
|
||||
HWND window() const {return m_hwnd;}
|
||||
|
||||
bool show() {
|
||||
if(!m_hwnd) return false;
|
||||
m_session.show_window(m_hwnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void win_render() {m_glarea.wm_paint();}
|
||||
|
||||
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) { //we do not have ownership.
|
||||
m_glarea.set_device_interactor(a_interactor);
|
||||
}
|
||||
protected:
|
||||
class _glarea : public glarea {
|
||||
public:
|
||||
virtual void paint(unsigned int a_w,unsigned int a_h) {
|
||||
m_viewer.set_size(a_w,a_h);
|
||||
m_viewer.render();
|
||||
}
|
||||
public:
|
||||
_glarea(HWND a_parent,parent_viewer& a_viewer)
|
||||
:glarea(a_parent)
|
||||
,m_viewer(a_viewer)
|
||||
{}
|
||||
protected:
|
||||
parent_viewer& m_viewer;
|
||||
};
|
||||
|
||||
protected:
|
||||
session& m_session;
|
||||
_glarea m_glarea;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Windows_window
|
||||
#define toolx_Windows_window
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <string>
|
||||
|
||||
namespace toolx {
|
||||
namespace Windows {
|
||||
|
||||
class window {
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::Windows::window");
|
||||
return s_v;
|
||||
}
|
||||
static void register_class(){
|
||||
static bool s_done = false; //not const, then not thread safe.
|
||||
if(!s_done) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = (WNDPROC)proc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = ::GetModuleHandle(NULL);
|
||||
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
|
||||
wc.lpszMenuName = s_class().c_str();
|
||||
wc.lpszClassName = s_class().c_str();
|
||||
::RegisterClass(&wc);
|
||||
s_done = true;
|
||||
}
|
||||
}
|
||||
public:
|
||||
virtual void key_up(){}
|
||||
virtual void key_down(){}
|
||||
virtual void key_left(){}
|
||||
virtual void key_right(){}
|
||||
virtual void key_escape(){}
|
||||
virtual void close(){
|
||||
//if(m_hwnd) ::PostMessage(m_hwnd,WM_QUIT,0,0);
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
public:
|
||||
window(const char* a_title,int a_x,int a_y,unsigned int a_w,unsigned int a_h,unsigned int a_mask = WS_OVERLAPPEDWINDOW)
|
||||
:m_hwnd(0)
|
||||
,m_key_shift(false)
|
||||
,m_key_ctrl(false)
|
||||
,m_focus_hwnd(0)
|
||||
{
|
||||
// WARNING : given a_w,a_h may not be the client area because of various decorations.
|
||||
// See set_client_area_size() method to enforce a client area size.
|
||||
register_class();
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
a_mask,
|
||||
a_x,a_y,
|
||||
a_w,a_h,
|
||||
NULL,NULL,
|
||||
::GetModuleHandle(NULL),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowText(m_hwnd,a_title);
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
}
|
||||
virtual ~window(){
|
||||
if(m_hwnd) {
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
::DestroyWindow(m_hwnd);
|
||||
m_hwnd = 0;
|
||||
}
|
||||
}
|
||||
protected:
|
||||
window(const window& a_from)
|
||||
:m_hwnd(0)
|
||||
,m_key_shift(a_from.m_key_shift)
|
||||
,m_key_ctrl(a_from.m_key_ctrl)
|
||||
,m_focus_hwnd(0)
|
||||
{
|
||||
/*
|
||||
if(!a_from.m_hwnd) return;
|
||||
int w,h;
|
||||
get_size(a_from.m_hwnd,w,h);
|
||||
register_class();
|
||||
m_hwnd = ::CreateWindow(s_class().c_str(),
|
||||
NULL,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT,
|
||||
w,h,
|
||||
NULL,NULL,
|
||||
::GetModuleHandle(NULL),
|
||||
NULL);
|
||||
if(!m_hwnd) return;
|
||||
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
|
||||
*/
|
||||
}
|
||||
window& operator=(const window& a_from){
|
||||
m_key_shift = a_from.m_key_shift;
|
||||
m_key_ctrl = a_from.m_key_ctrl;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
const window& get_me() const {return *this;}
|
||||
window& get_me() {return *this;}
|
||||
bool key_shift() const {return m_key_shift;}
|
||||
HWND hwnd() const {return m_hwnd;}
|
||||
|
||||
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
|
||||
if(!m_hwnd) return;
|
||||
RECT wrect;
|
||||
::GetWindowRect(m_hwnd,&wrect);
|
||||
unsigned int ww = wrect.right-wrect.left;
|
||||
unsigned int wh = wrect.bottom-wrect.top;
|
||||
|
||||
RECT carect;
|
||||
::GetClientRect(m_hwnd,&carect);
|
||||
unsigned int cw = carect.right-carect.left;
|
||||
unsigned int ch = carect.bottom-carect.top;
|
||||
|
||||
unsigned int woffset = ww-cw;
|
||||
unsigned int hoffset = wh-ch;
|
||||
|
||||
::MoveWindow(m_hwnd,wrect.left,wrect.top,a_w+woffset,a_h+hoffset,TRUE);
|
||||
}
|
||||
void move(unsigned int a_x,unsigned int a_y) {
|
||||
if(!m_hwnd) return;
|
||||
RECT rect;
|
||||
::GetWindowRect(m_hwnd,&rect);
|
||||
unsigned int w = rect.right-rect.left;
|
||||
unsigned int h = rect.bottom-rect.top;
|
||||
::MoveWindow(m_hwnd,a_x,a_y,w,h,TRUE);
|
||||
}
|
||||
|
||||
void set_focus_hwnd(HWND a_hwnd) {m_focus_hwnd = a_hwnd;}
|
||||
HWND focus_hwnd() const {return m_focus_hwnd;}
|
||||
protected:
|
||||
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
|
||||
switch (a_msg) {
|
||||
// Else :
|
||||
case WM_SIZE:{ // Assume one child window ! FIXME : have a message if not.
|
||||
int width = LOWORD(a_lparam);
|
||||
int height = HIWORD(a_lparam);
|
||||
HWND hwnd = GetFirstChild(a_hwnd);
|
||||
if(hwnd) {
|
||||
::MoveWindow(hwnd,0,0,width,height,TRUE);
|
||||
}
|
||||
}return 0;
|
||||
|
||||
case WM_SETFOCUS:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) {
|
||||
HWND hwnd = _this->focus_hwnd();
|
||||
if(hwnd) ::SetFocus(hwnd);
|
||||
}
|
||||
}return 0;
|
||||
|
||||
case WM_KEYDOWN:{
|
||||
switch(a_wparam){
|
||||
case VK_SHIFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_shift = true;
|
||||
return 0;
|
||||
}
|
||||
case VK_CONTROL:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_ctrl = true;
|
||||
return 0;
|
||||
}
|
||||
case VK_UP:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_up();
|
||||
return 0;
|
||||
}
|
||||
case VK_DOWN:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_down();
|
||||
return 0;
|
||||
}
|
||||
case VK_LEFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_left();
|
||||
return 0;
|
||||
}
|
||||
case VK_RIGHT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_right();
|
||||
return 0;
|
||||
}
|
||||
case VK_ESCAPE:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->key_escape();
|
||||
return 0;
|
||||
}
|
||||
} //end switch(a_wparam)
|
||||
break;
|
||||
}
|
||||
case WM_KEYUP:{
|
||||
switch(a_wparam){
|
||||
case VK_SHIFT:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_shift = false;
|
||||
return 0;
|
||||
}
|
||||
case VK_CONTROL:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->m_key_ctrl = false;
|
||||
return 0;
|
||||
}
|
||||
} //end switch(a_wparam)
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_CLOSE:{
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) _this->close();
|
||||
}break; //NOTE : can't be return 0.
|
||||
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
|
||||
}
|
||||
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
|
||||
}
|
||||
static void wm__destroy(HWND a_hwnd) {
|
||||
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
|
||||
if(_this) { //How to be sure that we have a window* ???
|
||||
if(_this->m_hwnd!=a_hwnd) {
|
||||
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
|
||||
}
|
||||
_this->m_hwnd = 0;
|
||||
}
|
||||
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
|
||||
}
|
||||
protected:
|
||||
void get_size(HWND a_hwnd,int& a_w,int& a_h){
|
||||
RECT rect;
|
||||
::GetWindowRect(a_hwnd,&rect);
|
||||
a_w = rect.right-rect.left;
|
||||
a_h = rect.bottom-rect.top;
|
||||
}
|
||||
protected:
|
||||
HWND m_hwnd;
|
||||
bool m_key_shift;
|
||||
bool m_key_ctrl;
|
||||
HWND m_focus_hwnd;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,392 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_X11_base_session
|
||||
#define toolx_X11_base_session
|
||||
|
||||
// pure X11 code, no GL.
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "dispatcher"
|
||||
#include <tools/forit>
|
||||
|
||||
#include <X11/Xatom.h> //XA_INTEGER
|
||||
|
||||
#include <X11/Xutil.h> //XVisualInfo
|
||||
|
||||
namespace toolx {
|
||||
namespace X11 {
|
||||
|
||||
class base_session {
|
||||
public:
|
||||
//virtual bool make_current(Window) const {
|
||||
// if(!m_display) return false;
|
||||
// return true;
|
||||
//}
|
||||
//virtual bool swap_buffers(Window) const {
|
||||
// if(!m_display) return false;
|
||||
// return true;
|
||||
//}
|
||||
public:
|
||||
base_session(std::ostream& a_out,unsigned int a_monitor = 0)
|
||||
:m_out(a_out)
|
||||
,m_monitor(a_monitor)
|
||||
,m_display(0)
|
||||
,m_WM_DELETE_WINDOW_atom(None)
|
||||
,m_SESSION_EXIT_STEER_atom(None)
|
||||
{
|
||||
//NOTE : macOS : XOpenDisplay leaks 128 bytes.
|
||||
m_display = ::XOpenDisplay(NULL);
|
||||
if(!m_display) {
|
||||
m_out << "toolx::X11::base_session::base_session : can't open display." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int monitors = ::XScreenCount(m_display);
|
||||
if(int(m_monitor)>=monitors) {
|
||||
m_out << "toolx::X11::base_session::base_session : bad monitor index "
|
||||
<< m_monitor << ". (#monitors " << monitors << ")." << std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_WM_DELETE_WINDOW_atom = ::XInternAtom(m_display,"WM_DELETE_WINDOW",False);
|
||||
if(m_WM_DELETE_WINDOW_atom==None) {
|
||||
m_out << "toolx::X11::base_session::base_session : can't create WM_DELETE_WINDOW Atom." << std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_SESSION_EXIT_STEER_atom = ::XInternAtom(m_display,"TOOLX_X11_SESSION_EXIT_STEER",False);
|
||||
if(m_SESSION_EXIT_STEER_atom==None) {
|
||||
m_out << "toolx::X11::base_session::base_session :"
|
||||
<< " can't create TOOLX_X11_SESSION_EXIT_STEER Atom." << std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
virtual ~base_session() {
|
||||
clear_dispatchers();
|
||||
if(m_display) ::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
//std::cout << "debug : ~base_session" << std::endl;
|
||||
}
|
||||
protected:
|
||||
base_session(const base_session& a_from)
|
||||
:m_out(a_from.m_out)
|
||||
,m_monitor(a_from.m_monitor)
|
||||
,m_display(0)
|
||||
,m_WM_DELETE_WINDOW_atom(None)
|
||||
,m_SESSION_EXIT_STEER_atom(None)
|
||||
{}
|
||||
base_session& operator=(const base_session& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
|
||||
Atom WM_DELETE_WINDOW_atom() const {return m_WM_DELETE_WINDOW_atom;}
|
||||
Atom SESSION_EXIT_STEER_atom() const {return m_SESSION_EXIT_STEER_atom;}
|
||||
|
||||
bool is_valid() const {return m_display?true:false;}
|
||||
|
||||
Display* display() const {return m_display;}
|
||||
|
||||
bool steer() {
|
||||
if(!m_display) return false;
|
||||
|
||||
while(true) {
|
||||
XEvent xevent;
|
||||
::XNextEvent(m_display,&xevent);
|
||||
if(xevent.type==ClientMessage) {
|
||||
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) break;
|
||||
}
|
||||
dispatch(xevent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sync() {
|
||||
if(!m_display) return false;
|
||||
//::glXWaitX();
|
||||
::XSync(m_display,False);
|
||||
while(true) {
|
||||
XEvent xevent;
|
||||
if(::XPending(m_display)) {
|
||||
::XNextEvent(m_display,&xevent);
|
||||
if(xevent.type==ClientMessage) {
|
||||
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) return false;
|
||||
}
|
||||
dispatch(xevent);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool event_pending(bool& a_is) {
|
||||
if(!m_display) {a_is = false;return false;}
|
||||
a_is = ::XPending(m_display)?true:false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool next_event(bool& a_to_exit) {
|
||||
if(!m_display) {a_to_exit = false;return false;}
|
||||
XEvent xevent;
|
||||
::XNextEvent(m_display,&xevent);
|
||||
if(xevent.type==ClientMessage) {
|
||||
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) {
|
||||
a_to_exit = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
dispatch(xevent);
|
||||
a_to_exit = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool flush() {
|
||||
if(!m_display) return false;
|
||||
::XFlush(m_display);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
|
||||
if(!m_display) return 0L;
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = StructureNotifyMask | ExposureMask
|
||||
| ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
|
||||
| PointerMotionMask
|
||||
| KeyPressMask;
|
||||
|
||||
swa.background_pixel = ::XWhitePixel(m_display,m_monitor);
|
||||
|
||||
Window window = ::XCreateWindow(m_display,
|
||||
::XRootWindow(m_display,m_monitor),
|
||||
a_x,a_y,a_width,a_height,
|
||||
0,
|
||||
(int)CopyFromParent,
|
||||
InputOutput,
|
||||
(Visual*)CopyFromParent,
|
||||
CWEventMask|CWBackPixel,&swa);
|
||||
if(window==0L) {
|
||||
m_out << "toolx::X11::base_session::create_window : can't create a X11 window." << std::endl;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
XTextProperty tp;
|
||||
::XStringListToTextProperty((char**)&a_title,1,&tp);
|
||||
XSizeHints sh;
|
||||
sh.flags = USPosition | USSize;
|
||||
::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0);
|
||||
::XFree(tp.value);
|
||||
|
||||
::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1);
|
||||
return window;
|
||||
}
|
||||
|
||||
void map_raise_window(Window a_window) const {
|
||||
if(!m_display) return;
|
||||
::XMapWindow(m_display,a_window);
|
||||
::XRaiseWindow(m_display,a_window);
|
||||
}
|
||||
|
||||
void show_window(Window a_window) const {
|
||||
if(!m_display) return;
|
||||
|
||||
XWindowAttributes watbs;
|
||||
::XGetWindowAttributes(m_display,a_window,&watbs);
|
||||
if(watbs.map_state!=IsUnmapped) return;
|
||||
|
||||
::XMapWindow(m_display,a_window);
|
||||
::XRaiseWindow(m_display,a_window);
|
||||
|
||||
{XEvent event;
|
||||
::XIfEvent(m_display,&event,wait_map_notify,(char*)a_window);}
|
||||
}
|
||||
|
||||
void hide_window(Window a_window) const {
|
||||
if(!m_display) return;
|
||||
|
||||
XWindowAttributes watbs;
|
||||
::XGetWindowAttributes(m_display,a_window,&watbs);
|
||||
if(watbs.map_state==IsUnmapped) return;
|
||||
|
||||
::XUnmapWindow(m_display,a_window);
|
||||
|
||||
{XEvent event;
|
||||
::XIfEvent(m_display,&event,wait_unmap_notify,(char*)a_window);}
|
||||
}
|
||||
|
||||
void resize_window(Window a_window,unsigned int a_width,unsigned int a_height) const {
|
||||
if(!m_display) return;
|
||||
unsigned int mask = CWWidth | CWHeight | CWBorderWidth;
|
||||
XWindowChanges changes;
|
||||
changes.border_width = 0;
|
||||
changes.width = a_width;
|
||||
changes.height = a_height;
|
||||
::XConfigureWindow(m_display,a_window,mask,&changes);
|
||||
}
|
||||
|
||||
bool window_size(Window a_window,int& a_width,int& a_height) const {
|
||||
if(!m_display) {a_width = 0;a_height = 0;return false;}
|
||||
XWindowAttributes watbs;
|
||||
if(!XGetWindowAttributes(m_display,a_window,&watbs)) {a_width = 0;a_height = 0;return false;}
|
||||
a_width = watbs.width;
|
||||
a_height = watbs.height;
|
||||
return true;
|
||||
}
|
||||
|
||||
void delete_window(Window a_window) const {
|
||||
if(!m_display) return;
|
||||
::XDestroyWindow(m_display,a_window);
|
||||
}
|
||||
|
||||
void set_override_redirect(Window a_window) const {
|
||||
//must be executed before window is mapped.
|
||||
if(!m_display) return;
|
||||
XSetWindowAttributes swa;
|
||||
swa.override_redirect = True;
|
||||
::XChangeWindowAttributes(m_display,a_window,CWOverrideRedirect,&swa);
|
||||
}
|
||||
|
||||
void set_wm_no_decorations(Window a_window) const {
|
||||
//must be executed before window is mapped.
|
||||
if(!m_display) return;
|
||||
|
||||
// struct, mwm_hints_decorations taken from OpenMotif MwmUtils.h.
|
||||
struct{
|
||||
unsigned long flags;
|
||||
unsigned long functions;
|
||||
unsigned long decorations;
|
||||
long inputMode;
|
||||
unsigned long status;
|
||||
} prop;
|
||||
|
||||
//unsigned long mwm_hints_functions = 1L << 0;
|
||||
unsigned long mwm_hints_decorations = 1L << 1;
|
||||
|
||||
Atom atom = ::XInternAtom(m_display,"_MOTIF_WM_HINTS",False);
|
||||
if(atom==None) {
|
||||
m_out << "toolx::X11::base_session::set_wm_no_decorations : can't create/get _MOTIF_WM_HINTS Atom." << std::endl;
|
||||
return;
|
||||
}
|
||||
prop.flags = mwm_hints_decorations;
|
||||
prop.functions = 0;
|
||||
prop.decorations = 0;
|
||||
|
||||
::XChangeProperty(m_display,a_window,atom,atom,32,PropModeReplace,(unsigned char*)&prop,5);
|
||||
}
|
||||
|
||||
bool post(Window a_win,
|
||||
long a_0 = 0,long a_1 = 0,
|
||||
long a_2 = 0,long a_3 = 0,
|
||||
long a_4 = 0) const {
|
||||
if(!m_display) return false;
|
||||
XEvent event;
|
||||
event.type = ClientMessage;
|
||||
event.xclient.display = m_display;
|
||||
event.xclient.window = a_win;
|
||||
event.xclient.message_type = XA_INTEGER;
|
||||
event.xclient.format = 8; /* put 8 because bug with 32 on VMCMS */
|
||||
event.xclient.data.l[0] = a_0;
|
||||
event.xclient.data.l[1] = a_1;
|
||||
event.xclient.data.l[2] = a_2;
|
||||
event.xclient.data.l[3] = a_3;
|
||||
event.xclient.data.l[4] = a_4;
|
||||
//lock();
|
||||
Status stat = ::XSendEvent(m_display,a_win,False,0L,&event);
|
||||
::XFlush(m_display);
|
||||
//unlock();
|
||||
return (stat==0?false:true);
|
||||
}
|
||||
|
||||
bool post_EXIT_STEER(Window a_win) {
|
||||
return post(a_win,SESSION_EXIT_STEER_atom());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
void add_dispatcher(dispatcher* a_dispatcher) {
|
||||
m_dispatchers.push_back(a_dispatcher); //take ownership.
|
||||
}
|
||||
|
||||
void invalidate_dispatchers_with_window(Window a_win){
|
||||
tools_vforit(dispatcher*,m_dispatchers,it) {
|
||||
if((*it)->window()==a_win) (*it)->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void remove_dispatchers_with_window(Window a_win){
|
||||
tools_vforit_npp(dispatcher*,m_dispatchers,it) {
|
||||
if((*it)->window()==a_win) {
|
||||
dispatcher* obj = *it;
|
||||
it = m_dispatchers.erase(it);
|
||||
delete obj;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dispatch(XEvent& a_event) {
|
||||
{tools_vforit_npp(dispatcher*,m_dispatchers,it) {
|
||||
if(!(*it)->is_valid()) {
|
||||
dispatcher* obj = *it;
|
||||
it = m_dispatchers.erase(it);
|
||||
delete obj;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}}
|
||||
tools_vforit(dispatcher*,m_dispatchers,it) {
|
||||
if((*it)->is_valid()) {
|
||||
if((*it)->dispatch(a_event)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected:
|
||||
static Bool wait_map_notify(Display*,XEvent* a_event,char* a_arg){
|
||||
return (a_event->type == MapNotify) && (a_event->xmap.window == (Window)a_arg);
|
||||
}
|
||||
static Bool wait_unmap_notify(Display*,XEvent* a_event,char* a_arg){
|
||||
return (a_event->type == UnmapNotify) && (a_event->xmap.window == (Window)a_arg);
|
||||
}
|
||||
|
||||
void clear_dispatchers() {
|
||||
tools_vforit_npp(dispatcher*,m_dispatchers,it) {
|
||||
dispatcher* obj = *it;
|
||||
it = m_dispatchers.erase(it);
|
||||
delete obj;
|
||||
}
|
||||
m_dispatchers.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
unsigned int m_monitor;
|
||||
Display* m_display;
|
||||
Atom m_WM_DELETE_WINDOW_atom;
|
||||
Atom m_SESSION_EXIT_STEER_atom;
|
||||
std::vector<dispatcher*> m_dispatchers;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_X11_dispatcher
|
||||
#define toolx_X11_dispatcher
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace X11 {
|
||||
|
||||
class dispatcher {
|
||||
protected:
|
||||
#ifdef TOOLS_MEM
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::X11::dispatcher");
|
||||
return s_v;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
virtual bool dispatch(XEvent&) = 0;
|
||||
virtual Window window() const = 0;
|
||||
virtual dispatcher* copy() const = 0;
|
||||
public:
|
||||
dispatcher():m_is_valid(true){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
virtual ~dispatcher(){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
dispatcher(const dispatcher& a_from):m_is_valid(a_from.m_is_valid){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
dispatcher& operator=(const dispatcher& a_from) { m_is_valid = a_from.m_is_valid;return *this;}
|
||||
public:
|
||||
bool is_valid() const {return m_is_valid;}
|
||||
void invalidate() {m_is_valid = false;}
|
||||
protected:
|
||||
bool m_is_valid;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_X11_session
|
||||
#define toolx_X11_session
|
||||
|
||||
#include "base_session"
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
namespace toolx {
|
||||
namespace X11 {
|
||||
|
||||
class session : public base_session {
|
||||
typedef base_session parent;
|
||||
public:
|
||||
//virtual bool make_current(Window a_window) const {
|
||||
// if(!m_display) return false;
|
||||
// if(::glXMakeCurrent(m_display,a_window,m_ctx)==False) {
|
||||
// m_out << "toolx::X11::session::make_current : glXMakeCurrent failed." << std::endl;
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
//virtual bool swap_buffers(Window a_window) const {
|
||||
// if(!m_display) return false;
|
||||
// ::glXSwapBuffers(m_display,a_window);
|
||||
// return true;
|
||||
//}
|
||||
public:
|
||||
session(std::ostream& a_out,unsigned int a_monitor = 0)
|
||||
:parent(a_out,a_monitor)
|
||||
,m_vinfo(0)
|
||||
,m_ctx(0)
|
||||
,m_colormap(0)
|
||||
{
|
||||
if(!m_display) return;
|
||||
|
||||
{int glxMajor, glxMinor;
|
||||
::glXQueryVersion(m_display,&glxMajor,&glxMinor);
|
||||
if(glxMajor<=0) {
|
||||
m_out << "toolx::X11::session::session : bad GLX-Version " << glxMajor << "." << glxMinor << std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
m_vinfo = 0;
|
||||
m_ctx = 0;
|
||||
return;
|
||||
}}
|
||||
|
||||
static const int atbs_alpha[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_ALPHA_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None};
|
||||
|
||||
//NOTE : macOS : glXChooseVisual leaks 640 bytes.
|
||||
m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs_alpha);
|
||||
if(!m_vinfo) {
|
||||
//m_out << "toolx::X11::session::initialize :"
|
||||
// << " can't get a visual with alpha on screen " << m_monitor << ". Try without alpha..."
|
||||
// << std::endl;
|
||||
//m_out << "toolx::X11::session::initialize :"
|
||||
// << " DefaultScreen(m_display): " << DefaultScreen(m_display) << "."
|
||||
// << std::endl;
|
||||
|
||||
static const int atbs[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None};
|
||||
|
||||
m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs);
|
||||
if(!m_vinfo) {
|
||||
m_out << "toolx::X11::session::session :"
|
||||
<< " can't choose a visual on screen " << m_monitor << "."
|
||||
<< std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
m_vinfo = 0;
|
||||
m_ctx = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_TRUE);
|
||||
if(!m_ctx) {
|
||||
m_out << "toolx::X11::session::session :"
|
||||
<< " can't create a glX context with direct rendering."
|
||||
<< std::endl;
|
||||
m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_FALSE);
|
||||
if(!m_ctx) {
|
||||
m_out << "toolx::X11::session::session :"
|
||||
<< " can't create a glX context."
|
||||
<< std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
m_vinfo = 0;
|
||||
m_ctx = 0;
|
||||
return;
|
||||
}
|
||||
//} else {
|
||||
//m_out << "toolx::X11::session::session :"
|
||||
// << " glX context with direct rendering created."
|
||||
// << std::endl;
|
||||
}
|
||||
|
||||
// It is better to create a colormap adapted to the visual.
|
||||
m_colormap = ::XCreateColormap(m_display,::XRootWindow(m_display,m_monitor),m_vinfo->visual,AllocNone);
|
||||
//m_colormap = ::XDefaultColormap(m_display,m_monitor);
|
||||
if(m_colormap==0L) {
|
||||
m_out << "toolx::X11::session::session : XCreateColormap failed." << std::endl;
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
m_vinfo = 0;
|
||||
m_ctx = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
virtual ~session() {
|
||||
if(m_display) {
|
||||
if(m_ctx) {
|
||||
::glXDestroyContext(m_display,m_ctx);
|
||||
m_ctx = 0;
|
||||
}
|
||||
if(m_colormap) {
|
||||
::XFreeColormap(m_display,m_colormap);
|
||||
m_colormap = 0;
|
||||
}
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = 0;
|
||||
}
|
||||
if(m_vinfo) {
|
||||
::XFree(m_vinfo);
|
||||
m_vinfo = 0;
|
||||
}
|
||||
//std::cout << "debug : ~session" << std::endl;
|
||||
}
|
||||
protected:
|
||||
session(const session& a_from)
|
||||
:parent(a_from)
|
||||
,m_vinfo(0)
|
||||
,m_ctx(0)
|
||||
,m_colormap(0)
|
||||
{}
|
||||
session& operator=(const session& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
GLXContext context() const {return m_ctx;}
|
||||
|
||||
Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
|
||||
if(!m_display) return 0L;
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
swa.event_mask = StructureNotifyMask | ExposureMask
|
||||
| ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
|
||||
| PointerMotionMask
|
||||
| KeyPressMask;
|
||||
|
||||
swa.colormap = m_colormap;
|
||||
swa.border_pixel = 0L;
|
||||
|
||||
Window window = ::XCreateWindow(m_display,
|
||||
::XRootWindow(m_display,m_monitor),
|
||||
a_x,a_y,a_width,a_height,
|
||||
0,
|
||||
m_vinfo->depth,
|
||||
InputOutput,
|
||||
m_vinfo->visual,
|
||||
CWBorderPixel|CWColormap|CWEventMask,&swa);
|
||||
|
||||
if(window==0L) {
|
||||
m_out << "toolx::X11::session::create_window :"
|
||||
<< " can't create a X11 window."
|
||||
<< std::endl;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
XTextProperty tp;
|
||||
::XStringListToTextProperty((char**)&a_title,1,&tp);
|
||||
XSizeHints sh;
|
||||
sh.flags = USPosition | USSize;
|
||||
::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0);
|
||||
::XFree(tp.value);
|
||||
|
||||
::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1);
|
||||
return window;
|
||||
}
|
||||
protected:
|
||||
XVisualInfo* m_vinfo;
|
||||
GLXContext m_ctx;
|
||||
Colormap m_colormap;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_X11_sg_viewer
|
||||
#define toolx_X11_sg_viewer
|
||||
|
||||
// not pure X11 version. The class inherits tools::sg::viewer that uses GL.
|
||||
|
||||
#include "session"
|
||||
|
||||
#include "../sg/GL_viewer"
|
||||
|
||||
#include "simple_dispatcher"
|
||||
|
||||
namespace tools{namespace sg{class device_interactor;}}
|
||||
|
||||
namespace toolx {
|
||||
namespace X11 {
|
||||
|
||||
class sg_viewer : public sg::GL_viewer {
|
||||
typedef sg::GL_viewer parent;
|
||||
private:
|
||||
class dispatcher : public simple_dispatcher {
|
||||
typedef simple_dispatcher parent;
|
||||
public:
|
||||
virtual void win_render() {m_sg_viewer.win_render();}
|
||||
virtual void set_size(unsigned int a_width,unsigned int a_height) {m_sg_viewer.set_size(a_width,a_height);}
|
||||
virtual dispatcher* copy() const {return new dispatcher(*this);}
|
||||
public:
|
||||
dispatcher(sg_viewer& a_sg_viewer)
|
||||
:parent(a_sg_viewer.m_session,a_sg_viewer.m_win)
|
||||
,m_sg_viewer(a_sg_viewer){}
|
||||
virtual ~dispatcher(){}
|
||||
protected:
|
||||
dispatcher(const dispatcher& a_from)
|
||||
:parent(a_from)
|
||||
,m_sg_viewer(a_from.m_sg_viewer)
|
||||
{}
|
||||
dispatcher& operator=(const dispatcher& a_from) {
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
sg_viewer& m_sg_viewer;
|
||||
};
|
||||
|
||||
public:
|
||||
sg_viewer(session& a_session,
|
||||
int a_x = 0,int a_y = 0,
|
||||
unsigned int a_width = 500,unsigned int a_height = 500,
|
||||
const std::string& a_win_title = "")
|
||||
:parent(a_session.out(),a_width,a_height)
|
||||
,m_session(a_session)
|
||||
,m_win(0)
|
||||
{
|
||||
if(!m_session.display()) return; //throw
|
||||
m_win = m_session.create_window(a_win_title.c_str(),a_x,a_y,a_width,a_height);
|
||||
if(!m_win) return; //throw
|
||||
m_session.add_dispatcher(new dispatcher(*this));
|
||||
}
|
||||
virtual ~sg_viewer() {
|
||||
if(m_win) {
|
||||
m_session.remove_dispatchers_with_window(m_win);
|
||||
m_session.delete_window(m_win);
|
||||
m_session.sync();
|
||||
}
|
||||
}
|
||||
public:
|
||||
sg_viewer(const sg_viewer& a_from)
|
||||
:parent(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_win(a_from.m_win)
|
||||
{}
|
||||
sg_viewer& operator=(const sg_viewer& a_from){
|
||||
parent::operator=(a_from);
|
||||
m_win = a_from.m_win;
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool has_window() const {return m_win?true:false;} //for SWIG
|
||||
|
||||
Window window() const {return m_win;}
|
||||
|
||||
bool show() {
|
||||
if(!m_win) return false;
|
||||
m_session.show_window(m_win);
|
||||
return true;
|
||||
}
|
||||
|
||||
void win_render() {
|
||||
if(!m_win) return;
|
||||
if(::glXMakeCurrent(m_session.display(),m_win,m_session.context())==False){
|
||||
m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent failed." << std::endl;
|
||||
return;
|
||||
}
|
||||
render(); //viewer::render()
|
||||
::glXSwapBuffers(m_session.display(),m_win);
|
||||
if(::glXMakeCurrent(m_session.display(),None,NULL)==False){
|
||||
m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent(None,NULL) failed." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor*) {}
|
||||
protected:
|
||||
session& m_session;
|
||||
Window m_win;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_X11_simple_dispatcher
|
||||
#define toolx_X11_simple_dispatcher
|
||||
|
||||
#include "base_session"
|
||||
|
||||
#include <tools/saui>
|
||||
|
||||
namespace toolx {
|
||||
namespace X11 {
|
||||
|
||||
class simple_dispatcher : public dispatcher {
|
||||
typedef dispatcher parent;
|
||||
public:
|
||||
virtual void win_render() = 0;
|
||||
virtual void set_size(unsigned int a_width,unsigned int a_height) = 0;
|
||||
public:
|
||||
virtual bool dispatch(XEvent& a_event) {
|
||||
if(!m_win) return false;
|
||||
if(a_event.xany.window!=m_win) return false;
|
||||
if( (a_event.type==Expose) || (a_event.type==ConfigureNotify) ){
|
||||
int width,height;
|
||||
m_session.window_size(m_win,width,height);
|
||||
set_size(width,height); //viewer::set_size()
|
||||
win_render();
|
||||
return true;
|
||||
} else if(a_event.type==ClientMessage) {
|
||||
if(a_event.xclient.data.l[0]==(long)m_session.WM_DELETE_WINDOW_atom()) {
|
||||
m_session.post(m_win,m_session.SESSION_EXIT_STEER_atom());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
virtual Window window() const {return m_win;}
|
||||
public:
|
||||
simple_dispatcher(base_session& a_session,Window a_win)
|
||||
:parent()
|
||||
,m_session(a_session)
|
||||
,m_win(a_win)
|
||||
{}
|
||||
virtual ~simple_dispatcher(){}
|
||||
public:
|
||||
simple_dispatcher(const simple_dispatcher& a_from)
|
||||
:parent(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_win(a_from.m_win)
|
||||
{}
|
||||
simple_dispatcher& operator=(const simple_dispatcher& a_from) {
|
||||
parent::operator=(a_from);
|
||||
m_win = a_from.m_win;
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
base_session& m_session;
|
||||
Window m_win;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,481 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Xt_OpenGLArea
|
||||
#define toolx_Xt_OpenGLArea
|
||||
|
||||
#include <X11/IntrinsicP.h>
|
||||
#include <X11/CoreP.h>
|
||||
#include <X11/CompositeP.h>
|
||||
#include <X11/StringDefs.h>
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace toolx {
|
||||
namespace Xt {
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct _OpenGLAreaClassRec* OpenGLAreaWidgetClass;
|
||||
typedef struct _OpenGLAreaRec* OpenGLAreaWidget;
|
||||
|
||||
typedef struct {
|
||||
int reason;
|
||||
XEvent* event;
|
||||
} XoAnyCallbackStruct;
|
||||
|
||||
#define XoNdoubleBufferOn "doubleBufferOn"
|
||||
#define XoNpaintCallback "paintCallback"
|
||||
#define XoNeventCallback "eventCallback"
|
||||
|
||||
#define XoCR_PAINT 1
|
||||
#define XoCR_EVENT 2
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct {
|
||||
void* extension;
|
||||
} OpenGLAreaClassPart;
|
||||
|
||||
typedef struct _OpenGLAreaClassRec {
|
||||
CoreClassPart core_class;
|
||||
CompositeClassPart composite_class;
|
||||
OpenGLAreaClassPart openGLArea_class;
|
||||
} OpenGLAreaClassRec;
|
||||
|
||||
typedef struct {
|
||||
Boolean doubleBufferOn;
|
||||
XtCallbackList paintCallback;
|
||||
XtCallbackList eventCallback;
|
||||
Visual* visual;
|
||||
Boolean installColormap;
|
||||
GLXContext glContext;
|
||||
} OpenGLAreaPart;
|
||||
|
||||
typedef struct _OpenGLAreaRec {
|
||||
CorePart core;
|
||||
CompositePart composite;
|
||||
OpenGLAreaPart openGLArea;
|
||||
} OpenGLAreaRec;
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
class OpenGLArea {
|
||||
public:
|
||||
static void paint(Widget a_this) {
|
||||
if(!XtIsRealized(a_this)) return;
|
||||
if(make_current(a_this)==1) {
|
||||
XoAnyCallbackStruct value;
|
||||
value.reason = XoCR_PAINT;
|
||||
value.event = 0;
|
||||
::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
|
||||
::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
|
||||
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
|
||||
}
|
||||
}
|
||||
protected:
|
||||
static void initialize_class(void) {}
|
||||
|
||||
static void initialize_widget(Widget a_request,Widget a_this,ArgList,Cardinal*) {
|
||||
if(a_request->core.width<=0) a_this->core.width = 100;
|
||||
if(a_request->core.height<=0) a_this->core.height = 100;
|
||||
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
::printf ("debug : OpenGLArea : InitializeWidget : %s\n",::XtName(a_this));
|
||||
#endif
|
||||
|
||||
OpenGLAreaPart& athis = _athis(a_this);
|
||||
athis.visual = CopyFromParent;
|
||||
athis.installColormap = False;
|
||||
athis.glContext = NULL;
|
||||
|
||||
Display* display;
|
||||
Screen* screen;
|
||||
int iscreen;
|
||||
XVisualInfo* vinfo;
|
||||
display = XtDisplay(a_this);
|
||||
screen = XtScreen(a_this);
|
||||
iscreen = XScreenNumberOfScreen(screen);
|
||||
|
||||
{int error,event;
|
||||
if(::glXQueryExtension(display,&error,&event)==0) {
|
||||
CWarn ("X server does not have OpenGL extensions.\n");
|
||||
}}
|
||||
|
||||
if(athis.doubleBufferOn==True) {
|
||||
int atbs_1[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_ALPHA_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None
|
||||
};
|
||||
vinfo = ::glXChooseVisual (display,iscreen,atbs_1);
|
||||
if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
|
||||
int atbs_2[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None
|
||||
};
|
||||
vinfo = ::glXChooseVisual (display,iscreen,atbs_2);
|
||||
}
|
||||
} else {
|
||||
int atbs_1[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_ALPHA_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
None
|
||||
};
|
||||
vinfo = ::glXChooseVisual (display,iscreen,atbs_1);
|
||||
if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
|
||||
int atbs_2[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
None
|
||||
};
|
||||
vinfo = ::glXChooseVisual (display,iscreen,atbs_2);
|
||||
}
|
||||
}
|
||||
|
||||
if(vinfo==NULL) {
|
||||
CWarn ("Can't choose a visual.\n");
|
||||
} else {
|
||||
a_this->core.depth = vinfo->depth;
|
||||
athis.visual = vinfo->visual;
|
||||
if( (vinfo->depth ==DefaultDepth (display,iscreen)) &&
|
||||
(vinfo->visual==DefaultVisual(display,iscreen)) ) {
|
||||
a_this->core.colormap = XDefaultColormap (display,iscreen);
|
||||
athis.installColormap = False;
|
||||
} else {
|
||||
a_this->core.colormap =
|
||||
XCreateColormap (display,XRootWindow(display,iscreen),vinfo->visual, AllocNone);
|
||||
athis.installColormap = True;
|
||||
}
|
||||
if(a_this->core.colormap==0L) {
|
||||
CWarn ("Can't get/create a X colormap.\n");
|
||||
}
|
||||
athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_TRUE);
|
||||
if(athis.glContext==NULL) {
|
||||
athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_FALSE);
|
||||
if(athis.glContext==NULL) {
|
||||
CWarn ("Can't create a GLX context.\n");
|
||||
}
|
||||
}
|
||||
::XFree(vinfo);
|
||||
}
|
||||
|
||||
::XtAddEventHandler
|
||||
(a_this,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask,0,event_handler,NULL);
|
||||
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : InitializeWidget : end\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void realize_widget(Widget a_this,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : realize_widget : %s\n",XtName(a_this));
|
||||
#endif
|
||||
|
||||
// Have to create window ourselves due to OpenGL that compells it's visual.
|
||||
// In principle colormap is correctly set in a_watbsy.
|
||||
|
||||
OpenGLAreaPart& athis = _athis(a_this);
|
||||
|
||||
::XtCreateWindow(a_this,(unsigned int)InputOutput,athis.visual,*a_mask,a_watbs);
|
||||
|
||||
// Call the Realize procedure (XtInheritRealize) :
|
||||
if(widget_class()->core_class.superclass->core_class.realize!=NULL)
|
||||
(widget_class()->core_class.superclass->core_class.realize)(a_this, a_mask, a_watbs);
|
||||
|
||||
// If window is delete, all seems ok :
|
||||
if(athis.installColormap==True) install_colormap(a_this);
|
||||
|
||||
//make_current(a_this);
|
||||
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : realize_widget : end\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void destroy_widget(Widget a_this) {
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : destroy_widget : begin\n");
|
||||
#endif
|
||||
OpenGLAreaPart& athis = _athis(a_this);
|
||||
if(athis.installColormap==True) {
|
||||
uninstall_colormap (a_this);
|
||||
athis.installColormap = False;
|
||||
::XFreeColormap(XtDisplay(a_this),a_this->core.colormap);
|
||||
}
|
||||
if(athis.glContext!=NULL) {
|
||||
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
|
||||
::glXDestroyContext(XtDisplay(a_this),athis.glContext);
|
||||
athis.glContext = NULL;
|
||||
}
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : destroy_widget : end\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static Boolean set_values(Widget a_current,Widget,Widget a_this,ArgList,Cardinal*) {
|
||||
OpenGLAreaPart& athis = _athis(a_this);
|
||||
if(athis.doubleBufferOn != ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn) {
|
||||
// Can't change buffering here if X window is created.
|
||||
// With OpenGL, buffering fix parameter of the X window.
|
||||
// Buffering must be choosen before the execution of the
|
||||
// Realize method that create the window.
|
||||
if(XtIsRealized(a_this) && (athis.installColormap==True)) {
|
||||
CWarn("Can't change buffering after \"realization\" of the widget.\n");
|
||||
athis.doubleBufferOn = ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn;
|
||||
}
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static void change_widget_size(Widget a_this) {
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : change_widget_size : %s\n",XtName(a_this));
|
||||
#endif
|
||||
|
||||
// Call the Resize procedure (XtInheritResize) :
|
||||
if(widget_class()->core_class.superclass->core_class.resize!=NULL)
|
||||
(widget_class()->core_class.superclass->core_class.resize)(a_this);
|
||||
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : change_widget_size : end\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void draw_widget(Widget a_this,XEvent* a_event,Region a_region) {
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : draw_widget : %s\n",XtName(a_this));
|
||||
#endif
|
||||
|
||||
if(widget_class()->core_class.superclass->core_class.expose!=NULL)
|
||||
(widget_class()->core_class.superclass->core_class.expose)(a_this,a_event,a_region);
|
||||
|
||||
if(make_current(a_this)==1) {
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : draw_widget : %s : make_current ok : call paintCallback...\n",XtName(a_this));
|
||||
#endif
|
||||
XoAnyCallbackStruct value;
|
||||
value.reason = XoCR_PAINT;
|
||||
value.event = a_event;
|
||||
::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
|
||||
::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
|
||||
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
|
||||
}
|
||||
|
||||
#ifdef OPENGLAREA_DEBUG
|
||||
printf("debug : OpenGLArea : draw_widget : end\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
static OpenGLAreaPart& _athis(Widget a_this) {return *(&(((OpenGLAreaWidget)a_this)->openGLArea));}
|
||||
static void CWarn(const char* a_msg) {
|
||||
::printf("%s",a_msg);
|
||||
}
|
||||
static void CWarnF(const char* a_format,...) {
|
||||
va_list args;
|
||||
va_start(args,a_format);
|
||||
::vprintf(a_format,args);
|
||||
va_end(args);
|
||||
}
|
||||
static int make_current(Widget a_this) {
|
||||
if(!XtIsRealized(a_this)) return 0;
|
||||
OpenGLAreaPart& athis = _athis(a_this);
|
||||
if(athis.glContext==NULL) return 0;
|
||||
return (int)::glXMakeCurrent(XtDisplay(a_this),XtWindow(a_this),athis.glContext);
|
||||
}
|
||||
|
||||
static void event_handler(Widget a_this,XtPointer,XEvent* a_event ,Boolean*) {
|
||||
XoAnyCallbackStruct value;
|
||||
value.reason = XoCR_EVENT;
|
||||
value.event = a_event;
|
||||
::XtCallCallbacks(a_this,XoNeventCallback,(XtPointer)&value);
|
||||
}
|
||||
|
||||
static void install_colormap(Widget a_this) {
|
||||
// From Mesa/widgets/GLwDrawingArea.c/post_colormap routine.
|
||||
// Could use also XtSetWMColormapWindows.
|
||||
if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
|
||||
Widget shell = get_shell(a_this);
|
||||
if(shell==NULL) return;
|
||||
Display* display = XtDisplay (a_this);
|
||||
Window wthis = XtWindow (a_this);
|
||||
Window wshell = XtWindow (shell);
|
||||
Window* ws = NULL;
|
||||
int wn = 0;
|
||||
::XGetWMColormapWindows (display,wshell, &ws, &wn);
|
||||
// Check if colormap of this is a colormap of a Window in list :
|
||||
XWindowAttributes watbs;
|
||||
XGetWindowAttributes (display,wthis,&watbs);
|
||||
Colormap cmapthis = watbs.colormap;
|
||||
int found = -1;
|
||||
for(int count=0;count<wn;count++) {
|
||||
Colormap cmap;
|
||||
XGetWindowAttributes (display,ws[count],&watbs);
|
||||
cmap = watbs.colormap;
|
||||
if(cmap==cmapthis) {
|
||||
::XFree (ws);
|
||||
return;
|
||||
}
|
||||
if(ws[count]==wshell) {
|
||||
found = count;
|
||||
}
|
||||
}
|
||||
// Have to add window of this in list :
|
||||
if(wn==0) {
|
||||
if(ws!=NULL) ::XFree(ws);
|
||||
ws = (Window*)::malloc( 2 * sizeof(Window));
|
||||
} else {
|
||||
ws = (Window*)::realloc(ws,(wn + 2) * sizeof(Window));
|
||||
}
|
||||
if(ws==NULL) return;
|
||||
if(found==-1) {
|
||||
// Window of shell not in list :
|
||||
ws[wn] = wthis; wn++;
|
||||
ws[wn] = wshell;wn++;
|
||||
} else {
|
||||
ws[found] = wthis;
|
||||
ws[wn] = wshell; wn++; // Shell must be last.
|
||||
}
|
||||
if (::XSetWMColormapWindows(display,wshell, ws, wn)==0) {
|
||||
CWarnF ("install_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
|
||||
}
|
||||
::free(ws);
|
||||
}
|
||||
|
||||
static void uninstall_colormap(Widget a_this) {
|
||||
if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
|
||||
Widget shell = get_shell (a_this);
|
||||
if(shell==NULL) return;
|
||||
Display* display = XtDisplay (a_this);
|
||||
Window wthis = XtWindow (a_this);
|
||||
Window wshell = XtWindow (shell);
|
||||
Window* ws = NULL;
|
||||
int wn = 0;
|
||||
::XGetWMColormapWindows (display,wshell, &ws, &wn);
|
||||
if( (wn==0) || (ws==NULL) ) return;
|
||||
Window* nws = (Window*)::malloc( wn * sizeof(Window));
|
||||
if(nws==NULL) {
|
||||
::XFree (ws);
|
||||
return;
|
||||
}
|
||||
int nwn = 0;
|
||||
for(int count=0;count<wn;count++) {
|
||||
if(ws[count]!=wthis) {
|
||||
nws[nwn] = ws[count];
|
||||
nwn++;
|
||||
}
|
||||
}
|
||||
if(wn!=nwn) {
|
||||
if (::XSetWMColormapWindows(display,wshell, nws, nwn)==0) {
|
||||
CWarnF("uninstall_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
|
||||
}
|
||||
}
|
||||
::XFree (ws);
|
||||
::free (nws);
|
||||
}
|
||||
|
||||
static Widget get_shell(Widget a_this) {
|
||||
Widget widget = a_this;
|
||||
while(1) {
|
||||
if(widget==NULL) return NULL;
|
||||
if(XtIsShell(widget)) return widget;
|
||||
widget = XtParent(widget);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static WidgetClass widget_class() {
|
||||
static XtResource s_resources [] = {
|
||||
{(String)XoNdoubleBufferOn,(String)"DoubleBufferOn",XtRBoolean,sizeof(Boolean),
|
||||
XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
|
||||
{(String)XoNpaintCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
|
||||
XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
|
||||
{(String)XoNeventCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
|
||||
XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
|
||||
};
|
||||
|
||||
static OpenGLAreaClassRec s_openGLAreaClassRec = {
|
||||
// Core Class Part :
|
||||
{
|
||||
(WidgetClass) &compositeClassRec, // pointer to superclass ClassRec
|
||||
(String)"OpenGLArea", // widget resource class name
|
||||
sizeof(OpenGLAreaRec), // size in bytes of widget record
|
||||
initialize_class, // class_initialize
|
||||
NULL, // dynamic initialization
|
||||
FALSE, // has class been initialized?
|
||||
initialize_widget, // initialize
|
||||
NULL, // notify that initialize called
|
||||
realize_widget, // XCreateWindow for widget
|
||||
NULL, // widget semantics name to proc mapWidget
|
||||
0, // number of entries in actions
|
||||
s_resources, // resources for subclass fields
|
||||
XtNumber(s_resources), // number of entries in resources
|
||||
NULLQUARK, // resource class quarkified
|
||||
TRUE, // compress MotionNotify for widget
|
||||
TRUE, // compress Expose events for widget
|
||||
TRUE, // compress enter and leave events
|
||||
TRUE, // select for VisibilityNotify
|
||||
destroy_widget, // free data for subclass pointers
|
||||
change_widget_size, // geom manager changed widget size
|
||||
draw_widget, // rediplay window
|
||||
set_values, // set subclass resource values
|
||||
NULL, // notify that SetValues called
|
||||
XtInheritSetValuesAlmost, // SetValues got "Almost" geo reply
|
||||
NULL, // notify that get_values called
|
||||
XtInheritAcceptFocus, // assign input focus to widget
|
||||
XtVersion, // version of intrinsics used
|
||||
NULL, // list of callback offsets
|
||||
XtInheritTranslations, // translations
|
||||
XtInheritQueryGeometry, // return preferred geometry
|
||||
XtInheritDisplayAccelerator, // display your accelerator
|
||||
NULL // pointer to extension record
|
||||
},
|
||||
// Composite Class Part :
|
||||
{
|
||||
XtInheritGeometryManager, // geometry manager for children
|
||||
XtInheritChangeManaged, // change managed state of child
|
||||
XtInheritInsertChild, // physically add child to parent
|
||||
XtInheritDeleteChild, // physically remove child
|
||||
NULL // pointer to extension record
|
||||
},
|
||||
// OpenGLArea :
|
||||
{
|
||||
NULL
|
||||
}
|
||||
};
|
||||
return (WidgetClass)&s_openGLAreaClassRec;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Xt_session
|
||||
#define toolx_Xt_session
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Shell.h>
|
||||
#include <X11/StringDefs.h>
|
||||
|
||||
namespace toolx {
|
||||
namespace Xt {
|
||||
|
||||
class session {
|
||||
public:
|
||||
session(std::ostream& a_out,int& a_argc,char** a_argv)
|
||||
:m_out(a_out),m_app_context(0),m_app_widget(0)
|
||||
{
|
||||
//LookDSM_Problem();
|
||||
Arg args[1];
|
||||
XtSetArg(args[0],XtNgeometry,XtNewString("100x100"));
|
||||
m_app_widget = ::XtAppInitialize(&m_app_context,"toolx::Xt::session",NULL,(Cardinal)0,&a_argc,a_argv,NULL,args,1);
|
||||
if(!m_app_context || !m_app_widget) {
|
||||
m_app_context = 0;
|
||||
m_app_widget = 0;
|
||||
}
|
||||
}
|
||||
virtual ~session() {
|
||||
if(m_app_widget) {::XtDestroyWidget(m_app_widget);m_app_widget = 0;}
|
||||
if(m_app_context) {::XtDestroyApplicationContext(m_app_context);m_app_context = 0;}
|
||||
}
|
||||
protected:
|
||||
session(const session& a_from)
|
||||
:m_out(a_from.m_out),m_app_context(0),m_app_widget(0)
|
||||
{}
|
||||
session& operator=(const session&){return *this;}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
bool is_valid() {return m_app_context && m_app_widget?true:false;}
|
||||
bool steer() {
|
||||
if(!m_app_context) return false;
|
||||
while(true) {
|
||||
XEvent event;
|
||||
::XtAppNextEvent(m_app_context,&event);
|
||||
::XtDispatchEvent(&event);
|
||||
//if(m_exit) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool sync() {
|
||||
//if(!m_app_widget) return false;
|
||||
//Display* display = XtDisplay(m_app_widget);
|
||||
//::XSync(display,False);
|
||||
if(!m_app_context) return false;
|
||||
while(true) {
|
||||
XtInputMask input = ::XtAppPending(m_app_context);
|
||||
if(input==0) break;
|
||||
XEvent event;
|
||||
::XtAppNextEvent(m_app_context,&event);
|
||||
::XtDispatchEvent(&event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
Widget get_app_widget() {return m_app_widget;}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
bool m_app_owner;
|
||||
XtAppContext m_app_context;
|
||||
Widget m_app_widget;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_Xt_sg_viewer
|
||||
#define toolx_Xt_sg_viewer
|
||||
|
||||
#include "session"
|
||||
|
||||
#include "../sg/GL_viewer"
|
||||
|
||||
#include "OpenGLArea"
|
||||
|
||||
#include <X11/Shell.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include <X11/IntrinsicP.h>
|
||||
|
||||
#include <tools/num2s>
|
||||
#include <tools/sg/device_interactor>
|
||||
#include <tools/sg/keys>
|
||||
|
||||
namespace toolx {
|
||||
namespace Xt {
|
||||
|
||||
class sg_viewer : public sg::GL_viewer {
|
||||
typedef sg::GL_viewer parent;
|
||||
public:
|
||||
sg_viewer(session& a_session,
|
||||
int a_x = 0,int a_y = 0,
|
||||
unsigned int a_width = 500,unsigned int a_height = 500,
|
||||
const std::string& a_win_title = "")
|
||||
:parent(a_session.out(),a_width,a_height)
|
||||
,m_session(a_session)
|
||||
,m_shell(0)
|
||||
,m_glarea(0)
|
||||
,m_interactor(0)
|
||||
{
|
||||
Widget app_widget = a_session.get_app_widget();
|
||||
if(!app_widget) return;
|
||||
|
||||
std::string sgeom;
|
||||
tools::numas(a_width,sgeom);
|
||||
sgeom += "x";
|
||||
tools::numas(a_height,sgeom);
|
||||
sgeom += "+";
|
||||
tools::numas(a_x,sgeom);
|
||||
sgeom += "+";
|
||||
tools::numas(a_y,sgeom);
|
||||
|
||||
Arg args[2];
|
||||
XtSetArg(args[0],XtNgeometry,XtNewString(sgeom.c_str()));
|
||||
XtSetArg(args[1],XtNborderWidth,0);
|
||||
|
||||
m_shell = ::XtAppCreateShell((char*)a_win_title.c_str(),
|
||||
(char*)"sg_viewer_shell",
|
||||
topLevelShellWidgetClass,XtDisplay(app_widget),args,2);
|
||||
::XtSetMappedWhenManaged(m_shell,True);
|
||||
|
||||
m_glarea = ::XtCreateManagedWidget("glarea",OpenGLArea::widget_class(),m_shell,args,0);
|
||||
::XtAddCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this);
|
||||
::XtAddCallback(m_glarea,XoNeventCallback,event_cbk,(XtPointer)this);
|
||||
|
||||
::XtAddCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this);
|
||||
|
||||
::XtRealizeWidget(m_shell);
|
||||
|
||||
//Atom WM_DELETE_WINDOW_atom = ::XInternAtom(XtDisplay(m_shell),"WM_DELETE_WINDOW",False);
|
||||
//::XSetWMProtocols(XtDisplay(m_shell),XtWindow(m_shell),&WM_DELETE_WINDOW_atom,1);
|
||||
}
|
||||
virtual ~sg_viewer() {
|
||||
if(m_shell) {
|
||||
::XtRemoveCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this);
|
||||
::XtRemoveCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this);
|
||||
::XtDestroyWidget(m_shell);
|
||||
}
|
||||
m_shell = 0;
|
||||
m_glarea = 0;
|
||||
}
|
||||
protected:
|
||||
sg_viewer(const sg_viewer& a_from)
|
||||
:parent(a_from)
|
||||
,m_session(a_from.m_session)
|
||||
,m_shell(0)
|
||||
,m_glarea(0)
|
||||
,m_interactor(0)
|
||||
{}
|
||||
sg_viewer& operator=(const sg_viewer& a_from){
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool has_window() const {return m_glarea?true:false;}
|
||||
|
||||
bool show() {
|
||||
if(!m_shell) return false;
|
||||
::XtRealizeWidget(m_shell);
|
||||
::XtMapWidget(m_shell);
|
||||
// Raise window :
|
||||
if(XtIsWidget(m_shell) && XtIsRealized(m_shell) ) {
|
||||
Display* display = XtDisplay(m_shell);
|
||||
Atom atom = ::XInternAtom(display,"WM_DELETE_WINDOW",False);
|
||||
::XSetWMProtocols(display,XtWindow(m_shell),&atom,1);
|
||||
::XRaiseWindow(display,XtWindow(m_shell));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void win_render() {
|
||||
if(m_glarea) OpenGLArea::paint(m_glarea);
|
||||
}
|
||||
|
||||
public:
|
||||
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
|
||||
protected:
|
||||
static void paint_cbk(Widget a_widget,XtPointer a_tag,XtPointer){
|
||||
unsigned int width = a_widget->core.width;
|
||||
unsigned int height = a_widget->core.height;
|
||||
//::printf("debug : toolx::Xt::sg_viewer::paint_cbk : %d %d\n",width,height);
|
||||
sg_viewer* _this = (sg_viewer*)a_tag;
|
||||
_this->set_size(width,height);
|
||||
_this->render();
|
||||
}
|
||||
static void event_cbk(Widget,XtPointer a_tag,XtPointer a_data){
|
||||
sg_viewer* _this = (sg_viewer*)a_tag;
|
||||
if(!_this->m_interactor) return;
|
||||
XoAnyCallbackStruct* data = (XoAnyCallbackStruct*)a_data;
|
||||
XEvent* xevent = data->event;
|
||||
switch( xevent->type ) {
|
||||
case KeyPress:{
|
||||
KeySym key_sym;
|
||||
::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL);
|
||||
tools::sg::key_down_event event(_this->convert(key_sym));
|
||||
_this->m_interactor->key_press(event);
|
||||
}return;
|
||||
case KeyRelease:{
|
||||
KeySym key_sym;
|
||||
::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL);
|
||||
tools::sg::key_up_event event(_this->convert(key_sym));
|
||||
_this->m_interactor->key_release(event);
|
||||
}return;
|
||||
case ButtonPress:{
|
||||
if(xevent->xbutton.button==Button4) { //4=wheel down, or move down double touch on trackpad = zoom in.
|
||||
tools::sg::wheel_rotate_event event(8); //8=cooking.
|
||||
_this->m_interactor->wheel_rotate(event);
|
||||
} else if(xevent->xbutton.button==Button5) { //5=wheel up, or move up double touch on trackpad = zoom out.
|
||||
tools::sg::wheel_rotate_event event(-8); //8=cooking.
|
||||
_this->m_interactor->wheel_rotate(event);
|
||||
} else {
|
||||
tools::sg::mouse_down_event event(xevent->xbutton.x,xevent->xbutton.y);
|
||||
_this->m_interactor->mouse_press(event);
|
||||
}
|
||||
}return;
|
||||
case ButtonRelease:{
|
||||
tools::sg::mouse_up_event event(xevent->xbutton.x,xevent->xbutton.y);
|
||||
_this->m_interactor->mouse_release(event);
|
||||
}return;
|
||||
case MotionNotify:{
|
||||
tools::sg::mouse_move_event event(xevent->xmotion.x,xevent->xmotion.y,0,0,false);
|
||||
_this->m_interactor->mouse_move(event);
|
||||
}return;
|
||||
default:return;}
|
||||
}
|
||||
static void destroy_shell_callback(Widget,XtPointer a_tag,XtPointer) {
|
||||
sg_viewer* _this = (sg_viewer*)a_tag;
|
||||
_this->m_shell = 0;
|
||||
_this->m_glarea = 0;
|
||||
}
|
||||
protected:
|
||||
tools::key_code convert(KeySym a_key) {
|
||||
if(a_key==XK_Shift_L) return tools::sg::key_shift();
|
||||
if(a_key==XK_Shift_R) return tools::sg::key_shift();
|
||||
return a_key;
|
||||
}
|
||||
protected:
|
||||
session& m_session;
|
||||
Widget m_shell;
|
||||
Widget m_glarea;
|
||||
tools::sg::device_interactor* m_interactor;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_glbuf
|
||||
#define toolx_glbuf
|
||||
|
||||
//define of TOOLX_HAS_GL_VBO decided in the build systems.
|
||||
|
||||
// To have prototypes of glGenBuffers,etc...
|
||||
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#elif defined(ANDROID)
|
||||
#elif _WIN32
|
||||
#include <GL/glext.h>
|
||||
#elif __APPLE__
|
||||
#include <OpenGL/glext.h> //Cocoa
|
||||
#else
|
||||
#include <GL/glext.h>
|
||||
#endif
|
||||
|
||||
#endif //TOOLX_HAS_GL_VBO
|
||||
|
||||
#endif
|
||||
+1366
File diff suppressed because it is too large
Load Diff
+72
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_atb
|
||||
#define toolx_hdf5_atb
|
||||
|
||||
// The below is internal methods in the HDF5 lib.
|
||||
|
||||
#include "hdf5_h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
inline herr_t H5LT_get_attribute_mem(hid_t obj_id,const char *attr_name,hid_t mem_type_id,void *data ) {
|
||||
hid_t attr_id;
|
||||
if ( ( attr_id = ::H5Aopen_name( obj_id, attr_name ) ) < 0 ) return -1;
|
||||
if ( ::H5Aread( attr_id, mem_type_id, data ) < 0 ) {
|
||||
::H5Aclose( attr_id );
|
||||
return -1;
|
||||
}
|
||||
if ( ::H5Aclose( attr_id ) < 0 ) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline herr_t find_attr( hid_t loc_id, const char *name, void *op_data) {
|
||||
int ret = 0;
|
||||
char *attr_name = (char*)op_data;
|
||||
if( ::strcmp( name, attr_name ) == 0 ) ret = 1;
|
||||
(void)loc_id;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline herr_t H5LT_find_attribute( hid_t loc_id, const char* attr_name ) {
|
||||
unsigned int attr_num;
|
||||
attr_num = 0;
|
||||
return toolx_H5Aiterate( loc_id, &attr_num, find_attr, (void *)attr_name );
|
||||
}
|
||||
|
||||
inline herr_t H5LT_get_attribute_disk( hid_t loc_id,const char *attr_name,void *attr_out ) {
|
||||
hid_t attr_id;
|
||||
if ( ( attr_id = ::H5Aopen_name( loc_id, attr_name ) ) < 0 ) return -1;
|
||||
|
||||
hid_t attr_type;
|
||||
if ( (attr_type = ::H5Aget_type( attr_id )) < 0 ) {
|
||||
::H5Tclose( attr_type );
|
||||
::H5Aclose( attr_id );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ::H5Aread( attr_id, attr_type, attr_out ) < 0 ) {
|
||||
::H5Tclose( attr_type );
|
||||
::H5Aclose( attr_id );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ::H5Tclose( attr_type ) < 0 ) {
|
||||
::H5Tclose( attr_type );
|
||||
::H5Aclose( attr_id );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ::H5Aclose( attr_id ) < 0 ) return -1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_group_exists
|
||||
#define toolx_hdf5_group_exists
|
||||
|
||||
#include "hdf5_h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
class group_exists_struct {
|
||||
public:
|
||||
group_exists_struct(const std::string& a_what):m_what(a_what),m_found(false){}
|
||||
virtual ~group_exists_struct() {}
|
||||
protected:
|
||||
group_exists_struct(const group_exists_struct& a_from):m_what(a_from.m_what),m_found(a_from.m_found){}
|
||||
group_exists_struct& operator=(const group_exists_struct&){return *this;}
|
||||
public:
|
||||
std::string m_what;
|
||||
bool m_found;
|
||||
};
|
||||
|
||||
inline herr_t group_exists_visit(hid_t a_id,const char* a_name,void* a_tag){ //a_id = parent of a_name object.
|
||||
group_exists_struct* visitor = (group_exists_struct*)a_tag;
|
||||
H5G_stat_t statbuf;
|
||||
::H5Gget_objinfo(a_id,a_name,0,&statbuf);
|
||||
switch(statbuf.type) {
|
||||
case H5G_GROUP:{
|
||||
if(a_name==visitor->m_what) {visitor->m_found=true;return 0;} //found
|
||||
//::H5Giterate(a_id,a_name,NULL,group_exists_visit,visitor);
|
||||
}break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool group_exists(hid_t a_file_id,const std::string& a_name) {
|
||||
group_exists_struct visitor(a_name);
|
||||
::H5Giterate(a_file_id,".",NULL,group_exists_visit,&visitor);
|
||||
return visitor.m_found;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+342
@@ -0,0 +1,342 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_h2file
|
||||
#define toolx_hdf5_h2file
|
||||
|
||||
#include "tools"
|
||||
#include "T_tools"
|
||||
|
||||
#include <tools/histo/histo_data>
|
||||
#include <tools/sout>
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
}}
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
inline bool write_std_map_ss(hid_t a_loc,const std::string& a_name,const std::map<std::string,std::string>& a_map,
|
||||
unsigned int /*a_chunked*/ = 0,unsigned int /*a_compress*/ = 0) {
|
||||
if(!write_scalar<tools::uint64>(a_loc,a_name+"_size",a_map.size())) return false;
|
||||
unsigned int count = 0; //uint for num2s.
|
||||
std::string scount;
|
||||
tools_mforcit(std::string,std::string,a_map,it) {
|
||||
tools::num2s(count,scount);
|
||||
if(!write_string(a_loc,a_name+"_elem_"+scount+"_first",(*it).first)) return false;
|
||||
if(!write_string(a_loc,a_name+"_elem_"+scount+"_secon",(*it).second)) return false;
|
||||
count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool read_std_map_ss(hid_t a_loc,const std::string& a_name,std::map<std::string,std::string>& a_map,
|
||||
unsigned int /*a_chunked*/ = 0,unsigned int /*a_compress*/ = 0) {
|
||||
a_map.clear();
|
||||
tools::uint64 sz;
|
||||
if(!read_scalar<tools::uint64>(a_loc,a_name+"_size",sz)) return false;
|
||||
std::string scount,key,value;
|
||||
for(tools::uint64 count=0;count<sz;count++) {
|
||||
tools::num2s(count,scount);
|
||||
if(!read_string(a_loc,a_name+"_elem_"+scount+"_first",key)) return false;
|
||||
if(!read_string(a_loc,a_name+"_elem_"+scount+"_secon",value)) return false;
|
||||
a_map[key] = value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef tools::histo::histo_data<double,unsigned int,unsigned int,double> histo_data_t;
|
||||
|
||||
inline bool write_hdata(hid_t a_loc,const histo_data_t& a_hdata) {
|
||||
|
||||
if(!write_string(a_loc,"title",a_hdata.m_title)) return false;
|
||||
if(!write_scalar<unsigned int>(a_loc,"dimension",a_hdata.m_dimension)) return false;
|
||||
if(!write_scalar<unsigned int>(a_loc,"bin_number",a_hdata.m_bin_number)) return false;
|
||||
|
||||
if(!write_std_vec<unsigned int>(a_loc,"bin_entries",a_hdata.m_bin_entries)) return false;
|
||||
if(!write_std_vec<double>(a_loc,"bin_Sw",a_hdata.m_bin_Sw)) return false;
|
||||
if(!write_std_vec<double>(a_loc,"bin_Sw2",a_hdata.m_bin_Sw2)) return false;
|
||||
if(!write_std_vec_vec<double>(a_loc,"bin_Sxw",a_hdata.m_bin_Sxw)) return false;
|
||||
if(!write_std_vec_vec<double>(a_loc,"bin_Sx2w",a_hdata.m_bin_Sx2w)) return false;
|
||||
|
||||
// axes :
|
||||
{std::string name,saxis;
|
||||
for(unsigned int iaxis=0;iaxis<a_hdata.m_dimension;iaxis++) {
|
||||
tools::num2s(iaxis,saxis);
|
||||
name = "axis_"+saxis+"_";
|
||||
const histo_data_t::axis_t& _axis = a_hdata.m_axes[iaxis];
|
||||
if(!write_scalar<unsigned int>(a_loc,name+"offset",_axis.m_offset)) return false;
|
||||
if(!write_scalar<unsigned int>(a_loc,name+"number_of_bins",_axis.m_number_of_bins)) return false;
|
||||
if(!write_scalar<double>(a_loc,name+"minimum_value",_axis.m_minimum_value)) return false;
|
||||
if(!write_scalar<double>(a_loc,name+"maximum_value",_axis.m_maximum_value)) return false;
|
||||
if(!write_scalar<bool>(a_loc,name+"fixed",_axis.m_fixed)) return false;
|
||||
if(!write_scalar<double>(a_loc,name+"bin_width",_axis.m_bin_width)) return false;
|
||||
if(!write_std_vec<double>(a_loc,name+"edges",_axis.m_edges)) return false;
|
||||
}}
|
||||
|
||||
// etc :
|
||||
if(!write_std_vec<double>(a_loc,"in_range_plane_Sxyw",a_hdata.m_in_range_plane_Sxyw)) return false;
|
||||
|
||||
// m_annotations :
|
||||
if(!write_std_map_ss(a_loc,"annotations",a_hdata.m_annotations)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class HISTO>
|
||||
inline bool write_histo(std::ostream& a_out,hid_t a_loc,const std::string& a_name,const HISTO& a_histo) {
|
||||
|
||||
hid_t histo = toolx_H5Gcreate(a_loc,a_name.c_str(),0);
|
||||
if(histo<0) {
|
||||
a_out << "toolx::hdf5::write_histo : can't create group for histo " << tools::sout(a_name) << "." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!write_atb(histo,"type","object")) {
|
||||
a_out << "toolx::hdf5::write_histo : write_atb() class failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
if(!write_atb(histo,"class",a_histo.s_cls())) {
|
||||
a_out << "toolx::hdf5::write_histo : write_atb() class failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
int v = 1;
|
||||
if(!write_scalar_atb<int>(histo,"version",v)) {
|
||||
a_out << "toolx::hdf5::write_histo : write_scalar_atb() version failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!write_hdata(histo,a_histo.dac())) {::H5Gclose(histo);return false;}
|
||||
|
||||
::H5Gclose(histo);
|
||||
|
||||
a_histo.not_a_profile(); //trick to be sure to use this function on an histo and not a profile.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class PROFILE>
|
||||
inline bool write_profile(std::ostream& a_out,hid_t a_loc,const std::string& a_name,const PROFILE& a_histo) {
|
||||
|
||||
hid_t histo = toolx_H5Gcreate(a_loc,a_name.c_str(),0);
|
||||
if(histo<0) {
|
||||
a_out << "toolx::hdf5::write_profile : can't create group for histo " << tools::sout(a_name) << "." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!write_atb(histo,"type","object")) {
|
||||
a_out << "toolx::hdf5::write_profile : write_atb() class failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
if(!write_atb(histo,"class",a_histo.s_cls())) {
|
||||
a_out << "toolx::hdf5::write_profile : write_atb() class failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
int v = 1;
|
||||
if(!write_scalar_atb<int>(histo,"version",v)) {
|
||||
a_out << "toolx::hdf5::write_profile : write_scalar_atb() version failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
typename PROFILE::pd_t pdata = a_histo.get_histo_data();
|
||||
|
||||
if(!write_hdata(histo,pdata)) {::H5Gclose(histo);return false;}
|
||||
|
||||
if(!write_bool(histo,"is_profile",pdata.m_is_profile)) {::H5Gclose(histo);return false;}
|
||||
if(!write_std_vec<double>(histo,"bin_Svw",pdata.m_bin_Svw)) {::H5Gclose(histo);return false;}
|
||||
if(!write_std_vec<double>(histo,"bin_Sv2w",pdata.m_bin_Sv2w)) {::H5Gclose(histo);return false;}
|
||||
if(!write_bool(histo,"cut_v",pdata.m_cut_v)) {::H5Gclose(histo);return false;}
|
||||
if(!write_scalar<double>(histo,"min_v",pdata.m_min_v)) {::H5Gclose(histo);return false;}
|
||||
if(!write_scalar<double>(histo,"max_v",pdata.m_max_v)) {::H5Gclose(histo);return false;}
|
||||
|
||||
::H5Gclose(histo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool read_hdata(hid_t a_loc,histo_data_t& a_hdata) {
|
||||
if(!read_string(a_loc,"title",a_hdata.m_title)) return false;
|
||||
if(!read_scalar<unsigned int>(a_loc,"dimension",a_hdata.m_dimension)) return false;
|
||||
if(!read_scalar<unsigned int>(a_loc,"bin_number",a_hdata.m_bin_number)) return false;
|
||||
|
||||
if(!read_std_vec<unsigned int>(a_loc,"bin_entries",a_hdata.m_bin_entries)) return false;
|
||||
if(!read_std_vec<double>(a_loc,"bin_Sw",a_hdata.m_bin_Sw)) return false;
|
||||
if(!read_std_vec<double>(a_loc,"bin_Sw2",a_hdata.m_bin_Sw2)) return false;
|
||||
|
||||
if(!read_std_vec_vec<double>(a_loc,"bin_Sxw",a_hdata.m_bin_Sxw)) return false;
|
||||
if(!read_std_vec_vec<double>(a_loc,"bin_Sx2w",a_hdata.m_bin_Sx2w)) return false;
|
||||
|
||||
// axes :
|
||||
{a_hdata.m_axes.resize(a_hdata.m_dimension);
|
||||
std::string name,saxis;
|
||||
for(unsigned int iaxis=0;iaxis<a_hdata.m_dimension;iaxis++) {
|
||||
tools::num2s(iaxis,saxis);
|
||||
name = "axis_"+saxis+"_";
|
||||
histo_data_t::axis_t& _axis = a_hdata.m_axes[iaxis];
|
||||
if(!read_scalar<unsigned int>(a_loc,name+"offset",_axis.m_offset)) return false;
|
||||
if(!read_scalar<unsigned int>(a_loc,name+"number_of_bins",_axis.m_number_of_bins)) return false;
|
||||
if(!read_scalar<double>(a_loc,name+"minimum_value",_axis.m_minimum_value)) return false;
|
||||
if(!read_scalar<double>(a_loc,name+"maximum_value",_axis.m_maximum_value)) return false;
|
||||
if(!read_scalar<bool>(a_loc,name+"fixed",_axis.m_fixed)) return false;
|
||||
if(!read_scalar<double>(a_loc,name+"bin_width",_axis.m_bin_width)) return false;
|
||||
if(!read_std_vec<double>(a_loc,name+"edges",_axis.m_edges)) return false;
|
||||
}}
|
||||
|
||||
// etc :
|
||||
if(!read_std_vec<double>(a_loc,"in_range_plane_Sxyw",a_hdata.m_in_range_plane_Sxyw)) return false;
|
||||
|
||||
// m_annotations :
|
||||
if(!read_std_map_ss(a_loc,"annotations",a_hdata.m_annotations)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class HISTO>
|
||||
inline bool read_histo(std::ostream& a_out,hid_t a_loc,const std::string& a_name,HISTO*& a_histo,bool a_verb_class = true) {
|
||||
a_histo = 0;
|
||||
|
||||
//if(::H5Gget_objinfo(a_loc,a_name.c_str(),0,NULL)<0) {return false;}
|
||||
|
||||
hid_t histo = toolx_H5Gopen(a_loc,a_name.c_str());
|
||||
if(histo<0) {
|
||||
a_out << "toolx::hdf5::read_histo : can't open group." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sclass;
|
||||
if(!read_atb(histo,"class",sclass)) {
|
||||
a_out << "toolx::hdf5::read_histo : can't read_atb() class." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sclass!=HISTO::s_class()) {
|
||||
if(a_verb_class) {
|
||||
a_out << "toolx::hdf5::read_histo :"
|
||||
<< " read class " << tools::sout(sclass) << " not " << tools::sout(HISTO::s_class()) << std::endl;
|
||||
}
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
int v;
|
||||
if(!read_atb(histo,"version",v)) {
|
||||
a_out << "toolx::hdf5::read_histo : read_atb version failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
histo_data_t hdata;
|
||||
|
||||
if(!read_hdata(histo,hdata)) {::H5Gclose(histo);return false;}
|
||||
|
||||
::H5Gclose(histo);
|
||||
|
||||
hdata.update_fast_getters();
|
||||
|
||||
a_histo = new HISTO;
|
||||
a_histo->copy_from_data(hdata);
|
||||
a_histo->not_a_profile(); //trick to be sure to use this function on an histo and not a profile.
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class PROFILE>
|
||||
inline bool read_profile(std::ostream& a_out,hid_t a_loc,const std::string& a_name,PROFILE*& a_histo,bool a_verb_class = true) {
|
||||
a_histo = 0;
|
||||
|
||||
hid_t histo = toolx_H5Gopen(a_loc,a_name.c_str());
|
||||
if(histo<0) {
|
||||
a_out << "toolx::hdf5::read_profile : can't open group." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sclass;
|
||||
if(!read_atb(histo,"class",sclass)) {
|
||||
a_out << "toolx::hdf5::read_profile : can't read_atb() class." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sclass!=PROFILE::s_class()) {
|
||||
if(a_verb_class) {
|
||||
a_out << "toolx::hdf5::read_profile :"
|
||||
<< " read class " << tools::sout(sclass) << " not " << tools::sout(PROFILE::s_class()) << std::endl;
|
||||
}
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
int v;
|
||||
if(!read_atb(histo,"version",v)) {
|
||||
a_out << "toolx::hdf5::read_profile : read_atb version failed." << std::endl;
|
||||
::H5Gclose(histo);
|
||||
return false;
|
||||
}
|
||||
|
||||
typename PROFILE::pd_t pdata;
|
||||
|
||||
if(!read_hdata(histo,pdata)) {::H5Gclose(histo);return false;}
|
||||
|
||||
if(!read_bool(histo,"is_profile",pdata.m_is_profile)) {::H5Gclose(histo);return false;}
|
||||
if(!read_std_vec<double>(histo,"bin_Svw",pdata.m_bin_Svw)) {::H5Gclose(histo);return false;}
|
||||
if(!read_std_vec<double>(histo,"bin_Sv2w",pdata.m_bin_Sv2w)) {::H5Gclose(histo);return false;}
|
||||
if(!read_bool(histo,"cut_v",pdata.m_cut_v)) {::H5Gclose(histo);return false;}
|
||||
if(!read_scalar<double>(histo,"min_v",pdata.m_min_v)) {::H5Gclose(histo);return false;}
|
||||
if(!read_scalar<double>(histo,"max_v",pdata.m_max_v)) {::H5Gclose(histo);return false;}
|
||||
|
||||
::H5Gclose(histo);
|
||||
|
||||
pdata.update_fast_getters();
|
||||
|
||||
a_histo = new PROFILE;
|
||||
a_histo->copy_from_data(pdata);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool read_class_version(std::ostream& a_out,hid_t a_loc,const std::string& a_name,
|
||||
std::string& a_class,int& a_version,bool a_verbose = true) {
|
||||
hid_t id = toolx_H5Gopen(a_loc,a_name.c_str());
|
||||
if(id<0) {
|
||||
if(a_verbose) a_out << "toolx::hdf5::read_class_version : can't open group." << std::endl;
|
||||
a_class.clear();
|
||||
a_version = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!read_atb(id,"class",a_class)) {
|
||||
if(a_verbose) a_out << "toolx::hdf5::read_class_version : can't read_atb() class." << std::endl;
|
||||
::H5Gclose(id);
|
||||
a_class.clear();
|
||||
a_version = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!read_atb(id,"version",a_version)) {
|
||||
if(a_verbose) a_out << "toolx::hdf5::read_class_version : read_atb version failed." << std::endl;
|
||||
::H5Gclose(id);
|
||||
a_class.clear();
|
||||
a_version = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
::H5Gclose(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_h
|
||||
#define toolx_hdf5_h
|
||||
|
||||
#include <hdf5.h>
|
||||
|
||||
#if (H5_VERS_MAJOR>=1) && (H5_VERS_MINOR<=6)
|
||||
#define toolx_H5Dopen H5Dopen
|
||||
#define toolx_H5Dcreate H5Dcreate
|
||||
#define toolx_H5Acreate H5Acreate
|
||||
#define toolx_H5Tarray_create H5Tarray_create
|
||||
#define toolx_H5Tget_array_dims H5Tget_array_dims
|
||||
#define toolx_H5Gcreate H5Gcreate
|
||||
#define toolx_H5Gopen H5Gopen
|
||||
#define toolx_H5Aiterate H5Aiterate
|
||||
#define toolx_H5free_memory free
|
||||
#else
|
||||
#define toolx_H5Dopen H5Dopen1
|
||||
#define toolx_H5Dcreate H5Dcreate1
|
||||
#define toolx_H5Acreate H5Acreate1
|
||||
#define toolx_H5Tarray_create H5Tarray_create1
|
||||
#define toolx_H5Tget_array_dims H5Tget_array_dims1
|
||||
#define toolx_H5Gcreate H5Gcreate1
|
||||
#define toolx_H5Gopen H5Gopen1
|
||||
#define toolx_H5Aiterate H5Aiterate1
|
||||
#define toolx_H5free_memory H5free_memory
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_header
|
||||
#define toolx_hdf5_header
|
||||
|
||||
#include "tools"
|
||||
#include "T_tools"
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
inline bool write_header(hid_t a_file,int a_version = 1) {
|
||||
hid_t header = toolx_H5Gcreate(a_file,"header",0);
|
||||
if(header<0) return false;
|
||||
if(!write_atb(header,"writer","exlib")) {::H5Gclose(header);return false;}
|
||||
if(!write_scalar_atb<int>(header,"data_schema_version",a_version)) {::H5Gclose(header);return false;}
|
||||
::H5Gclose(header);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool read_header(hid_t a_file,std::string& a_writer,int& a_data_schema_version) {
|
||||
hid_t header = toolx_H5Gopen(a_file,"header");
|
||||
if(header<0) {a_writer.clear();a_data_schema_version=0;return false;}
|
||||
if(!read_atb(header,"writer",a_writer)) {::H5Gclose(header);a_writer.clear();a_data_schema_version=0;return false;}
|
||||
if(!read_atb(header,"data_schema_version",a_data_schema_version)) {
|
||||
::H5Gclose(header);
|
||||
a_writer.clear();a_data_schema_version=0;
|
||||
return false;
|
||||
}
|
||||
::H5Gclose(header);
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+1111
File diff suppressed because it is too large
Load Diff
+319
@@ -0,0 +1,319 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_pages
|
||||
#define toolx_hdf5_pages
|
||||
|
||||
#include "T_tools"
|
||||
#include "tools"
|
||||
|
||||
#include <tools/S_STRING>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#endif
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
TOOLS_GLOBAL_STRING(pages)
|
||||
TOOLS_GLOBAL_STRING(entries)
|
||||
TOOLS_GLOBAL_STRING(columns)
|
||||
TOOLS_GLOBAL_STRING(names)
|
||||
TOOLS_GLOBAL_STRING(forms)
|
||||
|
||||
class pages {
|
||||
TOOLS_SCLASS(toolx::hdf5::pages)
|
||||
public:
|
||||
pages(std::ostream& a_out,
|
||||
hid_t a_group,const std::string& a_name,const std::string& a_form,
|
||||
bool a_write,unsigned int a_compress)
|
||||
:m_out(a_out),m_name(a_name),m_form(a_form)
|
||||
//,m_type(0),m_size(0)
|
||||
,m_group(-1),m_dataset(-1),m_write(a_write),m_compress(a_compress),m_entries(0),m_pos(0){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
if(m_write) {
|
||||
m_group = toolx_H5Gcreate(a_group,m_name.c_str(),0);
|
||||
if(m_group<0) {
|
||||
m_out << "pages::pages : can't create group for column " << m_name << "." << std::endl;
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
if(!write_atb(m_group,"class",s_class())) {
|
||||
m_out << "pages::pages : write_atb(class) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
int v = 1;
|
||||
if (!write_scalar_atb<int>(m_group,"version",v)) {
|
||||
m_out << "pages::pages : write_scalar_atb(version) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
m_group = toolx_H5Gopen(a_group,m_name.c_str());
|
||||
if(m_group<0) {
|
||||
m_out << "pages::pages : can't open group for column " << m_name << "." << std::endl;
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
if(!read_scalar<tools::uint64>(m_group,s_entries(),m_entries)) {
|
||||
m_out << "pages::pages : read_scalar(entries) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual ~pages(){
|
||||
if(m_write) {
|
||||
if(!write_scalar<tools::uint64>(m_group,s_entries(),m_entries)) {
|
||||
m_out << "pages::~pages : write_scalar(entries) failed." << std::endl;
|
||||
}
|
||||
if(m_dataset>=0) ::H5Dclose(m_dataset);
|
||||
}
|
||||
::H5Gclose(m_group);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
pages(const pages& a_from):m_out(a_from.m_out){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
pages& operator=(const pages&){return *this;}
|
||||
public:
|
||||
bool is_valid() const {return m_group<0?false:true;}
|
||||
|
||||
const std::string& name() const {return m_name;}
|
||||
const std::string& form() const {return m_form;}
|
||||
//int type() const {return m_type;}
|
||||
//unsigned int size() const {return m_size;}
|
||||
tools::uint64 entries() const {return m_entries;}
|
||||
tools::uint64 pos() const {return m_pos;}
|
||||
void reset_pos() {m_pos = 0;}
|
||||
|
||||
template <class TYPE>
|
||||
bool write_page(size_t a_size,const TYPE* a_array) {
|
||||
if(!m_pos) {
|
||||
if(!write_array<TYPE>(m_group,s_pages(),a_size,a_array,a_size?a_size:32,m_compress)) {
|
||||
m_out << "pages::write_page : write_array<TYPE>() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
|
||||
if(m_dataset<0) {
|
||||
m_out << "pages::write_page : H5Dopen failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!write_append_array_dataset<TYPE>(m_dataset,a_size,a_array)) {
|
||||
m_out << "pages::write_page : write_append_array_dataset<TYPE>() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_pos += a_size;
|
||||
m_entries = m_pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
bool read_page(size_t a_size,TYPE* a_array) {
|
||||
//it is assumed that a_array can contain a_size*sizeof(TYPE) bytes.
|
||||
unsigned int _size = a_size;
|
||||
unsigned int n = 0;
|
||||
TYPE* array = 0;
|
||||
if(!read_sub_array<TYPE>(m_group,s_pages(),(unsigned int)m_pos,(unsigned int)_size,n,array)) {
|
||||
m_out << "pages::read_page : read_sub_array<TYPE>() failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(n!=_size) {
|
||||
m_out << "pages::read_page : size mismatch. Requested " << _size << ", got "<< n << "." << std::endl;
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
|
||||
{TYPE* rpos = (TYPE*)array;
|
||||
TYPE* wpos = (TYPE*)a_array;
|
||||
for(size_t i=0;i<n;i++,rpos++,wpos++) *wpos = *rpos;
|
||||
for(size_t i=n;i<_size;i++,rpos++,wpos++) *wpos = TYPE();}
|
||||
|
||||
delete [] array;
|
||||
|
||||
m_pos += n;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
bool write_vlen(size_t a_size,const TYPE* a_array) {
|
||||
if(!m_pos) {
|
||||
if(!hdf5::write_vlen<TYPE>(m_group,s_pages(),a_size,a_array,a_size?a_size:32,m_compress)) {
|
||||
m_out << "pages::write_vlen : write_vlen<TYPE>() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
|
||||
if(m_dataset<0) {
|
||||
m_out << "pages::write_vlen : H5Dopen failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!write_append_vlen_dataset<TYPE>(m_dataset,a_size,a_array)) {
|
||||
m_out << "pages::write_vlen : write_append_vlen_dataset<TYPE>() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_pos++;
|
||||
m_entries++;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class TYPE>
|
||||
bool read_vlen(size_t& a_size,TYPE*& a_array) {
|
||||
//it is assumed that a_array can contain a_size*sizeof(TYPE) bytes.
|
||||
unsigned int sz;
|
||||
if(!read_sub_vlen<TYPE>(m_group,s_pages(),(unsigned int)m_pos,sz,a_array)) {
|
||||
m_out << "pages::read_vlen : read_sub_vlen<TYPE>() failed." << std::endl;
|
||||
a_size = 0;
|
||||
a_array = 0;
|
||||
return false;
|
||||
}
|
||||
a_size = sz;
|
||||
m_pos++;
|
||||
m_entries++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_string(const std::string& a_string) {
|
||||
if(!m_pos) {
|
||||
if(!hdf5::write_string_dataset(m_group,s_pages(),a_string,128,m_compress)) { //32=>enforce extendable.
|
||||
m_out << "pages::write_string : hdf5::write_string() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
|
||||
if(m_dataset<0) {
|
||||
m_out << "pages::write_string : H5Dopen failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!write_append_string_dataset(m_dataset,a_string)) {
|
||||
m_out << "pages::write_string : write_append_string_dataset() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_pos++;
|
||||
m_entries++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_string(std::string& a_string) {
|
||||
if(!read_sub_string(m_group,s_pages(),(unsigned int)m_pos,a_string)) {
|
||||
m_out << "pages::read_string : read_sub_string() failed." << std::endl;
|
||||
a_string.clear();
|
||||
return false;
|
||||
}
|
||||
m_pos++;
|
||||
m_entries++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool write_string(const std::string& a_string) {return write_vlen<char>(a_string.size(),a_string.c_str());}
|
||||
|
||||
bool read_string(std::string& a_string) {
|
||||
size_t sz;char* _data;
|
||||
if(!read_vlen<char>(sz,_data)) {a_string.clear();return false;}
|
||||
a_string.resize(sz);
|
||||
for(size_t index=0;index<sz;index++) a_string[index] = _data[index];
|
||||
delete [] _data;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
bool write_strings(size_t a_number,void* a_array) {
|
||||
size_t sz = m_size*a_number;
|
||||
char* buffer = new char[sz];
|
||||
{char* pos = buffer;
|
||||
for(size_t index=0;index<sz;index++,pos++) *pos = ' ';}
|
||||
|
||||
{char** strings = (char**)a_array;
|
||||
char* pos = buffer;
|
||||
size_t ls;
|
||||
for(size_t index=0;index<a_number;index++) {
|
||||
char* ss = strings[index];
|
||||
ls = ::strlen(ss);
|
||||
::memcpy(pos,ss,ls); //do not copy the ending 0.
|
||||
*(pos+m_size-1) = 0;
|
||||
pos += m_size;
|
||||
}}
|
||||
|
||||
if(!m_pos) {
|
||||
unsigned int chunked = 32*m_size; //<size>A strings.
|
||||
if(!write_array<char>(m_group,s_pages(),sz,buffer,chunked,m_compress)) {
|
||||
m_out << "pages::write_strings : write_strings() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
|
||||
if(m_dataset<0) {
|
||||
m_out << "pages::write_strings : H5Dopen failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!write_append_array_dataset<char>(m_dataset,sz,buffer)) {
|
||||
m_out << "pages::write_strings : write_append_strings() failed. Pos " << m_pos << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_pos += a_number;
|
||||
m_entries = m_pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_strings(size_t a_size,char* a_array) {
|
||||
unsigned int _size = a_size*m_size;
|
||||
unsigned int n = 0;
|
||||
char* array = 0;
|
||||
if(!read_sub_array<char>(m_group,s_pages(),m_pos,_size,n,array)) {
|
||||
m_out << "pages::read_strings : read_sub_array<char>() failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if(n!=_size) {
|
||||
m_out << "pages::read_strings : size mismatch. Requested " << _size << ", got "<< n << "." << std::endl;
|
||||
delete [] array;
|
||||
return false;
|
||||
}
|
||||
char* pos = array;
|
||||
{char** strings = (char**)a_array;
|
||||
for(size_t index=0;index<a_size;index++) {
|
||||
::memcpy(strings[index],pos,m_size*sizeof(char));
|
||||
pos += m_size;
|
||||
}}
|
||||
delete [] array;
|
||||
m_pos += n;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
std::string m_name;
|
||||
std::string m_form;
|
||||
//int m_type;
|
||||
//unsigned int m_size;
|
||||
hid_t m_group;
|
||||
hid_t m_dataset;
|
||||
bool m_write;
|
||||
unsigned int m_compress; //if write.
|
||||
tools::uint64 m_entries;
|
||||
tools::uint64 m_pos;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_hdf5_store
|
||||
#define toolx_hdf5_store
|
||||
|
||||
#include "pages"
|
||||
|
||||
#include <tools/vmanip>
|
||||
#include <tools/sout>
|
||||
|
||||
namespace toolx {
|
||||
namespace hdf5 {
|
||||
|
||||
class store {
|
||||
public:
|
||||
TOOLS_SCLASS(toolx::hdf5::store)
|
||||
public:
|
||||
store(std::ostream& a_out,hid_t a_group,const std::string& a_name,bool a_write,unsigned int a_compress)
|
||||
:m_out(a_out)
|
||||
,m_write(a_write)
|
||||
,m_compress(a_compress) //used at write.
|
||||
,m_group(-1)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
if(m_write) {
|
||||
if(a_name.empty()) {
|
||||
a_out << "toolx::hdf5::store::store : string a_name is empty." << std::endl;
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
m_group = toolx_H5Gcreate(a_group,a_name.c_str(),0);
|
||||
if(m_group<0) {
|
||||
a_out << "toolx::hdf5::store::store : can't create " << a_name << " group." << std::endl;
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
if(!write_atb(m_group,"type","object")) {
|
||||
m_out << "toolx::hdf5::store::store : write_atb(type) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
if(!write_atb(m_group,"class",s_class())) {
|
||||
m_out << "toolx::hdf5::store::store : write_atb(class) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
int v = 2; //1->2 add "type" atb.
|
||||
if(!write_scalar_atb<int>(m_group,"version",v)) {
|
||||
m_out << "toolx::hdf5::store::store : write_scalar_atb(version) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
} else { // to read.
|
||||
m_group = toolx_H5Gopen(a_group,a_name.c_str());
|
||||
if(m_group<0) {
|
||||
a_out << "toolx::hdf5::store::store : can't open " << a_name << " group." << std::endl;
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> names;
|
||||
if(!read_array_string(m_group,s_names(),names)) {
|
||||
m_out << "toolx::hdf5::store::store : read_array_string(names) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> TFORMs;
|
||||
if(!read_array_string(m_group,s_forms(),TFORMs)) {
|
||||
m_out << "toolx::hdf5::store::store : read_array_string(tforms) failed." << std::endl;
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
if(names.size()!=TFORMs.size()) {
|
||||
m_out << "toolx::hdf5::store::store : names/TFORMs size mismatch." << std::endl;
|
||||
m_out << "names :" << std::endl;
|
||||
{tools_vforcit(std::string,names,it) m_out << *it << std::endl;}
|
||||
m_out << "TFORMs :" << std::endl;
|
||||
{tools_vforcit(std::string,TFORMs,it) m_out << *it << std::endl;}
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
for(size_t index=0;index<names.size();index++) {
|
||||
if(!create_pages(names[index],TFORMs[index])) {
|
||||
m_out << "toolx::hdf5::store::store : can't create hdf5_column "
|
||||
<< tools::sout(names[index]) << "." << std::endl;
|
||||
tools::safe_clear(m_pagess);
|
||||
::H5Gclose(m_group);
|
||||
m_group = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual ~store(){
|
||||
if(m_write) {
|
||||
tools::uint64 _entries;
|
||||
if(!entries(_entries)) {
|
||||
m_out << "toolx::hdf5::store::~store : not same entries on all columns. Write 0." << std::endl;
|
||||
}
|
||||
if(m_group<0) { //constructor may have failed.
|
||||
} else {
|
||||
if(!write_scalar<tools::uint64>(m_group,s_entries(),_entries)) {
|
||||
m_out << "toolx::hdf5::store::~store : write_scalar(entries) failed." << std::endl;
|
||||
}
|
||||
if(!write_scalar<unsigned int>(m_group,s_columns(),m_pagess.size())) {
|
||||
m_out << "toolx::hdf5::store::~store : write_scalar(columns) failed." << std::endl;
|
||||
}
|
||||
{std::vector<std::string> names;
|
||||
tools_vforcit(pages*,m_pagess,it) names.push_back((*it)->name());
|
||||
//{m_out << "debug : write : names :" << std::endl;
|
||||
// tools_vforcit(std::string,names,it) m_out << *it << std::endl;}
|
||||
if(!write_array_string(m_group,s_names(),names)) {
|
||||
m_out << "toolx::hdf5::store::~store : write_array_string(names) failed." << std::endl;
|
||||
}}
|
||||
{std::vector<std::string> TFORMs;
|
||||
tools_vforcit(pages*,m_pagess,it) TFORMs.push_back((*it)->form());
|
||||
//{m_out << "debug : write : TFORMs :" << std::endl;
|
||||
// tools_vforcit(std::string,TFORMs,it) m_out << *it << std::endl;}
|
||||
if(!write_array_string(m_group,s_forms(),TFORMs)) {
|
||||
m_out << "toolx::hdf5::store::~store : write_array_string(tforms) failed." << std::endl;
|
||||
}}
|
||||
}
|
||||
}
|
||||
tools::safe_clear(m_pagess);
|
||||
if(m_group<0) { //constructor may have failed.
|
||||
} else {
|
||||
::H5Gclose(m_group);
|
||||
}
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
store(const store& a_from)
|
||||
:m_out(a_from.m_out)
|
||||
,m_name(a_from.m_name)
|
||||
,m_compress(a_from.m_compress)
|
||||
,m_group(-1)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
store& operator=(const store&){return *this;}
|
||||
public:
|
||||
std::ostream& out() const {return m_out;}
|
||||
//bool fill(tools::uint32 &a_n){a_n = 0;return true;}
|
||||
|
||||
bool entries(tools::uint64& a_entries) const {
|
||||
if(m_pagess.empty()) {a_entries = 0;return true;}
|
||||
a_entries = m_pagess.front()->entries();
|
||||
tools_vforcit(pages*,m_pagess,it) {
|
||||
if((*it)->entries()!=a_entries) {
|
||||
m_out << "toolx::hdf5::store::entries : not same entries on all columns."
|
||||
<< " Front " << a_entries << ", it " << (*it)->entries() << "." << std::endl;
|
||||
a_entries = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pages* create_pages(const std::string& a_name,const std::string& a_form) {
|
||||
//::printf("debug : create_pages %s %s\n",a_name.c_str(),a_form.c_str());
|
||||
pages* _pages = new pages(m_out,m_group,a_name,a_form,m_write,m_compress);
|
||||
if(!_pages->is_valid()) {
|
||||
m_out << "toolx::hdf5::store::create_column : can't create pages." << std::endl;
|
||||
delete _pages;
|
||||
return 0;
|
||||
}
|
||||
m_pagess.push_back(_pages);
|
||||
return _pages;
|
||||
}
|
||||
/*
|
||||
pages* find_column(unsigned int a_index) {
|
||||
if(a_index>=m_pagess.size()) {
|
||||
m_out << "toolx::hdf5::store::find_column : out of range index." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return m_pagess[a_index];
|
||||
}
|
||||
const std::vector<pages*>& columns() const {return m_pagess;}*/
|
||||
|
||||
hid_t group() const {return m_group;}
|
||||
unsigned int compress_level() const {return m_compress;}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
std::string m_name;
|
||||
bool m_write;
|
||||
unsigned int m_compress;
|
||||
hid_t m_group;
|
||||
std::vector<pages*> m_pagess;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+1048
File diff suppressed because it is too large
Load Diff
+266
@@ -0,0 +1,266 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_mpi_hmpi
|
||||
#define toolx_mpi_hmpi
|
||||
|
||||
// code to send, receive histos through MPI.
|
||||
|
||||
#include <tools/histo/hmpi>
|
||||
#include <tools/histo/hd2mpi>
|
||||
|
||||
#include <tools/histo/h1d>
|
||||
#include <tools/histo/h2d>
|
||||
#include <tools/histo/h3d>
|
||||
#include <tools/histo/p1d>
|
||||
#include <tools/histo/p2d>
|
||||
|
||||
#include "wrmpi"
|
||||
|
||||
namespace toolx {
|
||||
namespace mpi {
|
||||
|
||||
class hmpi : public virtual tools::histo::hmpi {
|
||||
typedef tools::histo::hmpi parent;
|
||||
protected:
|
||||
typedef unsigned int num_t;
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::mpi::hmpi");
|
||||
return s_v;
|
||||
}
|
||||
public:
|
||||
virtual bool pack(const tools::histo::h1d& a_h) {
|
||||
if(!m_wrmpi.spack(a_h.s_cls())) return false;
|
||||
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(const tools::histo::h2d& a_h) {
|
||||
if(!m_wrmpi.spack(a_h.s_cls())) return false;
|
||||
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(const tools::histo::h3d& a_h) {
|
||||
if(!m_wrmpi.spack(a_h.s_cls())) return false;
|
||||
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(const tools::histo::p1d& a_h) {
|
||||
if(!m_wrmpi.spack(a_h.s_cls())) return false;
|
||||
if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(const tools::histo::p2d& a_h) {
|
||||
if(!m_wrmpi.spack(a_h.s_cls())) return false;
|
||||
if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false;
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
virtual bool beg_send(unsigned int a_nhist) {
|
||||
m_wrmpi.pack_reset();
|
||||
return m_wrmpi.pack(a_nhist);
|
||||
}
|
||||
virtual bool send(int a_dest) {
|
||||
if(::MPI_Send(m_wrmpi.buffer(),m_wrmpi.ipos(),MPI_CHAR,a_dest,m_tag,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::hmpi::send : rank " << m_rank << " : MPI_Send failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_wrmpi.pack_reset();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
virtual bool wait_histos(int a_src,std::vector< std::pair<std::string,void*> >& a_hists) {
|
||||
a_hists.clear();
|
||||
|
||||
typedef std::pair<std::string,void*> class_pointer;
|
||||
|
||||
MPI_Status status;
|
||||
if(::MPI_Probe(a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Probe : failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int buffer_size = 0;
|
||||
if(::MPI_Get_count(&status,MPI_CHAR,&buffer_size)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Get_count : failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!buffer_size) {
|
||||
m_out << "exlb::mpi::wait_histos : MPI_Get_count returns zero data." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_verbose) m_out << "rank " << m_rank << " : get_count " << buffer_size << std::endl;
|
||||
|
||||
char* buffer = new char[buffer_size];
|
||||
if(!buffer) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : can't alloc buffer of size " << buffer_size << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(::MPI_Recv(buffer,buffer_size,MPI_CHAR,a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Recv : failed." << std::endl;
|
||||
delete [] buffer;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_verbose) m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : unpack data ..." << std::endl;
|
||||
|
||||
wrmpi _mpi(m_out,m_comm,buffer_size,buffer); //give ownership of buffer to _mpi.
|
||||
|
||||
num_t nhist;
|
||||
if(!_mpi.unpack(nhist)) return false;
|
||||
|
||||
if(m_verbose)
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : number of histos to unpack " << nhist << std::endl;
|
||||
|
||||
{for(num_t ihist=0;ihist<nhist;ihist++) {
|
||||
|
||||
std::string scls;
|
||||
if(!_mpi.sunpack(scls)) return false;
|
||||
|
||||
if(scls==tools::histo::h1d::s_class()) {
|
||||
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
|
||||
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
|
||||
tools::histo::h1d* h = new tools::histo::h1d("",10,0,1);
|
||||
h->copy_from_data(hdata);
|
||||
if(m_verbose) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got a " << scls
|
||||
<< ", title " << h->title()
|
||||
<< ", mean_x " << h->mean() << ", rms " << h->rms()
|
||||
<< std::endl;
|
||||
}
|
||||
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
|
||||
|
||||
} else if(scls==tools::histo::h2d::s_class()) {
|
||||
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
|
||||
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
|
||||
tools::histo::h2d* h = new tools::histo::h2d("",10,0,1,10,0,1);
|
||||
h->copy_from_data(hdata);
|
||||
if(m_verbose) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got a " << scls
|
||||
<< ", title " << h->title()
|
||||
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
|
||||
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
|
||||
<< std::endl;
|
||||
}
|
||||
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
|
||||
|
||||
} else if(scls==tools::histo::h3d::s_class()) {
|
||||
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
|
||||
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
|
||||
tools::histo::h3d* h = new tools::histo::h3d("",10,0,1,10,0,1,10,0,1);
|
||||
h->copy_from_data(hdata);
|
||||
if(m_verbose) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got a " << scls
|
||||
<< ", title " << h->title()
|
||||
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
|
||||
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
|
||||
<< ", mean_z " << h->mean_z() << ", rms_z " << h->rms_z()
|
||||
<< std::endl;
|
||||
}
|
||||
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
|
||||
|
||||
} else if(scls==tools::histo::p1d::s_class()) {
|
||||
tools::histo::profile_data<double,unsigned int,unsigned int,double,double> pdata;
|
||||
if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false;
|
||||
tools::histo::p1d* h = new tools::histo::p1d("",10,0,1);
|
||||
h->copy_from_data(pdata);
|
||||
if(m_verbose) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got a " << scls
|
||||
<< ", title " << h->title()
|
||||
<< ", mean_x " << h->mean() << ", rms " << h->rms()
|
||||
<< std::endl;
|
||||
}
|
||||
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
|
||||
|
||||
} else if(scls==tools::histo::p2d::s_class()) {
|
||||
tools::histo::profile_data<double,unsigned int,unsigned int,double,double> pdata;
|
||||
if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false;
|
||||
tools::histo::p2d* h = new tools::histo::p2d("",10,0,1,10,0,1);
|
||||
h->copy_from_data(pdata);
|
||||
if(m_verbose) {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got a " << scls
|
||||
<< ", title " << h->title()
|
||||
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
|
||||
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
|
||||
<< std::endl;
|
||||
}
|
||||
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
|
||||
|
||||
} else {
|
||||
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
|
||||
<< " : got not treated class " << scls
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
}} //ihist
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int rank() const { return m_rank;}
|
||||
virtual bool comm_rank(int& a_rank) const {
|
||||
if(::MPI_Comm_rank(m_comm,&a_rank)!=MPI_SUCCESS) {a_rank=-1;return false;}
|
||||
return true;
|
||||
}
|
||||
virtual bool comm_size(int& a_size) const {
|
||||
if(::MPI_Comm_size(m_comm,&a_size)!=MPI_SUCCESS) {a_size=0;return false;}
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
hmpi(std::ostream& a_out,int a_rank,int a_tag,const MPI_Comm& a_comm,bool a_verbose = false)
|
||||
:m_out(a_out)
|
||||
,m_rank(a_rank)
|
||||
,m_tag(a_tag)
|
||||
,m_comm(a_comm)
|
||||
,m_verbose(a_verbose)
|
||||
,m_wrmpi(a_out,a_comm)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
virtual ~hmpi(){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
hmpi(const hmpi& a_from)
|
||||
:parent(a_from)
|
||||
,m_out(a_from.m_out)
|
||||
,m_rank(a_from.m_rank)
|
||||
,m_tag(a_from.m_tag)
|
||||
,m_comm(a_from.m_comm)
|
||||
,m_verbose(a_from.m_verbose)
|
||||
,m_wrmpi(a_from.m_out,a_from.m_comm)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
hmpi& operator=(const hmpi& a_from){
|
||||
m_rank = a_from.m_rank;
|
||||
m_tag = a_from.m_tag;
|
||||
m_verbose = a_from.m_verbose;
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
int m_rank;
|
||||
int m_tag;
|
||||
const MPI_Comm& m_comm;
|
||||
bool m_verbose;
|
||||
wrmpi m_wrmpi;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_mpi_wait_buffer
|
||||
#define toolx_mpi_wait_buffer
|
||||
|
||||
#include <mpi.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace mpi {
|
||||
|
||||
inline bool wait_buffer(std::ostream& a_out,int a_rank,int a_src,int a_tag,const MPI_Comm& a_comm,
|
||||
int& a_buffer_size,char*& a_buffer,int& a_probe_src,bool a_verbose = false) {
|
||||
a_buffer = 0;
|
||||
a_buffer_size = 0;
|
||||
a_probe_src = -1;
|
||||
|
||||
MPI_Status status;
|
||||
if(::MPI_Probe(a_src,a_tag,a_comm,&status)!=MPI_SUCCESS) {
|
||||
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Probe : failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(::MPI_Get_count(&status,MPI_CHAR,&a_buffer_size)!=MPI_SUCCESS) {
|
||||
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Get_count : failed." << std::endl;
|
||||
a_buffer_size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
a_probe_src = status.MPI_SOURCE;
|
||||
|
||||
if(!a_buffer_size) {
|
||||
a_out << "exlb::mpi::wait_buffer : MPI_Get_count returns zero data." << std::endl;
|
||||
a_probe_src = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(a_verbose) a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : get_count " << a_buffer_size << std::endl;
|
||||
|
||||
a_buffer = new char[a_buffer_size];
|
||||
if(!a_buffer) {
|
||||
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : can't alloc buffer of size " << a_buffer_size << std::endl;
|
||||
a_buffer_size = 0;
|
||||
a_probe_src = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(::MPI_Recv(a_buffer,a_buffer_size,MPI_CHAR,status.MPI_SOURCE,status.MPI_TAG,a_comm,&status)!=MPI_SUCCESS) {
|
||||
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Recv : failed." << std::endl;
|
||||
a_buffer_size = 0;
|
||||
delete [] a_buffer;
|
||||
a_buffer = 0;
|
||||
a_probe_src = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(a_verbose) a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : unpack data ..." << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_mpi_world
|
||||
#define toolx_mpi_world
|
||||
|
||||
// code to wrap MPI global things by having an interface (toolx::mpi).
|
||||
|
||||
#include <tools/impi_world>
|
||||
|
||||
#include <mpi.h>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace mpi {
|
||||
|
||||
class world : public virtual tools::impi_world {
|
||||
typedef tools::impi_world parent;
|
||||
#ifdef TOOLS_MEM
|
||||
protected:
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::mpi::world");
|
||||
return s_v;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
virtual bool init(int* a_argc,char*** a_argv) {
|
||||
if(::MPI_Init(a_argc,a_argv)!=MPI_SUCCESS) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool rank(int& a_rank) const {
|
||||
if(::MPI_Comm_rank(MPI_COMM_WORLD,&a_rank)!=MPI_SUCCESS) {a_rank=-1;return false;}
|
||||
return true;
|
||||
}
|
||||
virtual bool size(int& a_size) const {
|
||||
if(::MPI_Comm_size(MPI_COMM_WORLD,&a_size)!=MPI_SUCCESS) {a_size=0;return false;}
|
||||
return true;
|
||||
}
|
||||
virtual bool processor_name(std::string& a_s) const {
|
||||
char name[MPI_MAX_PROCESSOR_NAME];
|
||||
int lname;
|
||||
if(::MPI_Get_processor_name(name,&lname)!=MPI_SUCCESS) {a_s.clear();return false;}
|
||||
a_s = std::string(name);
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
world() {
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
virtual ~world(){
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
world(const world& a_from):parent(a_from) {
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
world& operator=(const world&) {return *this;}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+528
@@ -0,0 +1,528 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_mpi_wrmpi
|
||||
#define toolx_mpi_wrmpi
|
||||
|
||||
#include "wait_buffer"
|
||||
|
||||
#include <tools/impi>
|
||||
#include <tools/vdata>
|
||||
#include <tools/realloc>
|
||||
#include <tools/mnmx>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#endif
|
||||
|
||||
// the below must be in sync with tools/typedefs
|
||||
#ifdef _MSC_VER
|
||||
//typedef __int64 int64;
|
||||
//typedef unsigned __int64 uint64;
|
||||
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG_LONG
|
||||
#define TOOLX_MPI_INT64 MPI_LONG_LONG
|
||||
#elif defined(_LP64)
|
||||
// 64 Bit Platforms
|
||||
//typedef long int64;
|
||||
//typedef unsigned long uint64;
|
||||
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG
|
||||
#define TOOLX_MPI_INT64 MPI_LONG
|
||||
#else
|
||||
// 32-Bit Platforms
|
||||
//typedef long long int64;
|
||||
//typedef unsigned long long uint64;
|
||||
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG_LONG
|
||||
#define TOOLX_MPI_INT64 MPI_LONG_LONG
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace mpi {
|
||||
|
||||
class wrmpi : public virtual tools::impi {
|
||||
typedef tools::impi parent;
|
||||
public:
|
||||
typedef unsigned int num_t;
|
||||
protected:
|
||||
static const std::string& s_class() {
|
||||
static const std::string s_v("toolx::mpi::wrmpi");
|
||||
return s_v;
|
||||
}
|
||||
public: //tools::impi
|
||||
virtual bool pack(char a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(char));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(char) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(short a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(short));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_SHORT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(short) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(int a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(int));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(int) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(unsigned int a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(unsigned int));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(unsigned int) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(tools::uint64 a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(tools::uint64));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,TOOLX_MPI_UINT64,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(uint64) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(tools::int64 a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(tools::int64));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,TOOLX_MPI_INT64,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(int64) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(float a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(float));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_FLOAT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(float) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(double a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(double));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
if(::MPI_Pack(&a_val,1,MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(double) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool bpack(bool a_val) {
|
||||
tools::uint32 sz = tools::uint32(sizeof(unsigned char));
|
||||
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
unsigned char val = a_val?1:0;
|
||||
if(::MPI_Pack(&val,1,MPI_UNSIGNED_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(bool) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool spack(const std::string& a_s) {
|
||||
if(!pack((num_t)a_s.size())) return false;
|
||||
tools::uint32 sz = (tools::uint32)a_s.size();
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(a_s.c_str(),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::string) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool vpack(const std::vector<unsigned int>& a_v) {
|
||||
if(!pack((num_t)a_v.size())) return false;
|
||||
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(unsigned int));
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<unsigned int*>(tools::vec_data(a_v)),a_v.size(),
|
||||
MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<unsigned int>) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool vpack(const std::vector<int>& a_v) {
|
||||
if(!pack((num_t)a_v.size())) return false;
|
||||
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(int));
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<int*>(tools::vec_data(a_v)),a_v.size(),MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<int>) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool vpack(const std::vector<double>& a_v) {
|
||||
if(!pack((num_t)a_v.size())) return false;
|
||||
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(double));
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<double*>(tools::vec_data(a_v)),a_v.size(),MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<double>) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
virtual bool pack(tools::uint32 a_size,const char* a_buffer) {
|
||||
if(!pack((num_t)a_size)) return false;
|
||||
tools::uint32 sz = (tools::uint32)(a_size*sizeof(char));
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<char*>(a_buffer),a_size,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(a_buffer,a_size,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(char*) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool pack(tools::uint32 a_size,const int* a_buffer) {
|
||||
if(!pack((num_t)a_size)) return false;
|
||||
tools::uint32 sz = (tools::uint32)(a_size*sizeof(int));
|
||||
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
if(::MPI_Pack(const_cast<int*>(a_buffer),a_size,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#else
|
||||
if(::MPI_Pack(a_buffer,a_size,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
|
||||
#endif
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Pack(int*) failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_pos += sz;
|
||||
return true;
|
||||
}
|
||||
public: //tools::impi
|
||||
virtual bool unpack(char& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_CHAR,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(char) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(short& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_SHORT,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(short) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(int& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_INT,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(unsigned int& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(unsigned int) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(tools::uint64& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,TOOLX_MPI_UINT64,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(uint64) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(tools::int64& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,TOOLX_MPI_INT64,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int64) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(float& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_FLOAT,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(float) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(double& a_val) {
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(double) failed." << std::endl;
|
||||
a_val = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool bunpack(bool& a_val) {
|
||||
typedef unsigned char bool_t;
|
||||
bool_t val;
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&val,1,MPI_UNSIGNED_CHAR,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(bool) failed." << std::endl;
|
||||
a_val = false;
|
||||
return false;
|
||||
}
|
||||
a_val = val==1?true:false;
|
||||
return true;
|
||||
}
|
||||
virtual bool vunpack(std::vector<unsigned int>& a_v) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_v.clear();return false;}
|
||||
a_v.resize(num);
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<unsigned int>) failed." << std::endl;
|
||||
a_v.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool vunpack(std::vector<int>& a_v) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_v.clear();return false;}
|
||||
a_v.resize(num);
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_INT,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<int>) failed." << std::endl;
|
||||
a_v.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool vunpack(std::vector<double>& a_v) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_v.clear();return false;}
|
||||
a_v.resize(num);
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<double>) failed." << std::endl;
|
||||
a_v.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool sunpack(std::string& a_s) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_s.clear();return false;}
|
||||
a_s.resize(num);
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::string) failed." << std::endl;
|
||||
a_s.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(tools::uint32& a_size,char*& a_buffer) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_size = 0;a_buffer = 0;return false;}
|
||||
a_buffer = new char[num];
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,a_buffer,num,MPI_CHAR,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(char*) failed." << std::endl;
|
||||
delete [] a_buffer;
|
||||
a_size = 0;
|
||||
a_buffer = 0;
|
||||
return false;
|
||||
}
|
||||
a_size = num;
|
||||
return true;
|
||||
}
|
||||
virtual bool unpack(tools::uint32& a_size,int*& a_buffer) {
|
||||
num_t num;
|
||||
if(!unpack(num)) {a_size = 0;a_buffer = 0;return false;}
|
||||
a_buffer = new int[num];
|
||||
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,a_buffer,num,MPI_INT,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int*) failed." << std::endl;
|
||||
delete [] a_buffer;
|
||||
a_size = 0;
|
||||
a_buffer = 0;
|
||||
return false;
|
||||
}
|
||||
a_size = num;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void pack_reset() {
|
||||
delete [] m_buffer;
|
||||
m_size = 128;
|
||||
m_buffer = new char[m_size];
|
||||
//if(!m_buffer) {}
|
||||
m_max = m_buffer+m_size;
|
||||
m_pos = m_buffer;
|
||||
m_ipos = 0; //IMPORTANT
|
||||
}
|
||||
|
||||
virtual bool send_buffer(int a_dest,int a_tag) { // used in tools/mpi/pntuple.
|
||||
if(::MPI_Send(m_buffer,m_ipos,MPI_CHAR,a_dest,a_tag,m_comm)!=MPI_SUCCESS) {
|
||||
m_out << "toolx::mpi::wrmpi::send_buffer : MPI_Send() failed for rank destination " << a_dest << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool wait_buffer(int a_rank,int a_src,int a_tag,int& a_probe_src,bool a_verbose = false) {
|
||||
int buffer_size = 0;
|
||||
char* _buffer = 0;
|
||||
if (!mpi::wait_buffer(m_out,a_rank,a_src,a_tag,m_comm,buffer_size,_buffer,a_probe_src,a_verbose)) {
|
||||
m_out << "toolx::mpi::wrmpi::wait_buffer : failed for rank " << a_rank << " and source " << a_src <<"." << std::endl;
|
||||
return false;
|
||||
}
|
||||
// we take ownership of buffer :
|
||||
delete [] m_buffer;
|
||||
m_size = buffer_size;
|
||||
m_buffer = _buffer;
|
||||
m_max = m_buffer+m_size;
|
||||
m_pos = m_buffer;
|
||||
m_ipos = 0; //IMPORTANT
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool wait_buffer(int a_rank,int a_tag,int& a_probe_src,bool a_verbose = false) {
|
||||
return wait_buffer(a_rank,MPI_ANY_SOURCE,a_tag,a_probe_src,a_verbose);
|
||||
}
|
||||
|
||||
public:
|
||||
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size = 128) // we expect a_size!=0
|
||||
:m_out(a_out)
|
||||
,m_comm(a_comm)
|
||||
,m_size(0)
|
||||
,m_buffer(0)
|
||||
,m_max(0)
|
||||
,m_pos(0)
|
||||
,m_ipos(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
m_size = a_size;
|
||||
m_buffer = new char[m_size];
|
||||
//if(!m_buffer) {}
|
||||
m_max = m_buffer+m_size;
|
||||
m_pos = m_buffer;
|
||||
}
|
||||
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size,char* a_buffer) //we take ownership of a_buffer.
|
||||
:m_out(a_out)
|
||||
,m_comm(a_comm)
|
||||
,m_size(a_size)
|
||||
,m_buffer(a_buffer)
|
||||
,m_max(0)
|
||||
,m_pos(0)
|
||||
,m_ipos(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
m_max = m_buffer+m_size;
|
||||
m_pos = m_buffer;
|
||||
}
|
||||
virtual ~wrmpi(){
|
||||
delete [] m_buffer;
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
wrmpi(const wrmpi& a_from)
|
||||
:parent(a_from)
|
||||
,m_out(a_from.m_out)
|
||||
,m_comm(a_from.m_comm)
|
||||
,m_size(0)
|
||||
,m_buffer(0)
|
||||
,m_max(0)
|
||||
,m_pos(0)
|
||||
,m_ipos(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
wrmpi& operator=(const wrmpi&){return *this;}
|
||||
public:
|
||||
int ipos() const {return m_ipos;}
|
||||
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
|
||||
char* buffer() {return m_buffer;}
|
||||
#else
|
||||
const char* buffer() const {return m_buffer;}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool expand2(tools::uint32 a_new_size) {return expand(tools::mx<tools::uint32>(2*m_size,a_new_size));} //CERN-ROOT logic.
|
||||
|
||||
bool expand(tools::uint32 a_new_size) {
|
||||
tools::diff_pointer_t len = m_pos-m_buffer;
|
||||
if(!tools::realloc<char>(m_buffer,a_new_size,m_size)) {
|
||||
m_out << "toolx::mpi::wrmpi::expand :"
|
||||
<< " can't realloc " << a_new_size << " bytes."
|
||||
<< std::endl;
|
||||
m_size = 0;
|
||||
m_max = 0;
|
||||
m_pos = 0;
|
||||
//m_wb.set_eob(m_max);
|
||||
return false;
|
||||
}
|
||||
m_size = a_new_size;
|
||||
m_max = m_buffer + m_size;
|
||||
m_pos = m_buffer + len;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
const MPI_Comm& m_comm;
|
||||
tools::uint32 m_size;
|
||||
char* m_buffer;
|
||||
char* m_max;
|
||||
char* m_pos;
|
||||
//
|
||||
int m_ipos;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#ifdef TOOLX_MPI_UINT64
|
||||
#undef TOOLX_MPI_UINT64
|
||||
#endif
|
||||
|
||||
#ifdef TOOLX_MPI_INT64
|
||||
#undef TOOLX_MPI_INT64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_raxml
|
||||
#define toolx_raxml
|
||||
|
||||
#include <tools/xml/aidas>
|
||||
|
||||
#include "xml/loader"
|
||||
|
||||
namespace toolx {
|
||||
|
||||
class raxml : public tools::xml::aidas, public xml::loader {
|
||||
typedef tools::xml::aidas parent_aidas;
|
||||
typedef xml::loader parent;
|
||||
public:
|
||||
raxml(tools::xml::factory& a_fac,std::ostream& a_out,bool a_verbose = false)
|
||||
:parent_aidas()
|
||||
,parent(a_fac,a_out,a_verbose)
|
||||
,m_read_tag(0)
|
||||
{
|
||||
set_default_tags(parent::m_tags);
|
||||
}
|
||||
virtual ~raxml() {}
|
||||
public:
|
||||
void set_read_tag(void* a_tag) {m_read_tag = a_tag;}
|
||||
protected:
|
||||
raxml(const raxml& a_from)
|
||||
:parent_aidas(a_from)
|
||||
,parent(a_from)
|
||||
{}
|
||||
raxml& operator=(const raxml& a_from){
|
||||
parent_aidas::operator=(a_from);
|
||||
parent::operator=(a_from);
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool load_file(const std::string& a_file,bool a_compressed){
|
||||
m_objects.clear();
|
||||
if(!parent::load_file(a_file,a_compressed)) return false;
|
||||
tools::xml::tree* top = top_item();
|
||||
if(!top) return false;
|
||||
const std::string& tag_name = top->tag_name();
|
||||
if(tag_name!=s_aida()) return false;
|
||||
|
||||
{tools::xml::looper _for(*top);
|
||||
while(tools::xml::tree* _tree = _for.next_tree()) {
|
||||
|
||||
const std::string& _tag_name = _tree->tag_name();
|
||||
reader rder = find_reader(_tag_name);
|
||||
if(!rder) {
|
||||
m_out << "toolx::raxml::load_file :"
|
||||
<< " reader not found for " << tools::sout(_tag_name)
|
||||
<< std::endl;
|
||||
//m_objects.clear(); //keep already loaded objects.
|
||||
return false;
|
||||
} else {
|
||||
tools::raxml_out ro = rder(*_tree,m_out,m_verbose,m_read_tag);
|
||||
if(ro.object()) m_objects.push_back(ro);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
void* m_read_tag;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+660
@@ -0,0 +1,660 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_sg_GL_action
|
||||
#define toolx_sg_GL_action
|
||||
|
||||
#include "GL_manager"
|
||||
|
||||
#include <tools/sg/render_action>
|
||||
|
||||
//#include <tools/mathf>
|
||||
//#include <tools/lina/matout>
|
||||
|
||||
namespace toolx {
|
||||
namespace sg {
|
||||
|
||||
class GL_action : public tools::sg::render_action {
|
||||
TOOLS_ACTION(GL_action,toolx::sg::GL_action,tools::sg::render_action)
|
||||
public:
|
||||
virtual void draw_vertex_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs){
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
_draw_v(a_mode,num,a_xyzs);
|
||||
}
|
||||
|
||||
virtual void draw_vertex_array_xy(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xys){
|
||||
size_t num = a_floatn/2;
|
||||
if(!num) return;
|
||||
#ifdef _WIN32
|
||||
float* vp = new float[num*3];
|
||||
if(!vp) return;
|
||||
float* pos = vp;
|
||||
float* pda = (float*)a_xys;
|
||||
for(size_t index=0;index<num;index++){
|
||||
*pos = *pda;pos++;pda++;
|
||||
*pos = *pda;pos++;pda++;
|
||||
*pos = 0;pos++; //Windows GL needs a z = 0.
|
||||
}
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glVertexPointer(3,GL_FLOAT,0,vp);
|
||||
::glDrawArrays(a_mode,0,(GLsizei)num);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
delete [] vp;
|
||||
#else
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glVertexPointer(2,GL_FLOAT,0,a_xys);
|
||||
::glDrawArrays(a_mode,0,(GLsizei)num);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void draw_vertex_color_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_rgbas){
|
||||
// Used in atb_vertices.
|
||||
// We expect a_rgbas of size : 4*(a_floatn/3)
|
||||
// (then one RGBA color per 3D point).
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
_draw_vc(a_mode,num,a_xyzs,a_rgbas);
|
||||
}
|
||||
|
||||
virtual void draw_vertex_normal_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_nms){
|
||||
// We expect a_nms of size : 3*(a_floatn/3)
|
||||
// (then one normal per 3D point).
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
_draw_vn(a_mode,num,a_xyzs,a_nms);
|
||||
}
|
||||
|
||||
virtual void draw_vertex_color_normal_array(tools::gl::mode_t a_mode,
|
||||
size_t a_floatn,const float* a_xyzs,const float* a_rgbas,const float* a_nms){
|
||||
// Used in atb_vertices.
|
||||
// We expect a_nms of size : 3*(a_floatn/3)
|
||||
// (then one normal per 3D point).
|
||||
// We expect a_rgbas of size : 4*(a_floatn/3)
|
||||
// (then one RGBA color per 3D point).
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
_draw_vcn(a_mode,num,a_xyzs,a_rgbas,a_nms);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// texture /////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
virtual void draw_vertex_array_texture(tools::gl::mode_t a_mode,
|
||||
size_t a_floatn,
|
||||
const float* a_xyzs,
|
||||
gstoid a_tex,
|
||||
const float* a_tex_coords) {
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
|
||||
//expect 2*num a_tex_coords.
|
||||
|
||||
::glEnable(GL_TEXTURE_2D);
|
||||
|
||||
m_mgr.bind_gsto(a_tex);
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
|
||||
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
|
||||
::glDrawArrays(a_mode,0,(GLsizei)num);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D,0);
|
||||
|
||||
::glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
virtual void draw_vertex_normal_array_texture(tools::gl::mode_t a_mode,
|
||||
size_t a_floatn,
|
||||
const float* a_xyzs,
|
||||
const float* a_nms,
|
||||
gstoid a_tex,
|
||||
const float* a_tex_coords) {
|
||||
size_t num = a_floatn/3;
|
||||
if(!num) return;
|
||||
|
||||
//expect 2*num a_tex_coords.
|
||||
|
||||
::glEnable(GL_TEXTURE_2D);
|
||||
|
||||
m_mgr.bind_gsto(a_tex);
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
|
||||
::glNormalPointer(GL_FLOAT,0,a_nms);
|
||||
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
|
||||
::glDrawArrays(a_mode,0,(GLsizei)num);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
::glBindTexture(GL_TEXTURE_2D,0);
|
||||
|
||||
::glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/// VBO /////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void begin_gsto(gstoid a_id) {
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
m_mgr.bind_gsto(a_id);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
m_gsto = a_id;
|
||||
m_created = false;
|
||||
m_gl_id = m_mgr.gsto_gl_list_id(a_id,m_created);
|
||||
if(m_gl_id && m_created) {
|
||||
::glNewList(m_gl_id,GL_COMPILE);
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
m_gsto = a_id;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void end_gsto() {
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
::glBindBuffer(GL_ARRAY_BUFFER,0);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
if(m_gl_id && m_created) {
|
||||
::glEndList();
|
||||
}
|
||||
if(m_gl_id) ::glCallList(m_gl_id);
|
||||
m_created = false;
|
||||
m_gl_id = 0;
|
||||
m_gsto = 0;
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
m_gsto = 0;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef tools::sg::bufpos bufpos;
|
||||
virtual void draw_gsto_v(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs){
|
||||
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
_draw_v(a_mode,a_elems,(char*)NULL+a_pos_xyzs);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
if(m_gl_id && m_created) {
|
||||
::glBegin(a_mode);
|
||||
float* pos = (float*)pos_xyzs;
|
||||
for(size_t index=0;index<a_elems;index++,pos+=3) {
|
||||
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
_draw_v(a_mode,a_elems,pos_xyzs);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void draw_gsto_vc(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas){
|
||||
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
_draw_vc(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
|
||||
if(m_gl_id && m_created) {
|
||||
::glBegin(a_mode);
|
||||
float* pos = (float*)pos_xyzs;
|
||||
float* pco = (float*)pos_rgbas;
|
||||
for(size_t index=0;index<a_elems;index++,pos+=3,pco+=4) {
|
||||
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
|
||||
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
|
||||
_draw_vc(a_mode,a_elems,pos_xyzs,pos_rgbas);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void draw_gsto_vn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_nms){
|
||||
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
_draw_vn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_nms);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
//void* pos_nms = (char*)buffer+a_pos_nms;
|
||||
if(m_gl_id && m_created) {
|
||||
::glBegin(a_mode);
|
||||
float* pos = (float*)pos_xyzs;
|
||||
for(size_t index=0;index<a_elems;index++,pos+=3) {
|
||||
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
void* pos_nms = (char*)buffer+a_pos_nms;
|
||||
_draw_vn(a_mode,a_elems,pos_xyzs,pos_nms);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void draw_gsto_vcn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas,bufpos a_pos_nms){
|
||||
|
||||
switch(m_mgr.get_gsto_mode()){
|
||||
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
_draw_vcn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas,(char*)NULL+a_pos_nms);
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
|
||||
void* pos_nms = (char*)buffer+a_pos_nms;
|
||||
if(m_gl_id && m_created) {
|
||||
::glBegin(a_mode);
|
||||
float* pos = (float*)pos_xyzs;
|
||||
float* pco = (float*)pos_rgbas;
|
||||
float* pnm = (float*)pos_nms;
|
||||
for(size_t index=0;index<a_elems;
|
||||
index++,pos+=3,pco+=4,pnm+=3) {
|
||||
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
|
||||
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
|
||||
::glNormal3f(*(pnm+0),*(pnm+1),*(pnm+2));
|
||||
}
|
||||
::glEnd();
|
||||
}
|
||||
#endif
|
||||
}break;
|
||||
|
||||
case tools::sg::gsto_memory:{
|
||||
float* buffer = m_mgr.gsto_data(m_gsto);
|
||||
if(!buffer) return;
|
||||
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
|
||||
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
|
||||
void* pos_nms = (char*)buffer+a_pos_nms;
|
||||
_draw_vcn(a_mode,a_elems,pos_xyzs,pos_rgbas,pos_nms);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void clear_color(float a_r,float a_g,float a_b,float a_a){
|
||||
::glClearColor(a_r,a_g,a_b,a_a);
|
||||
::glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
virtual void color4f(float a_r,float a_g,float a_b,float a_a){
|
||||
::glColor4f(a_r,a_g,a_b,a_a);
|
||||
}
|
||||
virtual void line_width(float a_v){::glLineWidth(a_v);}
|
||||
virtual void point_size(float a_v){::glPointSize(a_v);}
|
||||
virtual void set_polygon_offset(bool a_v) {
|
||||
if(a_v) ::glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
else ::glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
::glPolygonOffset(1.,1.);
|
||||
}
|
||||
virtual void normal(float a_x,float a_y,float a_z) {
|
||||
::glNormal3f(a_x,a_y,a_z);
|
||||
}
|
||||
|
||||
virtual void set_winding(tools::sg::winding_type a_v) {
|
||||
if(a_v==tools::sg::winding_ccw)
|
||||
::glFrontFace(GL_CCW);
|
||||
else
|
||||
::glFrontFace(GL_CW);
|
||||
}
|
||||
|
||||
virtual void set_shade_model(tools::sg::shade_type a_v) {
|
||||
if(a_v==tools::sg::shade_smooth)
|
||||
::glShadeModel(GL_SMOOTH);
|
||||
else
|
||||
::glShadeModel(GL_FLAT);
|
||||
}
|
||||
|
||||
virtual void set_cull_face(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_CULL_FACE);
|
||||
else ::glDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
virtual void set_point_smooth(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_POINT_SMOOTH);
|
||||
else ::glDisable(GL_POINT_SMOOTH);
|
||||
}
|
||||
|
||||
virtual void set_line_smooth(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_LINE_SMOOTH);
|
||||
else ::glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
virtual void set_depth_test(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_DEPTH_TEST);
|
||||
else ::glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
virtual void load_proj_matrix(const tools::mat4f& a_mtx) {
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadMatrixf(a_mtx.data());
|
||||
}
|
||||
|
||||
virtual void load_model_matrix(const tools::mat4f& a_mtx) {
|
||||
::glMatrixMode(GL_MODELVIEW);
|
||||
::glLoadMatrixf(a_mtx.data());
|
||||
/*
|
||||
tools::mat4f tmp(a_mtx);
|
||||
tmp.no_translate();
|
||||
tools::mat4f normal_matrix;
|
||||
if(!tmp.invert(normal_matrix)) {
|
||||
m_out << "toolx::WebGL::render::load_model_matrix :"
|
||||
<< " can't invert model matrix."
|
||||
<< std::endl;
|
||||
}
|
||||
normal_matrix.transpose();
|
||||
|
||||
tools::mat4f to_check(a_mtx);
|
||||
to_check.no_translate();
|
||||
float fepsilon = 1e-10;
|
||||
if(!normal_matrix.equal_prec(to_check,fepsilon,tools::ffabs)) {
|
||||
mat_dump(m_out,"problem with normal_matrix ",normal_matrix);
|
||||
mat_dump(m_out,"expected",to_check);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
virtual unsigned int max_lights() {return GL_MAX_LIGHTS;}
|
||||
|
||||
virtual void enable_light(unsigned int a_light,
|
||||
float a_dx,float a_dy,float a_dz,
|
||||
float a_r,float a_g,float a_b,float a_a){
|
||||
::glEnable(GL_LIGHTING);
|
||||
GLenum light = GL_LIGHT0+a_light;
|
||||
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
|
||||
|
||||
float params[4];
|
||||
params[0] = -a_dx;
|
||||
params[1] = -a_dy;
|
||||
params[2] = -a_dz;
|
||||
params[3] = 0; //0 tells that it is a directional light.
|
||||
::glLightfv(light,GL_POSITION,params);
|
||||
|
||||
//params[0] = a_dir[0];
|
||||
//params[1] = a_dir[1];
|
||||
//params[2] = a_dir[2];
|
||||
//::glLightfv(light,GL_SPOT_DIRECTION,params);
|
||||
|
||||
params[0] = a_r;
|
||||
params[1] = a_g;
|
||||
params[2] = a_b;
|
||||
params[3] = a_a;
|
||||
::glLightfv(light,GL_DIFFUSE,params);
|
||||
::glLightfv(light,GL_SPECULAR,params); //coin/SoDirectionalLight does that.
|
||||
|
||||
params[0] = 0;
|
||||
params[1] = 0;
|
||||
params[2] = 0;
|
||||
params[3] = 1;
|
||||
::glLightfv(light,GL_AMBIENT,params); //coin/SoDirectionalLight does that.
|
||||
|
||||
// coin/SoDirectionalLight does the below :
|
||||
::glLightf(light, GL_SPOT_EXPONENT, 0.0);
|
||||
::glLightf(light, GL_SPOT_CUTOFF, 180.0);
|
||||
::glLightf(light, GL_CONSTANT_ATTENUATION, 1);
|
||||
::glLightf(light, GL_LINEAR_ATTENUATION, 0);
|
||||
::glLightf(light, GL_QUADRATIC_ATTENUATION, 0);
|
||||
|
||||
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
|
||||
|
||||
::glEnable(light);
|
||||
}
|
||||
|
||||
virtual void set_lighting(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_LIGHTING);
|
||||
else ::glDisable(GL_LIGHTING);
|
||||
}
|
||||
virtual void set_blend(bool a_on) {
|
||||
if(a_on) ::glEnable(GL_BLEND);
|
||||
else ::glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
virtual void restore_state(unsigned int a_ret_num_light) {
|
||||
const tools::sg::state& _state = state();
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadMatrixf(_state.m_proj.data());
|
||||
|
||||
::glMatrixMode(GL_MODELVIEW);
|
||||
::glLoadMatrixf(_state.m_model.data());
|
||||
|
||||
if(_state.m_GL_LIGHTING) ::glEnable(GL_LIGHTING);
|
||||
else ::glDisable(GL_LIGHTING);
|
||||
|
||||
if(_state.m_GL_DEPTH_TEST) ::glEnable(GL_DEPTH_TEST);
|
||||
else ::glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if(_state.m_GL_CULL_FACE) ::glEnable(GL_CULL_FACE);
|
||||
else ::glDisable(GL_CULL_FACE);
|
||||
|
||||
if(_state.m_GL_POINT_SMOOTH) ::glEnable(GL_POINT_SMOOTH);
|
||||
else ::glDisable(GL_POINT_SMOOTH);
|
||||
|
||||
if(_state.m_GL_LINE_SMOOTH) ::glEnable(GL_LINE_SMOOTH);
|
||||
else ::glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
if(_state.m_GL_POLYGON_OFFSET_FILL) ::glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
else ::glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
if(_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
|
||||
else ::glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if(_state.m_GL_BLEND) ::glEnable(GL_BLEND);
|
||||
else ::glDisable(GL_BLEND);
|
||||
|
||||
if(_state.m_winding==tools::sg::winding_ccw) {
|
||||
::glFrontFace(GL_CCW);
|
||||
} else {
|
||||
::glFrontFace(GL_CW);
|
||||
}
|
||||
|
||||
if(_state.m_shade_model==tools::sg::shade_smooth)
|
||||
::glShadeModel(GL_SMOOTH);
|
||||
else
|
||||
::glShadeModel(GL_FLAT);
|
||||
|
||||
::glColor4f(_state.m_color.r(),
|
||||
_state.m_color.g(),
|
||||
_state.m_color.b(),
|
||||
_state.m_color.a());
|
||||
|
||||
::glNormal3f(_state.m_normal.x(),
|
||||
_state.m_normal.y(),
|
||||
_state.m_normal.z());
|
||||
|
||||
// The "return of separator" state had ret_num_light.
|
||||
// The restored state has m_light.
|
||||
// We have to glDisable lights with index in [m_light,ret_num_light-1]
|
||||
for(unsigned int index=_state.m_light;index<a_ret_num_light;index++) {
|
||||
::glDisable(GL_LIGHT0+index);
|
||||
}
|
||||
|
||||
::glLineWidth(_state.m_line_width);
|
||||
|
||||
::glPointSize(_state.m_point_size);
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// GL-ES
|
||||
#elif defined(ANDROID)
|
||||
// GL-ES
|
||||
#else
|
||||
::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual tools::sg::render_manager& render_manager() {return m_mgr;}
|
||||
public:
|
||||
GL_action(GL_manager& a_mgr,std::ostream& a_out,unsigned int a_ww,unsigned int a_wh)
|
||||
:parent(a_out,a_ww,a_wh)
|
||||
,m_mgr(a_mgr)
|
||||
,m_gsto(0)
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
,m_created(false)
|
||||
,m_gl_id(0)
|
||||
#endif
|
||||
{}
|
||||
virtual ~GL_action(){}
|
||||
public:
|
||||
GL_action(const GL_action& a_from)
|
||||
:parent(a_from)
|
||||
,m_mgr(a_from.m_mgr)
|
||||
,m_gsto(0)
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
,m_created(false)
|
||||
,m_gl_id(0)
|
||||
#endif
|
||||
{}
|
||||
GL_action& operator=(const GL_action& a_from){
|
||||
render_action::operator=(a_from);
|
||||
m_gsto = 0;
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
m_created = false;
|
||||
m_gl_id = 0;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
void _draw_v(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs){
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
|
||||
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void _draw_vc(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas){
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
|
||||
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
|
||||
|
||||
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
|
||||
|
||||
::glDisableClientState(GL_COLOR_ARRAY);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void _draw_vn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_nms){
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
|
||||
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
|
||||
|
||||
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
|
||||
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void _draw_vcn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas,const void* a_pos_nms){
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_COLOR_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
|
||||
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
|
||||
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
|
||||
|
||||
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
|
||||
|
||||
::glDisableClientState(GL_COLOR_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
protected:
|
||||
GL_manager& m_mgr;
|
||||
gstoid m_gsto;
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
bool m_created;
|
||||
gstoid m_gl_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,696 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_sg_GL_manager
|
||||
#define toolx_sg_GL_manager
|
||||
|
||||
#include "gl"
|
||||
#include "../glbuf"
|
||||
|
||||
#include <tools/sg/render_manager>
|
||||
#include <tools/mapmanip>
|
||||
#include <tools/carray>
|
||||
|
||||
#include <cmath> //::sqrt
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace sg {
|
||||
|
||||
class GL_manager : public virtual tools::sg::render_manager {
|
||||
typedef tools::sg::render_manager parent;
|
||||
public:
|
||||
TOOLS_SCLASS(toolx::sg::GL_manager)
|
||||
virtual void* cast(const std::string& a_class) const {
|
||||
if(void* p = tools::cmp_cast<GL_manager>(this,a_class)) {return p;}
|
||||
else return 0;
|
||||
}
|
||||
public:
|
||||
virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh,
|
||||
float a_r,float a_g,float a_b,float a_a,bool a_clear = true) {
|
||||
gl_clear_errors();
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#elif defined(ANDROID)
|
||||
#elif _WIN32
|
||||
#elif __APPLE__ // Cocoa
|
||||
// to avoid a 0x506 error message :
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
#if GL_ARB_framebuffer_object
|
||||
if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
|
||||
//m_out << "toolx::sg::GL_manager::begin_render :"
|
||||
// << " frame buffer not complete."
|
||||
// << std::endl;
|
||||
return false;
|
||||
}
|
||||
#endif //GL_ARB_framebuffer_object
|
||||
#endif //TOOLX_HAS_GL_VBO
|
||||
#else
|
||||
#endif
|
||||
|
||||
// WARNING : the values set here must match the default values in sg::state.
|
||||
|
||||
// Antialiasing :
|
||||
#if TARGET_OS_IPHONE
|
||||
#elif defined(ANDROID)
|
||||
::glEnable(GL_MULTISAMPLE);
|
||||
#elif _WIN32
|
||||
#elif __APPLE__
|
||||
::glEnable(GL_MULTISAMPLE); //Cocoa
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* NOTE : not GL-ES :
|
||||
// ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
// The upper is cruely lacking with povama solid+light.
|
||||
// ::glEnable(GL_LINE_STIPPLE);
|
||||
|
||||
::glDisable(GL_POLYGON_SMOOTH);
|
||||
::glAccum(GL_LOAD,1.0f);
|
||||
::glAccum(GL_RETURN,1.0f);
|
||||
::glReadBuffer(GL_FRONT);
|
||||
|
||||
NOTE : GL_POLYGON_SMOOTH is here on Cocoa/AGL, Windows/WGL but it
|
||||
does nothing.
|
||||
*/
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// GL-ES
|
||||
#elif defined(ANDROID)
|
||||
// GL-ES
|
||||
#else
|
||||
::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
|
||||
#endif
|
||||
|
||||
/*
|
||||
::printf("debug : is enabled %d\n",::glIsEnabled(GL_COLOR_MATERIAL));
|
||||
{GLfloat v[4];
|
||||
::glGetMaterialfv(GL_FRONT,GL_AMBIENT,v);
|
||||
::printf("debug : ambient : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
||||
{GLfloat v[4];
|
||||
::glGetMaterialfv(GL_FRONT,GL_DIFFUSE,v);
|
||||
::printf("debug : diffuse : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
||||
{GLfloat v[4];
|
||||
::glGetMaterialfv(GL_FRONT,GL_SPECULAR,v);
|
||||
::printf("debug : specular : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
||||
{GLfloat v[4];
|
||||
::glGetMaterialfv(GL_FRONT,GL_EMISSION,v);
|
||||
::printf("debug : emission : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
||||
{GLfloat shine;
|
||||
::glGetMaterialfv(GL_FRONT,GL_SHININESS,&shine);
|
||||
::printf("debug : shine : %g\n",shine);}
|
||||
debug : is enabled 0
|
||||
debug : ambient : 0.2 0.2 0.2 1
|
||||
debug : diffuse : 0.8 0.8 0.8 1
|
||||
debug : specular : 0 0 0 1
|
||||
debug : emission : 0 0 0 1
|
||||
debug : shine : 0
|
||||
*/
|
||||
|
||||
::glEnable(GL_NORMALIZE);
|
||||
::glShadeModel(GL_FLAT);
|
||||
//::glShadeModel(GL_SMOOTH);
|
||||
// GL-ES : ::glMaterialfv does not work. We then use :
|
||||
// ::glEnable(GL_COLOR_MATERIAL) and ::glColor.
|
||||
//::glColorMaterial(GL_FRONT, GL_DIFFUSE); //?
|
||||
::glEnable(GL_COLOR_MATERIAL);
|
||||
|
||||
/*
|
||||
debug : is enabled 1
|
||||
debug : ambient : 1 1 1 1
|
||||
debug : diffuse : 1 1 1 1
|
||||
debug : specular : 0 0 0 1
|
||||
debug : emission : 0 0 0 1
|
||||
debug : shine : 0
|
||||
*/
|
||||
|
||||
// to handle transparency (same as SoGLRenderAction::SCREEN_DOOR ?) :
|
||||
//::glEnable(GL_BLEND);
|
||||
// NOTE : with Cocoa+AppleGL on macOS-10.14 (Mojave), it appears that points are blended ! (Even if alpha color is 1).
|
||||
// Seen with some simulated catalog of galaxies done for LSST/DC2.
|
||||
// To master this, we disable GL_BLEND by default. Then people wanting some transparency have to
|
||||
// use the tools::sg::blend node in their scene graph.
|
||||
::glDisable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
|
||||
::glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//WARNING : the below glEnable/glDisable corresponds
|
||||
// to defaults in tools::sg::state.
|
||||
::glEnable(GL_DEPTH_TEST);
|
||||
::glDisable(GL_LIGHTING);
|
||||
::glFrontFace(GL_CCW);
|
||||
::glEnable(GL_CULL_FACE);
|
||||
::glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
::glDisable(GL_TEXTURE_2D);
|
||||
|
||||
::glDisable(GL_POINT_SMOOTH);
|
||||
::glPointSize(1);
|
||||
::glDisable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms !
|
||||
::glLineWidth(1);
|
||||
|
||||
::glViewport(a_x,a_y,a_ww,a_wh);
|
||||
|
||||
// NOTE : iOS : glScissor logic does not work properly with Apple multisampling.
|
||||
// But it appears that it is not needed for VR split views.
|
||||
// Here a combination glViewport+[correct camera lrbt] does the clipping job (???).
|
||||
// (But the clear color should be the same for both views).
|
||||
//::glEnable(GL_SCISSOR_TEST);
|
||||
//::glScissor(a_x,a_y,a_ww,a_wh);
|
||||
|
||||
//NOTE : a=0 coworks with the below logic to handle transparent background.
|
||||
if(a_clear) {
|
||||
::glClearColor(a_r,a_g,a_b,0);
|
||||
::glClear(GL_COLOR_BUFFER_BIT);
|
||||
::glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
//WARNING : Android, iPhone : only one glPushMatrix ok !
|
||||
::glMatrixMode(GL_PROJECTION);
|
||||
::glLoadIdentity();
|
||||
|
||||
//WARNING : we take the convention that the current mode is MODELVIEW
|
||||
::glMatrixMode(GL_MODELVIEW);
|
||||
::glLoadIdentity();
|
||||
|
||||
//m_clear_color.set_a(0.2);
|
||||
|
||||
// to handle a transparent background :
|
||||
//NOTE : not tested on Android and iOS.
|
||||
// dst color :
|
||||
// cr * alpha + cr * (1-alpha) = cr
|
||||
// cg * alpha + cg * (1-alpha) = cg
|
||||
// cb * alpha + cb * (1-alpha) = cb
|
||||
// alpha*alpha + 0 * (1-alpha) = ca => alpha = sqrt(ca)
|
||||
|
||||
{::glColor4f(a_r,a_g,a_b,::sqrt(a_a));
|
||||
float xyzs[12];
|
||||
xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0;
|
||||
xyzs[3] = 1;xyzs[ 4] = -1;xyzs[ 5] = 0;
|
||||
xyzs[6] = 1;xyzs[ 7] = 1;xyzs[ 8] = 0;
|
||||
xyzs[9] = -1;xyzs[10] = 1;xyzs[11] = 0;
|
||||
::glDisable(GL_DEPTH_TEST);
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glVertexPointer(3,GL_FLOAT,0,xyzs);
|
||||
::glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnable(GL_DEPTH_TEST);}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void end_render() {
|
||||
::glFinish();
|
||||
gl_dump_if_errors(m_out,"toolx::sg::GL_manager::end_render :");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// texture : //////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) {
|
||||
|
||||
unsigned int gl_id;
|
||||
::glGenTextures(1,&gl_id);
|
||||
if(!gl_id) return 0;
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_tex().c_str());
|
||||
#endif
|
||||
unsigned int gsto_size = a_img.size();
|
||||
::glBindTexture(GL_TEXTURE_2D,gl_id);
|
||||
bool status = true;
|
||||
{int sz;
|
||||
::glGetIntegerv(GL_MAX_TEXTURE_SIZE,&sz);
|
||||
// MacBookPro : it returns 8192.
|
||||
// Android : it returns 2048.
|
||||
// iPad1 : it returns 2048.
|
||||
// iPod : it returns ?
|
||||
//::printf("debug : GL_MAX_TEXTURE_SIZE : %d\n",sz);
|
||||
tools::img_byte res;
|
||||
if(!sz) {
|
||||
m_out << "toolx::sg::gl::tex_img : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl;
|
||||
status = gl_tex_img(m_out,a_img);
|
||||
} else {
|
||||
if(a_img.check_gl_limit(sz,res)) {
|
||||
if(res.is_empty()) { //a_img does not exceed.
|
||||
status = gl_tex_img(m_out,a_img);
|
||||
} else {
|
||||
m_out << "toolx::sg::gl::tex_img : warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ")." << std::endl;
|
||||
status = gl_tex_img(m_out,res);
|
||||
gsto_size = res.size();
|
||||
}
|
||||
} else {
|
||||
m_out << "toolx::sg::gl::tex_img :"
|
||||
<< " warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce."
|
||||
<< std::endl;
|
||||
status = false;
|
||||
}}}
|
||||
|
||||
if(a_NEAREST) {
|
||||
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels.
|
||||
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem.
|
||||
} else {
|
||||
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
||||
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
}
|
||||
::glBindTexture(GL_TEXTURE_2D,0);
|
||||
|
||||
if(!status) {
|
||||
gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (1) :");
|
||||
::glDeleteTextures(1,&gl_id);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_tex().c_str());
|
||||
#endif
|
||||
gl_id = 0;
|
||||
gl_clear_errors();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (2) :")) {
|
||||
::glDeleteTextures(1,&gl_id);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_tex().c_str());
|
||||
#endif
|
||||
gl_id = 0;
|
||||
gl_clear_errors();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int _id = m_gen_id;m_gen_id++;
|
||||
m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0);
|
||||
return _id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
/// VBO ////////////////////////////////////////
|
||||
////////////////////////////////////////////////
|
||||
virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) {
|
||||
if(!a_floatn) return 0;
|
||||
switch(m_gsto_mode) {
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
unsigned int gl_id = 0;
|
||||
::glGenBuffers(1,&gl_id);
|
||||
if(!gl_id) {
|
||||
if(!m_warned) {
|
||||
m_warned = true;
|
||||
m_out << "toolx::sg::GL_manager::create_gsto_from_data : glGenBuffers failed ()." << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_gsto().c_str());
|
||||
#endif
|
||||
|
||||
::glBindBuffer(GL_ARRAY_BUFFER,gl_id);
|
||||
::glBufferData(GL_ARRAY_BUFFER,
|
||||
a_floatn*sizeof(float),a_data,
|
||||
GL_STATIC_DRAW);
|
||||
::glBindBuffer(GL_ARRAY_BUFFER,0);
|
||||
|
||||
if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_gsto_from_data :")) {
|
||||
::glDeleteBuffers(1,&gl_id);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_gsto().c_str());
|
||||
#endif
|
||||
gl_id = 0;
|
||||
gl_clear_errors();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int _id = m_gen_id;m_gen_id++;
|
||||
m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0);
|
||||
return _id;
|
||||
#else //!TOOLX_HAS_GL_VBO
|
||||
m_out << "toolx::sg::GL_manager::create_gsto_from_data :"
|
||||
<< " gsto mode is gl_vbo but class not compiled with TOOLX_HAS_GL_VBO."
|
||||
<< std::endl;
|
||||
return 0;
|
||||
#endif //TOOLX_HAS_GL_VBO
|
||||
}break;
|
||||
case tools::sg::gsto_gl_list:{
|
||||
unsigned int gl_id = 0;
|
||||
unsigned int _id = m_gen_id;m_gen_id++;
|
||||
m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data);
|
||||
return _id;
|
||||
}break;
|
||||
case tools::sg::gsto_memory:{
|
||||
unsigned int gl_id = 0;
|
||||
unsigned int _id = m_gen_id;m_gen_id++;
|
||||
m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data);
|
||||
return _id;
|
||||
}break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool is_gsto_id_valid(unsigned int a_id) const {
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
||||
if(it==m_gstos.end()) return false;
|
||||
return (*it).second->is_valid();
|
||||
}
|
||||
|
||||
virtual void delete_gsto(unsigned int a_id){
|
||||
tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
float* gsto_data(unsigned int a_id) const {
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
||||
if(it==m_gstos.end()) return 0;
|
||||
return (*it).second->m_data;
|
||||
}
|
||||
|
||||
unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) const {
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
||||
if(it==m_gstos.end()) {a_created = false;return 0;}
|
||||
if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;}
|
||||
if((*it).second->m_gl_id) {
|
||||
a_created = false;
|
||||
return (*it).second->m_gl_id;
|
||||
} else {
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
unsigned int _id = ::glGenLists(1);
|
||||
if(!_id) {a_created = false;return 0;}
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_gsto().c_str());
|
||||
#endif
|
||||
a_created = true;
|
||||
(*it).second->m_gl_id = _id;
|
||||
return _id;
|
||||
#else
|
||||
a_created = false;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////
|
||||
virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;}
|
||||
|
||||
virtual void set_gsto_mode(tools::sg::gsto_mode a_v) {
|
||||
if(a_v==m_gsto_mode) return;
|
||||
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
||||
switch(a_v) {
|
||||
case tools::sg::gsto_gl_vbo:{
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
m_gsto_mode = a_v;
|
||||
#else
|
||||
m_gsto_mode = tools::sg::gsto_memory;
|
||||
#endif
|
||||
}break;
|
||||
case tools::sg::gsto_gl_list:{
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
m_gsto_mode = a_v;
|
||||
#else
|
||||
m_gsto_mode = tools::sg::gsto_memory;
|
||||
#endif
|
||||
}break;
|
||||
case tools::sg::gsto_memory:{
|
||||
m_gsto_mode = tools::sg::gsto_memory;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void available_gsto_modes(std::vector<std::string>& a_vs) {
|
||||
a_vs.clear();
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
a_vs.push_back(tools::sg::s_gsto_gl_vbo());
|
||||
#endif
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
a_vs.push_back(tools::sg::s_gsto_gl_list());
|
||||
#endif
|
||||
a_vs.push_back(tools::sg::s_gsto_memory());
|
||||
}
|
||||
|
||||
virtual void available_not_memory_gsto_mode(std::string& a_v) const {
|
||||
a_v.clear();
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
a_v = tools::sg::s_gsto_gl_vbo();
|
||||
#endif
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
if(a_v.empty()) a_v = tools::sg::s_gsto_gl_list();
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual size_t used_texture_memory() const {
|
||||
size_t sz = 0;
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it;
|
||||
for(it=m_gstos.begin();it!=m_gstos.end();++it) {
|
||||
if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
virtual size_t gstos_size() const {
|
||||
size_t sz = 0;
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it;
|
||||
for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size;
|
||||
return sz;
|
||||
}
|
||||
|
||||
public:
|
||||
GL_manager(std::ostream& a_out)
|
||||
:m_out(a_out)
|
||||
,m_gen_id(1)
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs.
|
||||
#elif TOOLX_HAS_GL_LIST
|
||||
,m_gsto_mode(tools::sg::gsto_gl_list)
|
||||
#else
|
||||
,m_gsto_mode(tools::sg::gsto_memory)
|
||||
#endif
|
||||
,m_warned(false)
|
||||
{}
|
||||
virtual ~GL_manager(){
|
||||
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
||||
}
|
||||
public:
|
||||
GL_manager(const GL_manager& a_from)
|
||||
:parent(a_from)
|
||||
,m_out(a_from.m_out)
|
||||
,m_gen_id(a_from.m_gen_id)
|
||||
,m_gsto_mode(a_from.m_gsto_mode)
|
||||
,m_warned(false)
|
||||
{}
|
||||
GL_manager& operator=(const GL_manager& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
m_gen_id = a_from.m_gen_id;
|
||||
m_gsto_mode = a_from.m_gsto_mode;
|
||||
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
||||
m_warned = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
void bind_gsto(unsigned int a_id) {
|
||||
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
||||
if(it==m_gstos.end()) return;
|
||||
(*it).second->bind();
|
||||
}
|
||||
|
||||
void delete_gstos() {
|
||||
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) {
|
||||
//WARNING : it does OpenGL. Under Android it should be executed
|
||||
// in the OpenGL thread.
|
||||
//NOTE : Android, iOS : RGB produces a black image.
|
||||
unsigned char* rgbas = new unsigned char[4 * a_w * a_h];
|
||||
if(!rgbas) return 0;
|
||||
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
|
||||
::glReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas);
|
||||
/*{size_t number = 4 * a_w * a_h;
|
||||
size_t count_not_255 = 0;
|
||||
for(size_t item=3;item<number;item+=4) {
|
||||
unsigned char a = rgbas[item];
|
||||
if(a!=255) {
|
||||
::printf("%lu : %d\n",item,a);
|
||||
count_not_255++;
|
||||
rgbas[item] = 255;
|
||||
}
|
||||
}
|
||||
::printf("not_255 : %lu\n",count_not_255);}*/
|
||||
return rgbas;
|
||||
}
|
||||
|
||||
#if defined(TARGET_OS_IPHONE) || defined(ANDROID)
|
||||
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
|
||||
unsigned char* rgbas = get_rgbas(a_w,a_h);
|
||||
if(!rgbas) return 0;
|
||||
unsigned char* rgbs = tools::_4s_to_3s<unsigned char,unsigned int>(rgbas,a_w,a_h);
|
||||
delete [] rgbas;
|
||||
return rgbs;
|
||||
}
|
||||
#else
|
||||
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
|
||||
//WARNING : it does OpenGL. Under Android it should be executed
|
||||
// in the OpenGL thread.
|
||||
//NOTE : Android, iOS : RGB produces a black image.
|
||||
unsigned char* rgbs = new unsigned char[3 * a_w * a_h];
|
||||
if(!rgbs) return 0;
|
||||
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
|
||||
::glReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs);
|
||||
return rgbs;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::ostream& m_out;
|
||||
|
||||
class gsto_t {
|
||||
TOOLS_SCLASS(GL_manager::gsto_t)
|
||||
public:
|
||||
enum kind {
|
||||
kind_texture,
|
||||
kind_buffer,
|
||||
kind_list,
|
||||
kind_memory
|
||||
};
|
||||
public:
|
||||
gsto_t(kind a_kind,int a_gl_id,size_t a_size,const float* a_data)
|
||||
:m_gl_id(a_gl_id)
|
||||
,m_kind(a_kind)
|
||||
,m_size(a_size)
|
||||
,m_data(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
if(a_data) {
|
||||
size_t num = m_size/sizeof(float);
|
||||
m_data = new float[num];
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_new().c_str());
|
||||
#endif
|
||||
::memcpy(m_data,a_data,m_size);
|
||||
}
|
||||
}
|
||||
virtual ~gsto_t() {
|
||||
if(m_kind==kind_texture) {
|
||||
::glDeleteTextures(1,&m_gl_id);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_tex().c_str());
|
||||
#endif
|
||||
} else if(m_kind==kind_buffer) {
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
::glDeleteBuffers(1,&m_gl_id);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_gsto().c_str());
|
||||
#endif
|
||||
#endif
|
||||
} else if(m_kind==kind_list) {
|
||||
if(m_gl_id) {
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
::glDeleteLists(m_gl_id,1);
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_gsto().c_str());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(m_data) {
|
||||
delete [] m_data;
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_new().c_str());
|
||||
#endif
|
||||
}
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
gsto_t(const gsto_t& a_from)
|
||||
:m_gl_id(a_from.m_gl_id)
|
||||
,m_kind(a_from.m_kind)
|
||||
,m_size(a_from.m_size)
|
||||
,m_data(0)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
if(a_from.m_data) {
|
||||
size_t num = m_size/sizeof(float);
|
||||
m_data = new float[num];
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_new().c_str());
|
||||
#endif
|
||||
::memcpy(m_data,a_from.m_data,m_size);
|
||||
}
|
||||
}
|
||||
gsto_t& operator=(const gsto_t& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
m_gl_id = a_from.m_gl_id;
|
||||
m_kind = a_from.m_kind;
|
||||
m_size = a_from.m_size;
|
||||
if(m_data) {
|
||||
delete [] m_data;
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(tools::s_new().c_str());
|
||||
#endif
|
||||
m_data = 0;
|
||||
}
|
||||
if(a_from.m_data) {
|
||||
size_t num = m_size/sizeof(float);
|
||||
m_data = new float[num];
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(tools::s_new().c_str());
|
||||
#endif
|
||||
::memcpy(m_data,a_from.m_data,m_size);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
bool is_valid() const {
|
||||
if(m_kind==kind_texture) {
|
||||
return (::glIsTexture(m_gl_id)==GL_TRUE?true:false);
|
||||
} else if(m_kind==kind_buffer) {
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false);
|
||||
#endif
|
||||
} else if(m_kind==kind_list) {
|
||||
#ifdef TOOLX_HAS_GL_LIST
|
||||
return (::glIsList(m_gl_id)==GL_TRUE?true:false);
|
||||
#endif
|
||||
} else if(m_kind==kind_memory) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void bind() const {
|
||||
if(m_kind==kind_texture) {
|
||||
::glBindTexture(GL_TEXTURE_2D,m_gl_id);
|
||||
} else if(m_kind==kind_buffer) {
|
||||
#ifdef TOOLX_HAS_GL_VBO
|
||||
::glBindBuffer(GL_ARRAY_BUFFER,m_gl_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
public:
|
||||
unsigned int m_gl_id;
|
||||
kind m_kind;
|
||||
size_t m_size;
|
||||
float* m_data;
|
||||
};
|
||||
|
||||
std::map<unsigned int,gsto_t*> m_gstos;
|
||||
|
||||
bool m_gsto_on_card;
|
||||
unsigned int m_gen_id;
|
||||
tools::sg::gsto_mode m_gsto_mode;
|
||||
bool m_warned;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_sg_GL_viewer
|
||||
#define toolx_sg_GL_viewer
|
||||
|
||||
#include <tools/sg/viewer>
|
||||
|
||||
#include "GL_manager"
|
||||
#include "GL_action"
|
||||
|
||||
namespace toolx {
|
||||
namespace sg {
|
||||
|
||||
class GL_viewer : public tools::sg::viewer {
|
||||
TOOLS_HEADER(GL_viewer,toolx::sg::GL_viewer,tools::sg::viewer)
|
||||
public:
|
||||
void render() {
|
||||
if(!m_ww) return;
|
||||
if(!m_wh) return;
|
||||
|
||||
m_gl_mgr.begin_render(0,0,m_ww,m_wh,
|
||||
m_clear_color.r(),
|
||||
m_clear_color.g(),
|
||||
m_clear_color.b(),
|
||||
m_clear_color.a());
|
||||
|
||||
GL_action action(m_gl_mgr,m_out,m_ww,m_wh);
|
||||
action.state().m_use_gsto = m_use_gsto;
|
||||
|
||||
action.set_do_transparency(false);
|
||||
action.set_have_to_do_transparency(false);
|
||||
|
||||
m_sg.render(action);
|
||||
if(!action.end()) { //check that matrices stack are ok.
|
||||
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
|
||||
} else {
|
||||
if(action.have_to_do_transparency()) {
|
||||
action.set_do_transparency(true);
|
||||
m_sg.render(action);
|
||||
if(!action.end()) { //check that matrices stack are ok.
|
||||
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//after_render();
|
||||
|
||||
m_gl_mgr.end_render();
|
||||
}
|
||||
|
||||
public:
|
||||
GL_viewer(std::ostream& a_out,unsigned int a_width,unsigned int a_height)
|
||||
:parent(a_out,a_width,a_height)
|
||||
,m_gl_mgr(a_out)
|
||||
{}
|
||||
virtual ~GL_viewer(){
|
||||
//WARNING : nodes may refer m_gl_mgr (to handle gstos/texs), then
|
||||
// we have to delete them first.
|
||||
m_sg.clear();
|
||||
}
|
||||
public:
|
||||
GL_viewer(const GL_viewer& a_from)
|
||||
:parent(a_from)
|
||||
,m_gl_mgr(a_from.m_gl_mgr)
|
||||
{}
|
||||
GL_viewer& operator=(const GL_viewer& a_from){
|
||||
parent::operator=(a_from);
|
||||
m_gl_mgr = a_from.m_gl_mgr;
|
||||
return *this;
|
||||
}
|
||||
protected:
|
||||
GL_manager m_gl_mgr;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_sg_gl
|
||||
#define toolx_sg_gl
|
||||
|
||||
#include "../OpenGL"
|
||||
|
||||
#include <tools/platform> //for APPLE TargetConditionals.h
|
||||
#include <tools/img>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
namespace sg {
|
||||
//namespace gl : no, problem with g4tools.
|
||||
|
||||
inline void gl_clear_errors() {
|
||||
GLenum glerror = ::glGetError();
|
||||
while(glerror!=GL_NO_ERROR) {
|
||||
glerror = ::glGetError();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool gl_dump_if_errors(std::ostream& a_out,const std::string& a_head) {
|
||||
bool retval = false;
|
||||
GLenum glerror = ::glGetError();
|
||||
if(glerror!=GL_NO_ERROR) {
|
||||
a_out << a_head
|
||||
<< " we have gl errors :"
|
||||
<< std::endl;
|
||||
retval = true;
|
||||
}
|
||||
while(glerror!=GL_NO_ERROR) {
|
||||
//#define GL_NO_ERROR 0
|
||||
//#define GL_INVALID_ENUM 0x0500
|
||||
//#define GL_INVALID_VALUE 0x0501
|
||||
//#define GL_INVALID_OPERATION 0x0502
|
||||
//#define GL_STACK_OVERFLOW 0x0503
|
||||
//#define GL_STACK_UNDERFLOW 0x0504
|
||||
//#define GL_OUT_OF_MEMORY 0x0505
|
||||
|
||||
//#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
|
||||
|
||||
a_out << "0x" << std::hex << glerror << std::endl;
|
||||
|
||||
glerror = ::glGetError();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
inline void gl_dump_infos(std::ostream& a_out) {
|
||||
std::string gl_version;
|
||||
{const char* _sv = (const char*)::glGetString(GL_VERSION);
|
||||
if(_sv) gl_version = _sv;}
|
||||
|
||||
std::string gl_vendor;
|
||||
{const char* _sv = (const char*)::glGetString(GL_VENDOR);
|
||||
if(_sv) gl_vendor = _sv;}
|
||||
|
||||
std::string gl_renderer;
|
||||
{const char* _sv = (const char*)::glGetString(GL_RENDERER);
|
||||
if(_sv) gl_renderer = _sv;}
|
||||
|
||||
std::string gl_extensions;
|
||||
{const char* _sv = (const char*)::glGetString(GL_EXTENSIONS);
|
||||
if(_sv) gl_extensions = _sv;}
|
||||
|
||||
GLint gl_texture_size;
|
||||
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_texture_size);
|
||||
|
||||
//GLint gl_buffer_size;
|
||||
//::glGetIntegerv(GL_BUFFER_SIZE, &gl_buffer_size);
|
||||
|
||||
a_out << "toolx::sg::gl::dump_infos :" << std::endl;
|
||||
a_out << " GL_VERSION " << gl_version << std::endl;
|
||||
a_out << " GL_VENDOR " << gl_vendor << std::endl;
|
||||
a_out << " GL_RENDERER " << gl_renderer << std::endl;
|
||||
a_out << " GL_EXTENSIONS " << gl_extensions << std::endl;
|
||||
a_out << " GL_MAX_TEXTURE_SIZE " << gl_texture_size << std::endl;
|
||||
//a_out << " GL_BUFFER_SIZE " << gl_buffer_size << std::endl;
|
||||
}
|
||||
|
||||
inline bool gl_tex_img(std::ostream& a_out,const tools::img_byte& a_img) {
|
||||
if(a_img.bpp()==1) {
|
||||
//to pass eiffel-tower.png
|
||||
#if defined(ANDROID) || TARGET_OS_IPHONE
|
||||
tools::img_byte res;
|
||||
if(!a_img.bw2x(3,res)) {
|
||||
a_out << "toolx::sg::gl::tex_img : toolx::img.bw2x() failed." << std::endl;
|
||||
return false;
|
||||
}
|
||||
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,res.width(),res.height(),0,GL_RGB,GL_UNSIGNED_BYTE,res.buffer());
|
||||
#else
|
||||
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_LUMINANCE,GL_UNSIGNED_BYTE,a_img.buffer());
|
||||
#endif
|
||||
} else if(a_img.bpp()==3) {
|
||||
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_RGB,GL_UNSIGNED_BYTE,a_img.buffer());
|
||||
} else if(a_img.bpp()==4) {
|
||||
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,a_img.width(),a_img.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,a_img.buffer());
|
||||
} else {
|
||||
a_out << "toolx::sg::gl::tex_img : img.bpp() " << a_img.bpp() << " not treated." << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+2161
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,264 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_sg_text_freetype_marker
|
||||
#define toolx_sg_text_freetype_marker
|
||||
|
||||
#include "text_freetype"
|
||||
|
||||
namespace toolx {
|
||||
namespace sg {
|
||||
|
||||
class text_freetype_marker : public text_freetype {
|
||||
TOOLS_NODE(text_freetype_marker,toolx::sg::text_freetype_marker,text_freetype)
|
||||
public:
|
||||
virtual bool draw_in_frame_buffer() const {return true;}
|
||||
|
||||
virtual void render(tools::sg::render_action& a_action) {
|
||||
{bool _color_touched = color_touched(a_action.state());
|
||||
bool _char_height_touched = char_height_touched(a_action.state());
|
||||
if(touched()||_color_touched||_char_height_touched) {
|
||||
update_sg(a_action.out(),font.touched(),a_action.state());
|
||||
reset_touched();
|
||||
}}
|
||||
|
||||
const tools::sg::state& state = a_action.state();
|
||||
|
||||
a_action.set_lighting(false); //Same logic as Inventor SoLightModel.model = BASE_COLOR.
|
||||
a_action.set_depth_test(false);
|
||||
|
||||
if(m_wndg==wndg_ccw) a_action.set_winding(tools::sg::winding_ccw);
|
||||
else if(m_wndg==wndg_cw) a_action.set_winding(tools::sg::winding_cw);
|
||||
|
||||
float x,y,z;
|
||||
a_action.projected_origin(x,y,z);
|
||||
float zz = 0;
|
||||
|
||||
a_action.load_matrices_to_identity();
|
||||
|
||||
{tools::mat4f _mtx;
|
||||
_mtx.set_translate(x,y,zz);
|
||||
if(!m_bitmaps.size()) {
|
||||
if(state.m_ww) _mtx.mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
|
||||
}
|
||||
a_action.load_model_matrix(_mtx);}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// lines /////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
{tools_vforcit(line_t,m_lines,it) {
|
||||
const line_t& item = *it;
|
||||
size_t pos = item.first;
|
||||
size_t num = item.second;
|
||||
if(!num) continue;
|
||||
const float* data = tools::vec_data<float>(m_xys)+pos;
|
||||
a_action.draw_vertex_array_xy(tools::gl::line_strip(),num*2,data);
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// triangles /////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
{tools_vforcit(gl_triangle_t,m_triangles,it) {
|
||||
const std::pair<GLUenum,triangle_t>& item = *it;
|
||||
size_t pos = item.second.first;
|
||||
size_t num = item.second.second;
|
||||
if(!num) continue;
|
||||
//a_out << "toolx::sg::text_freetype_marker::render :"
|
||||
// << " num points " << num
|
||||
// << std::endl;
|
||||
|
||||
const float* data = tools::vec_data<float>(m_xys)+pos;
|
||||
a_action.draw_vertex_array_xy((*it).first,num*2,data);
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// bitmap ////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
if(m_bitmaps.size()) {
|
||||
#if defined(ANDROID) /*|| TARGET_OS_IPHONE*/
|
||||
// we do not have transparent texture here (see also gl/tex_img() that does img/4-bytes => img/3-bytes) :
|
||||
{tools::sg::state& _state = a_action.state();
|
||||
tools::colorf old_color = _state.m_color;
|
||||
_state.m_color = tools::colorf_white();
|
||||
a_action.color4f(_state.m_color);
|
||||
m_bitmaps.render(a_action);
|
||||
_state.m_color = old_color;
|
||||
a_action.color4f(_state.m_color);}
|
||||
#else
|
||||
m_bitmaps.render(a_action);
|
||||
#endif
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
a_action.load_matrices_from_state();
|
||||
|
||||
a_action.set_depth_test(state.m_GL_DEPTH_TEST);
|
||||
a_action.set_lighting(state.m_GL_LIGHTING);
|
||||
a_action.set_winding(state.m_winding);
|
||||
|
||||
}
|
||||
|
||||
virtual void pick(tools::sg::pick_action& a_action) {
|
||||
const tools::sg::state& state = a_action.state();
|
||||
|
||||
{bool _char_height_touched = char_height_touched(a_action.state());
|
||||
if(touched()||_char_height_touched) {
|
||||
update_sg(a_action.out(),font.touched(),a_action.state());
|
||||
reset_touched();
|
||||
}}
|
||||
|
||||
float x,y,z;
|
||||
a_action.projected_origin(x,y,z);
|
||||
float zz = 0;
|
||||
|
||||
a_action.set_matrices_to_identity();
|
||||
|
||||
a_action.model_matrix().set_translate(x,y,zz);
|
||||
if(!m_bitmaps.size()) {
|
||||
if(state.m_ww) a_action.model_matrix().mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// lines /////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
{tools_vforcit(line_t,m_lines,it) {
|
||||
const line_t& item = *it;
|
||||
size_t pos = item.first;
|
||||
size_t num = item.second;
|
||||
if(!num) continue;
|
||||
|
||||
const float* data = tools::vec_data<float>(m_xys)+pos;
|
||||
float* vp = _trans2(num,data,x,y);
|
||||
if(!vp) continue;
|
||||
|
||||
if(a_action.add__line_strip_xy(*this,2*num,vp,true)) {
|
||||
delete [] vp;
|
||||
a_action.set_matrices_from_state();
|
||||
return;
|
||||
}
|
||||
|
||||
delete [] vp;
|
||||
}}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// triangles /////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
{tools_vforcit(gl_triangle_t,m_triangles,it) {
|
||||
const std::pair<GLUenum,triangle_t>& item = *it;
|
||||
size_t pos = item.second.first;
|
||||
size_t num = item.second.second;
|
||||
if(!num) continue;
|
||||
|
||||
const float* data = tools::vec_data<float>(m_xys)+pos;
|
||||
float* vp = _trans2(num,data,x,y);
|
||||
if(!vp) continue;
|
||||
if(a_action.add__primitive_xy(*this,item.first,2*num,vp,true)){
|
||||
delete [] vp;
|
||||
a_action.set_matrices_from_state();
|
||||
return;
|
||||
}
|
||||
delete [] vp;
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// bitmap ////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
if(m_bitmaps.size()) {
|
||||
m_bitmaps.pick(a_action);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
a_action.set_matrices_from_state();
|
||||
}
|
||||
|
||||
virtual void bbox(tools::sg::bbox_action& a_action) {
|
||||
{bool _char_height_touched = char_height_touched(a_action.state());
|
||||
if(touched()||_char_height_touched) {
|
||||
update_sg(a_action.out(),font.touched(),a_action.state());
|
||||
reset_touched();
|
||||
}}
|
||||
a_action.add_one_point(0,0,0);
|
||||
/*
|
||||
{tools_vforcit(line_t,m_lines,it) {
|
||||
const line_t& item = *it;
|
||||
size_t num = item.second;
|
||||
const float* data = tools::vec_data<float>(m_xys)+item.first;
|
||||
|
||||
float px,py,pz;
|
||||
float* pos = (float*)data;
|
||||
for(size_t index=0;index<num;index++) {
|
||||
px = *pos;pos++;
|
||||
py = *pos;pos++;
|
||||
pz = 0;
|
||||
a_action.add_one_point(px,py,pz);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// triangles /////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
{tools_vforcit(gl_triangle_t,m_triangles,it) {
|
||||
const std::pair<GLUenum,triangle_t>& item = *it;
|
||||
size_t num = item.second.second;
|
||||
const float* data = tools::vec_data<float>(m_xys)+item.second.first;
|
||||
|
||||
float px,py,pz;
|
||||
float* pos = (float*)data;
|
||||
for(size_t index=0;index<num;index++) {
|
||||
px = *pos;pos++;
|
||||
py = *pos;pos++;
|
||||
pz = 0;
|
||||
a_action.add_one_point(px,py,pz);
|
||||
}
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
/// bitmap ////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////
|
||||
m_bitmaps.bbox(a_action);
|
||||
*/
|
||||
}
|
||||
|
||||
public:
|
||||
text_freetype_marker():parent(){
|
||||
height = 10; //pixels
|
||||
}
|
||||
virtual ~text_freetype_marker(){}
|
||||
public:
|
||||
text_freetype_marker(const text_freetype_marker& a_from):parent(a_from) {}
|
||||
text_freetype_marker& operator=(const text_freetype_marker& a_from){parent::operator=(a_from);return *this;}
|
||||
protected:
|
||||
void update_sg(std::ostream& a_out,bool a_load_font,const tools::sg::state& a_state) {
|
||||
if(!a_state.m_wh) {parent::update_sg(a_out,a_load_font);return;}
|
||||
float sy = 2.0f*float(height.value())/float(a_state.m_wh); //in [-1,1]
|
||||
float old_height = height.value();
|
||||
height.value_no_cmp(sy);
|
||||
//update_what what = lines;
|
||||
//if(modeling==tools::sg::font_filled) what = faces_and_lines;
|
||||
parent::update_sg(a_out,a_load_font);
|
||||
height.value_no_cmp(old_height);
|
||||
}
|
||||
|
||||
float* _trans2(size_t a_num,const float* a_data,float a_x,float a_y) {
|
||||
float* vp = new float[a_num*2];
|
||||
if(!vp) return 0;
|
||||
float* pos = vp;
|
||||
float* pda = (float*)a_data;
|
||||
for(size_t index=0;index<a_num;index++){
|
||||
*pos = *pda + a_x;pos++;pda++;
|
||||
*pos = *pda + a_y;pos++;pda++;
|
||||
}
|
||||
return vp;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
+578
@@ -0,0 +1,578 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_xml_loader
|
||||
#define toolx_xml_loader
|
||||
|
||||
#include <tools/xml/tree>
|
||||
#include <tools/file>
|
||||
#include <tools/mnmx>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cctype> //iscntrl
|
||||
|
||||
#include <expat.h>
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
#include <tools/mem>
|
||||
namespace toolx {
|
||||
extern "C" {
|
||||
inline void* xml_malloc(size_t a_size){
|
||||
tools::mem::increment(tools::s_malloc().c_str());
|
||||
return ::malloc(a_size);
|
||||
}
|
||||
inline void* xml_realloc(void* a_ptr,size_t a_size){
|
||||
if(a_ptr==NULL) tools::mem::increment(tools::s_malloc().c_str());
|
||||
return ::realloc(a_ptr,a_size);
|
||||
}
|
||||
inline void xml_free(void* a_ptr){
|
||||
if(a_ptr!=NULL) tools::mem::decrement(tools::s_malloc().c_str());
|
||||
::free(a_ptr);
|
||||
}
|
||||
}}
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
namespace xml {
|
||||
|
||||
class loader {
|
||||
#ifdef TOOLS_MEM
|
||||
TOOLS_SCLASS(toolx::xml::loader)
|
||||
#endif
|
||||
public:
|
||||
loader(tools::xml::factory& a_factory,
|
||||
std::ostream& a_out,bool a_verbose = false)
|
||||
:m_factory(a_factory)
|
||||
,m_out(a_out)
|
||||
,m_verbose(a_verbose)
|
||||
,m_take_cntrl(false)
|
||||
|
||||
,m_errors(0)
|
||||
,m_top(0) // Used to cleanup in case XML parsing failed.
|
||||
,m_current(0)
|
||||
,m_compressed_reader(0)
|
||||
,m_depth(0)
|
||||
,m_abort(false)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~loader(){
|
||||
delete m_compressed_reader;
|
||||
clear();
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::decrement(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
loader(const loader& a_from)
|
||||
:m_factory(a_from.m_factory)
|
||||
,m_out(a_from.m_out)
|
||||
,m_verbose(a_from.m_verbose)
|
||||
,m_take_cntrl(a_from.m_take_cntrl)
|
||||
|
||||
,m_errors(0)
|
||||
,m_top(0) // Used to cleanup in case XML parsing failed.
|
||||
,m_current(0)
|
||||
,m_compressed_reader(0)
|
||||
,m_depth(0)
|
||||
,m_abort(false)
|
||||
{
|
||||
#ifdef TOOLS_MEM
|
||||
tools::mem::increment(s_class().c_str());
|
||||
#endif
|
||||
}
|
||||
loader& operator=(const loader& a_from){
|
||||
if(&a_from==this) return *this;
|
||||
|
||||
m_verbose = a_from.m_verbose;
|
||||
m_take_cntrl = a_from.m_take_cntrl;
|
||||
|
||||
m_errors = 0;
|
||||
m_top = 0;
|
||||
m_current = 0;
|
||||
m_compressed_reader = 0;
|
||||
m_depth = 0;
|
||||
m_abort = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool visit_end_element(tools::xml::tree&,bool& a_keep) {
|
||||
a_keep = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
void set_take_cntrl_chars(bool a_value) {m_take_cntrl = a_value;}
|
||||
|
||||
std::ostream& out() const {return m_out;}
|
||||
void set_compressed_reader(tools::file::reader* aReader){
|
||||
delete m_compressed_reader;
|
||||
m_compressed_reader = aReader; //take ownership.
|
||||
}
|
||||
|
||||
unsigned int errors() const {return m_errors;}
|
||||
|
||||
void set_tags(const std::vector<std::string>& a_tags){m_tags=a_tags;}
|
||||
void add_tag(const std::string& a_tag){m_tags.push_back(a_tag);}
|
||||
|
||||
bool load_file(const std::string& a_file,bool a_compressed) {
|
||||
clear();
|
||||
if(!parse_file(a_file,
|
||||
(XML_StartElementHandler)start_element,
|
||||
(XML_EndElementHandler)end_element,
|
||||
this,a_compressed)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
if(m_current) m_current->set_file(a_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_string(const std::string& a_string){
|
||||
clear();
|
||||
if(!parse_buffer(a_string.size(),a_string.c_str(),
|
||||
(XML_StartElementHandler)start_element,
|
||||
(XML_EndElementHandler)end_element,
|
||||
this)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool load_buffer(size_t aSize,const char* aBuffer){
|
||||
clear();
|
||||
if(!parse_buffer(aSize,aBuffer,
|
||||
(XML_StartElementHandler)start_element,
|
||||
(XML_EndElementHandler)end_element,
|
||||
this)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const tools::xml::tree* top_item() const {return m_current;}
|
||||
|
||||
tools::xml::tree* top_item(){return m_current;}
|
||||
|
||||
void empty(){m_top = 0;m_current = 0;}
|
||||
|
||||
bool is_tag(const std::string& a_string) const {
|
||||
size_t number = m_tags.size();
|
||||
for(size_t index=0;index<number;index++) {
|
||||
if(a_string==m_tags[index]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
void clear(){
|
||||
// In case of problem, deleting m_current is not sufficient.
|
||||
delete m_top;
|
||||
m_top = 0;
|
||||
m_current = 0;
|
||||
}
|
||||
|
||||
bool parse_buffer(size_t aSize,const char* aBuffer,
|
||||
XML_StartElementHandler a_start,XML_EndElementHandler a_end,
|
||||
void* a_tag){
|
||||
m_errors = 0;
|
||||
if(!aSize) return true; //nothing to do.
|
||||
m_depth = 0;
|
||||
m_abort = false;
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
XML_Memory_Handling_Suite mem;
|
||||
mem.malloc_fcn = xml_malloc;
|
||||
mem.realloc_fcn = xml_realloc;
|
||||
mem.free_fcn = xml_free;
|
||||
XML_Parser _parser = XML_ParserCreate_MM(NULL,&mem,NULL);
|
||||
#else
|
||||
XML_Parser _parser = XML_ParserCreate(NULL);
|
||||
#endif
|
||||
|
||||
XML_SetUserData(_parser,a_tag);
|
||||
XML_SetElementHandler(_parser,a_start,a_end);
|
||||
XML_SetCharacterDataHandler(_parser,(XML_CharacterDataHandler)character_data_handler);
|
||||
//XML_SetProcessingInstructionHandler(_parser,processingInstructionHandler);
|
||||
char* buf = (char*)aBuffer;
|
||||
size_t l = aSize;
|
||||
int done = 0;
|
||||
do {
|
||||
size_t len = tools::mn<size_t>(l,BUFSIZ); //BUFSIZ in cstdio
|
||||
done = len < BUFSIZ ? 1 : 0;
|
||||
if(XML_Parse(_parser, buf, (int)len, done)==XML_STATUS_ERROR) {
|
||||
m_out << "parse_buffer :"
|
||||
<< " " << XML_ErrorString(XML_GetErrorCode(_parser))
|
||||
<< " at line " << (int)XML_GetCurrentLineNumber(_parser)
|
||||
<< " at byte index " << (int)XML_GetCurrentByteIndex(_parser)
|
||||
<< std::endl;
|
||||
{XML_Index pos = XML_GetCurrentByteIndex(_parser);
|
||||
XML_Index pmn = tools::mx<XML_Index>(pos-10,0);
|
||||
XML_Index pmx = tools::mn<XML_Index>(pos+10,XML_Index(aSize)-1);
|
||||
std::string c = " ";
|
||||
{for(XML_Index p=pmn;p<=pmx;p++) {c[0] = *(aBuffer+p);m_out << c;}
|
||||
m_out << std::endl;}
|
||||
{for(XML_Index p=pmn;p<pos;p++) m_out << " ";
|
||||
m_out << "^" << std::endl;}}
|
||||
XML_ParserFree(_parser);
|
||||
return false;
|
||||
}
|
||||
if(m_abort) {
|
||||
XML_ParserFree(_parser);
|
||||
return false;
|
||||
}
|
||||
buf += len;
|
||||
l -= len;
|
||||
} while (!done);
|
||||
XML_ParserFree(_parser);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_file(const std::string& a_file,
|
||||
XML_StartElementHandler a_start,XML_EndElementHandler a_end,
|
||||
void* a_tag,bool a_compressed){
|
||||
if(m_verbose) {
|
||||
m_out << "parse_file :"
|
||||
<< " parse file " << tools::sout(a_file) << "..." << std::endl;
|
||||
}
|
||||
m_errors = 0;
|
||||
|
||||
bool use_zlib = false;
|
||||
if(a_compressed) {
|
||||
if(m_verbose) {
|
||||
m_out << "parse_file :"
|
||||
<< " uncompress requested for file "
|
||||
<< tools::sout(a_file) << "."
|
||||
<< std::endl;
|
||||
}
|
||||
use_zlib = true;
|
||||
} else {
|
||||
// may be compressed anyway :
|
||||
bool compressed;
|
||||
if(!tools::file::is_gzip(a_file,compressed)) {
|
||||
m_out << "parse_file :"
|
||||
<< " tools::file::is_gzip() failed for " << a_file << "."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
if(compressed) use_zlib = true;
|
||||
}
|
||||
|
||||
tools::file::reader* freader = 0;
|
||||
bool delete_freader = false;
|
||||
if(use_zlib) {
|
||||
if(!m_compressed_reader) {
|
||||
m_out << "parse_file :"
|
||||
<< " no compressed reader given."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
freader = m_compressed_reader;
|
||||
} else {
|
||||
freader = new tools::FILE_reader();
|
||||
delete_freader = true;
|
||||
}
|
||||
if(!freader->open(a_file)) {
|
||||
m_out << "parse_file :"
|
||||
<< " can't open file " << a_file << std::endl;
|
||||
if(delete_freader) delete freader;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_depth = 0;
|
||||
m_abort = false;
|
||||
|
||||
#ifdef TOOLS_MEM
|
||||
XML_Memory_Handling_Suite mem;
|
||||
mem.malloc_fcn = xml_malloc;
|
||||
mem.realloc_fcn = xml_realloc;
|
||||
mem.free_fcn = xml_free;
|
||||
XML_Parser _parser = XML_ParserCreate_MM(NULL,&mem,NULL);
|
||||
#else
|
||||
XML_Parser _parser = XML_ParserCreate(NULL);
|
||||
#endif
|
||||
|
||||
XML_SetUserData(_parser,a_tag);
|
||||
XML_SetElementHandler(_parser,a_start,a_end);
|
||||
XML_SetCharacterDataHandler(_parser,(XML_CharacterDataHandler)character_data_handler);
|
||||
//XML_SetProcessingInstructionHandler(_parser,
|
||||
// processingInstructionHandler);
|
||||
|
||||
|
||||
//char buf[1024 * BUFSIZ];
|
||||
char buf[BUFSIZ];
|
||||
int done = 0;
|
||||
do {
|
||||
size_t len;
|
||||
if(!freader->read(buf,sizeof(buf),len)) {
|
||||
XML_ParserFree(_parser);
|
||||
freader->close();
|
||||
if(delete_freader) delete freader;
|
||||
return false;
|
||||
}
|
||||
done = len < sizeof(buf) ? 1 : 0;
|
||||
if(XML_Parse(_parser, buf, (int)len, done)==XML_STATUS_ERROR) {
|
||||
m_out << "parse_file :"
|
||||
<< " in file " << tools::sout(a_file)
|
||||
<< " " << XML_ErrorString(XML_GetErrorCode(_parser))
|
||||
<< " at line " << (int)XML_GetCurrentLineNumber(_parser)
|
||||
<< std::endl;
|
||||
XML_ParserFree(_parser);
|
||||
freader->close();
|
||||
if(delete_freader) delete freader;
|
||||
return false;
|
||||
}
|
||||
if(m_abort) {
|
||||
XML_ParserFree(_parser);
|
||||
freader->close();
|
||||
if(delete_freader) delete freader;
|
||||
return false;
|
||||
}
|
||||
} while (!done);
|
||||
XML_ParserFree(_parser);
|
||||
freader->close();
|
||||
if(m_verbose) {
|
||||
m_out << "parse_file :"
|
||||
<< " parse file " << tools::sout(a_file) << " done." << std::endl;
|
||||
}
|
||||
if(delete_freader) delete freader;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
static void character_data_handler(void* aUserData,const XML_Char* a_string,int aLength){
|
||||
loader* This = (loader*)aUserData;
|
||||
std::string _s;
|
||||
_s.resize(aLength);
|
||||
size_t count = 0;
|
||||
char* p = (char*)a_string;
|
||||
for (int i = 0; i < aLength; i++, p++) {
|
||||
if(This->m_take_cntrl || (!iscntrl(*p))) {
|
||||
_s[count] = *p;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if(count) {
|
||||
_s.resize(count);
|
||||
This->m_value += _s;
|
||||
}
|
||||
}
|
||||
|
||||
static void start_element(void* aUserData,const XML_Char* a_name,const XML_Char** a_atbs){
|
||||
loader* This = (loader*)aUserData;
|
||||
if(This->m_abort) return; //Do nothing.
|
||||
|
||||
This->m_depth++;
|
||||
This->m_value = "";
|
||||
|
||||
std::string name = a_name; //Can't be empty
|
||||
if(This->is_tag(name)) {
|
||||
|
||||
if(!This->m_current) {
|
||||
if(This->m_depth==1) {
|
||||
// Ok. Head.
|
||||
} else {
|
||||
This->m_out << "start_element :"
|
||||
<< " no tag with a depth of " << This->m_depth
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
int delta = This->m_current->depth() - This->m_depth;
|
||||
if(delta>=1) {
|
||||
This->m_out << "start_element :"
|
||||
<< " for element " << tools::sout(name)
|
||||
<< " tag with a delta depth of " << delta
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<tools::xml::tree::atb> atbs;
|
||||
{const XML_Char** a_atts = a_atbs;
|
||||
while((*a_atts)&&(*(a_atts+1))) {
|
||||
atbs.push_back(tools::xml::tree::atb(*a_atts,*(a_atts+1)));
|
||||
a_atts+=2;
|
||||
}}
|
||||
|
||||
tools::xml::tree* parent = This->m_current;
|
||||
tools::xml::tree* _tree = This->m_factory.create(name,atbs,parent);
|
||||
if(!_tree) {
|
||||
This->m_out << "start_element :"
|
||||
<< " can't create a tree for tag " << tools::sout(name)
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//out << "start_element :" << std::endl;
|
||||
//_tree->print_xml(*(This->m_printer),"debug : ");
|
||||
|
||||
if(parent) parent->add_child(_tree);
|
||||
|
||||
/*
|
||||
if(This->m_current && !This->m_current->parent()) {
|
||||
This->m_out << "start_element :"
|
||||
<< " warning : current tree without parent."
|
||||
<< " Potential mem leak."
|
||||
<< std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
This->m_current = _tree;
|
||||
_tree->set_depth(This->m_depth); // Internal only.
|
||||
|
||||
if(!This->m_top) This->m_top = _tree;
|
||||
|
||||
} else {
|
||||
|
||||
if(!This->m_current) {
|
||||
|
||||
// Can't be in a non-tag without a tag !
|
||||
This->m_out << "start_element :"
|
||||
<< " for element " << tools::sout(name)
|
||||
<< " non-tag without some parent tag."
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
int delta = This->m_depth - This->m_current->depth();
|
||||
if(delta>1) {
|
||||
|
||||
This->m_out << "start_element :"
|
||||
<< " for element " << tools::sout(name)
|
||||
<< " grand child of a tag."
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
|
||||
} else if(delta==1) { //ok
|
||||
|
||||
This->m_atbs.clear();
|
||||
{const XML_Char** a_atts = a_atbs;
|
||||
while((*a_atts)&&(*(a_atts+1))) {
|
||||
This->m_atbs.push_back(tools::xml::tree::atb(*a_atts,*(a_atts+1)));
|
||||
a_atts+=2;
|
||||
}}
|
||||
|
||||
} else {
|
||||
|
||||
This->m_out << "start_element :"
|
||||
<< " for element " << tools::sout(name)
|
||||
<< " non-tag with a delta depth of " << delta
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void end_element(void* aUserData,const XML_Char* a_name){
|
||||
loader* This = (loader*)aUserData;
|
||||
if(This->m_abort) return; //Do nothing.
|
||||
|
||||
if(This->m_current) {
|
||||
|
||||
tools::xml::tree* tr = This->m_current;
|
||||
int delta = This->m_depth - tr->depth();
|
||||
if(delta==0) { //Back to a tag :
|
||||
|
||||
tools::xml::tree* parent = tr->parent();
|
||||
|
||||
bool keep = false;
|
||||
bool cont = This->visit_end_element(*tr,keep);
|
||||
if(keep) {
|
||||
if(parent) {
|
||||
/*
|
||||
if(!This->m_current->parent()) {
|
||||
This->m_out << "end_element :"
|
||||
<< " warning : current tree without parent (1)."
|
||||
<< " Potential mem leak."
|
||||
<< std::endl;
|
||||
}
|
||||
*/
|
||||
This->m_current = parent;
|
||||
}
|
||||
} else {
|
||||
//FIXME : the top could be recreated !
|
||||
if(This->m_top==tr) This->m_top = 0;
|
||||
|
||||
if(parent) {
|
||||
parent->remove_child(tr); //delete the tr
|
||||
} else {
|
||||
delete tr;
|
||||
}
|
||||
|
||||
/*
|
||||
if(!This->m_current->parent()) {
|
||||
This->m_out << "end_element :"
|
||||
<< " warning : current tree without parent (2)."
|
||||
<< " Potential mem leak."
|
||||
<< std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
This->m_current = parent; //parent could be 0 : ok.
|
||||
}
|
||||
|
||||
if(!cont) This->m_abort = true;
|
||||
|
||||
} else if(delta==1) { //Back to a child of tag :
|
||||
|
||||
//FIXME : correct m_value ? (Can we pick the one of a sub item ?)
|
||||
tr->add_element(std::string(a_name),This->m_atbs,This->m_value);
|
||||
//This->m_value = "";
|
||||
|
||||
} else {
|
||||
|
||||
This->m_out << "end_element :"
|
||||
<< " problem for element " << tools::sout(std::string(a_name))
|
||||
<< " : delta depth of " << delta
|
||||
<< std::endl;
|
||||
This->m_abort = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
This->m_depth--;
|
||||
}
|
||||
|
||||
protected:
|
||||
tools::xml::factory& m_factory;
|
||||
std::ostream& m_out;
|
||||
protected:
|
||||
bool m_verbose;
|
||||
bool m_take_cntrl;
|
||||
unsigned int m_errors;
|
||||
std::vector<std::string> m_tags;
|
||||
tools::xml::tree* m_top;
|
||||
tools::xml::tree* m_current;
|
||||
//std::vector<tools::xml::tree::atb> m_atbs;
|
||||
std::vector< std::pair<std::string,std::string> > m_atbs;
|
||||
std::string m_value;
|
||||
tools::file::reader* m_compressed_reader;
|
||||
unsigned int m_depth;
|
||||
bool m_abort;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_xml_style
|
||||
#define toolx_xml_style
|
||||
|
||||
#include <tools/xml/styles>
|
||||
|
||||
#include "loader"
|
||||
|
||||
namespace toolx {
|
||||
namespace xml {
|
||||
|
||||
inline bool load_style_file(std::ostream&,const std::string& a_file,tools::xml::styles& a_styles) {
|
||||
tools::xml::default_factory factory;
|
||||
toolx::xml::loader ml(factory,a_styles.out(),false);
|
||||
std::vector<std::string> tags;
|
||||
tags.push_back("styles");
|
||||
tags.push_back("style");
|
||||
tags.push_back("plotter_style");
|
||||
ml.set_tags(tags);
|
||||
if(!ml.load_file(a_file,false)) return false;
|
||||
tools::xml::tree* top = ml.top_item();
|
||||
if(!top) return true; //File could be empty.
|
||||
return scan_style_tree(a_styles,*top);
|
||||
}
|
||||
|
||||
inline bool load_style_string(tools::xml::styles& a_styles,const std::string& a_string) {
|
||||
tools::xml::default_factory factory;
|
||||
toolx::xml::loader ml(factory,a_styles.out(),false);
|
||||
std::vector<std::string> tags;
|
||||
tags.push_back("styles");
|
||||
tags.push_back("style");
|
||||
tags.push_back("plotter_style");
|
||||
ml.set_tags(tags);
|
||||
if(!ml.load_string(a_string)) return false;
|
||||
tools::xml::tree* top = ml.top_item();
|
||||
if(!top) return true;
|
||||
return scan_style_tree(a_styles,*top);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
||||
// See the file tools.license for terms.
|
||||
|
||||
#ifndef toolx_zlib
|
||||
#define toolx_zlib
|
||||
|
||||
// what is needed for root file compression with zlib.
|
||||
|
||||
//NOTE : zlib contains deflate/inflate and also the gz functions to write/read a .gz file.
|
||||
// The gz functions use also deflate/inflate.
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace toolx {
|
||||
|
||||
inline bool compress_buffer(std::ostream& a_out,
|
||||
unsigned int a_level,
|
||||
unsigned int a_srcsize,const char* a_src,
|
||||
unsigned int a_tgtsize,char* a_tgt,
|
||||
unsigned int& a_irep) {
|
||||
|
||||
z_stream stream; // decompression stream
|
||||
|
||||
stream.next_in = (Bytef*)(a_src);
|
||||
stream.avail_in = (uInt)(a_srcsize);
|
||||
stream.next_out = (Bytef*)a_tgt;
|
||||
stream.avail_out = (uInt)(a_tgtsize);
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
stream.total_in = 0; /*to quiet Coverity.*/
|
||||
stream.total_out = 0; /*to quiet Coverity.*/
|
||||
|
||||
int err = deflateInit(&stream,a_level);
|
||||
if(err!=Z_OK) {
|
||||
a_out << "toolx::compress_buffer :"
|
||||
<< " error in zlib/deflateInit." << std::endl;
|
||||
a_irep = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if(err!=Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
a_out << "toolx::compress_buffer :"
|
||||
<< " error in zlib/deflate." << std::endl;
|
||||
a_irep = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
deflateEnd(&stream);
|
||||
|
||||
//a_out << "toolx::compress_buffer : ok "
|
||||
// << stream.total_out << std::endl;
|
||||
|
||||
a_irep = stream.total_out;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool decompress_buffer(std::ostream& a_out,
|
||||
unsigned int a_srcsize,const char* a_src,
|
||||
unsigned int a_tgtsize,char* a_tgt,
|
||||
unsigned int& a_irep) {
|
||||
|
||||
z_stream stream; // decompression stream
|
||||
|
||||
stream.next_in = (Bytef*)(a_src);
|
||||
stream.avail_in = (uInt)(a_srcsize);
|
||||
stream.next_out = (Bytef*)a_tgt;
|
||||
stream.avail_out = (uInt)(a_tgtsize);
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
stream.total_in = 0; /*to quiet Coverity.*/
|
||||
stream.total_out = 0; /*to quiet Coverity.*/
|
||||
|
||||
int err = inflateInit(&stream);
|
||||
if (err != Z_OK) {
|
||||
a_out << "toolx::decompress_buffer :"
|
||||
<< " error " << err << " in zlib/inflateInit." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
a_out << "toolx::decompress_buffer :"
|
||||
<< " error " << err << " in zlib/inflate." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
inflateEnd(&stream);
|
||||
|
||||
//a_out << "toolx::decompress_buffer : zlib : ok "
|
||||
// << stream.total_out << std::endl;
|
||||
|
||||
a_irep = stream.total_out;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1140
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
namespace toolx {
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1140
|
||||
inline int gunzip_get_byte(char*& a_buffer) {
|
||||
int c = *a_buffer;a_buffer++;
|
||||
return c;
|
||||
}
|
||||
|
||||
inline int gunzip_check_header(char*& a_buffer) {
|
||||
#define TOOLX_ZLIB_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
|
||||
#define TOOLX_ZLIB_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define TOOLX_ZLIB_ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define TOOLX_ZLIB_COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define TOOLX_ZLIB_RESERVED 0xE0 /* bits 5..7: reserved */
|
||||
|
||||
uInt len;
|
||||
int c;
|
||||
|
||||
/* Check the gzip magic header */
|
||||
for (len = 0; len < 2; len++) {
|
||||
c = gunzip_get_byte(a_buffer);
|
||||
/*
|
||||
if (c != gz_magic[len]) {
|
||||
if (len != 0) s->stream.avail_in++, s->stream.next_in--;
|
||||
if (c != EOF) {
|
||||
s->stream.avail_in++, s->stream.next_in--;
|
||||
s->transparent = 1;
|
||||
}
|
||||
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
int method = gunzip_get_byte(a_buffer);
|
||||
int flags = gunzip_get_byte(a_buffer);
|
||||
if (method != Z_DEFLATED || (flags & TOOLX_ZLIB_RESERVED) != 0) {
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
/* Discard time, xflags and OS code: */
|
||||
for (len = 0; len < 6; len++) (void)gunzip_get_byte(a_buffer);
|
||||
|
||||
if ((flags & TOOLX_ZLIB_EXTRA_FIELD) != 0) { /* skip the extra field */
|
||||
len = (uInt)gunzip_get_byte(a_buffer);
|
||||
len += ((uInt)gunzip_get_byte(a_buffer))<<8;
|
||||
/* len is garbage if EOF but the loop below will quit anyway */
|
||||
while (len-- != 0 && gunzip_get_byte(a_buffer) != EOF) ;
|
||||
}
|
||||
if ((flags & TOOLX_ZLIB_ORIG_NAME) != 0) { /* skip the original file name */
|
||||
while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & TOOLX_ZLIB_COMMENT) != 0) { /* skip the .gz file comment */
|
||||
while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & TOOLX_ZLIB_HEAD_CRC) != 0) { /* skip the header crc */
|
||||
for (len = 0; len < 2; len++) (void)gunzip_get_byte(a_buffer);
|
||||
}
|
||||
//s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
|
||||
return Z_OK;
|
||||
|
||||
#undef TOOLX_ZLIB_HEAD_CRC
|
||||
#undef TOOLX_ZLIB_EXTRA_FIELD
|
||||
#undef TOOLX_ZLIB_ORIG_NAME
|
||||
#undef TOOLX_ZLIB_COMMENT
|
||||
#undef TOOLX_ZLIB_RESERVED
|
||||
}
|
||||
#endif //ZLIB_VERNUM <= 0x1140
|
||||
|
||||
inline bool gunzip_buffer(std::ostream& a_out,
|
||||
unsigned int a_srcsize,const char* a_src,
|
||||
unsigned int a_tgtsize,char* a_tgt,
|
||||
unsigned int& a_irep) {
|
||||
|
||||
z_stream stream; // decompression stream
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1140
|
||||
char* pos = (char*)a_src;
|
||||
if(gunzip_check_header(pos)!=Z_OK) return false;
|
||||
stream.next_in = (Bytef*)pos;
|
||||
stream.avail_in = (uInt)(a_srcsize-(pos-a_src));
|
||||
#else
|
||||
stream.next_in = (Bytef*)a_src;
|
||||
stream.avail_in = (uInt)a_srcsize;
|
||||
#endif //ZLIB_VERNUM
|
||||
|
||||
stream.next_out = (Bytef*)a_tgt;
|
||||
stream.avail_out = (uInt)a_tgtsize;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
#if ZLIB_VERNUM <= 0x1140
|
||||
int err = inflateInit2(&stream,-MAX_WBITS);
|
||||
#else
|
||||
int err = inflateInit2(&stream,MAX_WBITS+16);
|
||||
#endif
|
||||
if (err != Z_OK) {
|
||||
a_out << "toolx::gunzip_buffer :"
|
||||
<< " error " << err << " in zlib/inflateInit2." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
a_out << "toolx::gunzip_buffer :"
|
||||
<< " error " << err << " in zlib/inflate." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
inflateEnd(&stream);
|
||||
|
||||
a_irep = stream.total_out;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user