<commit_before>#include "x11api.h"

#ifdef __LINUX__
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <X11/keysymdef.h>
#include <X11/Xutil.h>
//#include <GL/glx.h> //FIXME

#include <Tempest/Event>
#include <Tempest/TextCodec>
#include <Tempest/Window>

#include <atomic>
#include <stdexcept>
#include <cstring>
#include <thread>
#include <unordered_map>

struct HWND final {
  ::Window wnd;
  HWND()=default;
  HWND(::Window w):wnd(w) {
    }
  HWND(Tempest::SystemApi::Window* p) {
    std::memcpy(&wnd,&p,sizeof(wnd));
    }

  HWND& operator = (::Window w) { wnd = w; return *this; }

  operator ::Window() { return wnd; }

  Tempest::SystemApi::Window* ptr() {
    static_assert (sizeof(::Window)<=sizeof(void*),"cannot map X11 window handle to pointer");
    Tempest::SystemApi::Window* ret=nullptr;
    std::memcpy(&ret,&wnd,sizeof(wnd));
    return ret;
    }
  };

using namespace Tempest;

static const char*      wndClassName="Tempest.Window";
static Display*         dpy  = nullptr;
static ::Window         root = {};
static std::atomic_bool isExit{0};
static int              activeCursorChange = 0;

static std::unordered_map<SystemApi::Window*,Tempest::Window*> windows;

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static Atom& _NET_WM_STATE(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_HORZ(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_VERT(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
  return w;
  }

static Atom& _NET_WM_STATE_FULLSCREEN(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", 0);
  return w;
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static void maximizeWindow(HWND& w) {
  Atom a[2];
  a[0] = _NET_WM_STATE_MAXIMIZED_HORZ();
  a[1] = _NET_WM_STATE_MAXIMIZED_VERT();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 2);
  XSync(dpy,False);
  }

X11Api::X11Api() {
  dpy = XOpenDisplay(nullptr);

  if(dpy == nullptr)
    throw std::runtime_error("cannot connect to X server!");

  root = DefaultRootWindow(dpy);

  static const TranslateKeyPair k[] = {
    { XK_Control_L, Event::K_LControl },
    { XK_Control_R, Event::K_RControl },

    { XK_Shift_L,   Event::K_LShift   },
    { XK_Shift_R,   Event::K_RShift   },

    { XK_Alt_L,     Event::K_LAlt     },

    { XK_Left,      Event::K_Left     },
    { XK_Right,     Event::K_Right    },
    { XK_Up,        Event::K_Up       },
    { XK_Down,      Event::K_Down     },

    { XK_Escape,    Event::K_ESCAPE   },
    { XK_Tab,       Event::K_Tab      },
    { XK_BackSpace, Event::K_Back     },
    { XK_Delete,    Event::K_Delete   },
    { XK_Insert,    Event::K_Insert   },
    { XK_Home,      Event::K_Home     },
    { XK_End,       Event::K_End      },
    { XK_Pause,     Event::K_Pause    },
    { XK_Return,    Event::K_Return   },
    { XK_space,     Event::K_Space    },
    { XK_Caps_Lock, Event::K_CapsLock },

    { XK_F1,        Event::K_F1       },
    {   48,         Event::K_0        },
    {   97,         Event::K_A        },

    { 0,            Event::K_NoKey    }
    };

  setupKeyTranslate(k,24);
  }

void *X11Api::display() {
  return dpy;
  }

void X11Api::alignGeometry(SystemApi::Window *w, Tempest::Window& owner) {
  XWindowAttributes xwa={};
  if(XGetWindowAttributes(dpy, HWND(w), &xwa)){
    Tempest::SizeEvent e(xwa.width, xwa.height);
    SystemApi::dispatchResize(owner,e);
    }
  }

SystemApi::Window *X11Api::implCreateWindow(Tempest::Window *owner, uint32_t w, uint32_t h) {
  //GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  //XVisualInfo * vi = glXChooseVisual(dpy, 0, att);

  long visualMask = VisualScreenMask;
  int numberOfVisuals;
  XVisualInfo vInfoTemplate = {};
  vInfoTemplate.screen = DefaultScreen(dpy);
  XVisualInfo * vi = XGetVisualInfo(dpy, visualMask, &vInfoTemplate, &numberOfVisuals);

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  XSetWindowAttributes swa={};
  swa.colormap   = cmap;
  swa.event_mask = PointerMotionMask | ExposureMask |
                   ButtonPressMask | ButtonReleaseMask |
                   KeyPressMask | KeyReleaseMask;

  HWND win = XCreateWindow( dpy, root, 0, 0, w, h,
                            0, vi->depth, InputOutput, vi->visual,
                            CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, win, &wmDeleteMessage(), 1);
  XStoreName(dpy, win, wndClassName);

  XFreeColormap( dpy, cmap );
  XFree(vi);

  auto ret = reinterpret_cast<SystemApi::Window*>(win.ptr());
  windows[ret] = owner;
  XMapWindow(dpy, win);
  XSync(dpy,False);
  if(owner!=nullptr)
    alignGeometry(win.ptr(),*owner);
  return ret;
  }

SystemApi::Window *X11Api::implCreateWindow(Tempest::Window *owner, SystemApi::ShowMode sm) {
  Screen* s = DefaultScreenOfDisplay(dpy);
  int width = s->width;
  int height = s->height;

  SystemApi::Window* hwnd = nullptr;

  switch(sm) {
    case Hidden:
      hwnd = implCreateWindow(owner,1, 1);
      // TODO: make window invisible
      break;
    case Normal:
      hwnd = implCreateWindow(owner,800, 600);
      break;
    case Minimized:
    case Maximized:
      // TODO
      hwnd = implCreateWindow(owner,width, height);
      break;
    case FullScreen:
      hwnd = implCreateWindow(owner,width, height);
      implSetAsFullscreen(hwnd,true);
      break;
    }

  return hwnd;
  }

void X11Api::implDestroyWindow(SystemApi::Window *w) {
  windows.erase(w); //NOTE: X11 can send events to ded window
  XDestroyWindow(dpy, HWND(w));
  }

bool X11Api::implSetAsFullscreen(SystemApi::Window *w, bool fullScreen) {
  XEvent e = {};
  e.xclient.type         = ClientMessage;
  e.xclient.window       = HWND(w);
  e.xclient.message_type = _NET_WM_STATE();
  e.xclient.format       = 32;
  e.xclient.data.l[0]    = 2;    // _NET_WM_STATE_TOGGLE
  e.xclient.data.l[1]    = _NET_WM_STATE_FULLSCREEN();
  e.xclient.data.l[2]    = 0;    // no second property to toggle

  if(fullScreen)
    e.xclient.data.l[3]  = 1;
  else
    e.xclient.data.l[3]  = 0;

  XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
  return true;
  }

bool X11Api::implIsFullscreen(SystemApi::Window *w) {
  Atom actualType;
  int actualFormat;
  unsigned long i, numItems, bytesAfter;
  unsigned char *propertyValue = NULL;
  long maxLength = 1024;

  if (XGetWindowProperty(dpy, HWND(w), _NET_WM_STATE(),
                           0l, maxLength, False, XA_ATOM, &actualType,
                           &actualFormat, &numItems, &bytesAfter,
                           &propertyValue) == Success) {
        int fullscreen = 0;
        Atom *atoms = (Atom *) propertyValue;

        for (i = 0; i < numItems; ++i) {
            if (atoms[i] == _NET_WM_STATE_FULLSCREEN()) {
                fullscreen = 1;
            }
        }

        if(fullscreen) {
          return true;
        }
  }
  return false;
  }

void X11Api::implSetCursorPosition(int x, int y) {
  activeCursorChange = 1;
  XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y);
  XFlush(dpy);
  }

void X11Api::implShowCursor(bool show) {
  if(windows.size()==0)
    return;
  if(show) {
    XUndefineCursor(dpy, HWND(windows.begin()->first));
    } else {
    Cursor invisibleCursor;
    Pixmap bitmapNoData;
    XColor black;
    static char noData[] = { 0,0,0,0,0,0,0,0 };
    black.red = black.green = black.blue = 0;

    bitmapNoData = XCreateBitmapFromData(dpy, HWND(windows.begin()->first), noData, 8, 8);
    invisibleCursor = XCreatePixmapCursor(dpy, bitmapNoData, bitmapNoData,
                                      &black, &black, 0, 0);
    XDefineCursor(dpy, HWND(windows.begin()->first), invisibleCursor);
    XFreeCursor(dpy, invisibleCursor);
    XFreePixmap(dpy, bitmapNoData);
    }

  XSync(dpy, False);
  }

Rect X11Api::implWindowClientRect(SystemApi::Window *w) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, HWND(w), &xwa);

  return Rect( xwa.x, xwa.y, xwa.width, xwa.height );
  }

void X11Api::implExit() {
  isExit.store(true);
  }

bool X11Api::implIsRunning() {
  return !isExit.load();
  }

int X11Api::implExec(SystemApi::AppCallBack &cb) {
  // main message loop
  while (!isExit.load()) {
    implProcessEvents(cb);
    }
  return 0;
  }

void X11Api::implProcessEvents(SystemApi::AppCallBack &cb) {
  // main message loop
  if(XPending(dpy)>0) {
    XEvent xev={};
    XNextEvent(dpy, &xev);

    HWND hWnd = xev.xclient.window;
    auto it = windows.find(hWnd.ptr());
    if(it==windows.end() || it->second==nullptr)
      return;
    Tempest::Window& cb = *it->second; //TODO: validation
    switch( xev.type ) {
      case ClientMessage: {
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          SystemApi::exit();
          }
        break;
        }
      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) &&
            (xev.xbutton.button == Button4 || xev.xbutton.button == Button5) ){
          XEvent ev;
          XNextEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 100;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -100;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemApi::dispatchMouseWheel(cb, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          if(xev.type==ButtonPress)
            SystemApi::dispatchMouseDown(cb, e); else
            SystemApi::dispatchMouseUp(cb, e);
          }
        break;
        }
      case MotionNotify: {
        if(activeCursorChange == 1) {
          // FIXME: mouse behave crazy in OpenGothic
          activeCursorChange = 0;
          break;
        }
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        SystemApi::dispatchMouseMove(cb, e);
        break;
        }
      case KeyPress:
      case KeyRelease: {
        int keysyms_per_keycode_return = 0;
        KeySym *ksym = XGetKeyboardMapping( dpy, KeyCode(xev.xkey.keycode),
                                            1,
                                            &keysyms_per_keycode_return );

        char txt[10]={};
        XLookupString(&xev.xkey, txt, sizeof(txt)-1, ksym, nullptr );

        auto u16 = TextCodec::toUtf16(txt); // TODO: remove dynamic allocation
        auto key = SystemApi::translateKey(XLookupKeysym(&xev.xkey,0));

        uint32_t scan = xev.xkey.keycode;

        Tempest::KeyEvent e(Event::KeyType(key),uint32_t(u16.size()>0 ? u16[0] : 0),Event::M_NoModifier,(xev.type==KeyPress) ? Event::KeyDown : Event::KeyUp);
        if(xev.type==KeyPress)
          SystemApi::dispatchKeyDown(cb,e,scan); else
          SystemApi::dispatchKeyUp  (cb,e,scan);
        break;
        }
      }

    std::this_thread::yield();
    } else {
    if(cb.onTimer()==0)
      std::this_thread::yield();
    for(auto& i:windows) {
      if(i.second==nullptr)
        continue;
      // artificial move/resize event
      alignGeometry(i.first,*i.second);
      SystemApi::dispatchRender(*i.second);
      }
    }
  }

#endif
<commit_msg>x11 name collision<commit_after>#include "x11api.h"

#ifdef __LINUX__
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <X11/keysymdef.h>
#include <X11/Xutil.h>
//#include <GL/glx.h> //FIXME

#include <Tempest/Event>
#include <Tempest/TextCodec>
#include <Tempest/Window>

#include <atomic>
#include <stdexcept>
#include <cstring>
#include <thread>
#include <unordered_map>

struct HWND final {
  ::Window wnd;
  HWND()=default;
  HWND(::Window w):wnd(w) {
    }
  HWND(Tempest::SystemApi::Window* p) {
    std::memcpy(&wnd,&p,sizeof(wnd));
    }

  HWND& operator = (::Window w) { wnd = w; return *this; }

  operator ::Window() { return wnd; }

  Tempest::SystemApi::Window* ptr() {
    static_assert (sizeof(::Window)<=sizeof(void*),"cannot map X11 window handle to pointer");
    Tempest::SystemApi::Window* ret=nullptr;
    std::memcpy(&ret,&wnd,sizeof(wnd));
    return ret;
    }
  };

using namespace Tempest;

static const char*      wndClassName="Tempest.Window";
static Display*         dpy  = nullptr;
static ::Window         root = {};
static std::atomic_bool isExit{0};
static int              activeCursorChange = 0;

static std::unordered_map<SystemApi::Window*,Tempest::Window*> windows;

static Atom& wmDeleteMessage(){
  static Atom w  = XInternAtom( dpy, "WM_DELETE_WINDOW", 0);
  return w;
  }

static Atom& _NET_WM_STATE(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_HORZ(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
  return w;
  }

static Atom& _NET_WM_STATE_MAXIMIZED_VERT(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
  return w;
  }

static Atom& _NET_WM_STATE_FULLSCREEN(){
  static Atom w  = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", 0);
  return w;
  }

static Event::MouseButton toButton( XButtonEvent& msg ){
  if( msg.button==Button1 )
    return Event::ButtonLeft;

  if( msg.button==Button3 )
    return Event::ButtonRight;

  if( msg.button==Button2 )
    return Event::ButtonMid;

  return Event::ButtonNone;
  }

static void maximizeWindow(HWND& w) {
  Atom a[2];
  a[0] = _NET_WM_STATE_MAXIMIZED_HORZ();
  a[1] = _NET_WM_STATE_MAXIMIZED_VERT();

  XChangeProperty ( dpy, w, _NET_WM_STATE(),
    XA_ATOM, 32, PropModeReplace, (unsigned char*)a, 2);
  XSync(dpy,False);
  }

X11Api::X11Api() {
  dpy = XOpenDisplay(nullptr);

  if(dpy == nullptr)
    throw std::runtime_error("cannot connect to X server!");

  root = DefaultRootWindow(dpy);

  static const TranslateKeyPair k[] = {
    { XK_Control_L, Event::K_LControl },
    { XK_Control_R, Event::K_RControl },

    { XK_Shift_L,   Event::K_LShift   },
    { XK_Shift_R,   Event::K_RShift   },

    { XK_Alt_L,     Event::K_LAlt     },

    { XK_Left,      Event::K_Left     },
    { XK_Right,     Event::K_Right    },
    { XK_Up,        Event::K_Up       },
    { XK_Down,      Event::K_Down     },

    { XK_Escape,    Event::K_ESCAPE   },
    { XK_Tab,       Event::K_Tab      },
    { XK_BackSpace, Event::K_Back     },
    { XK_Delete,    Event::K_Delete   },
    { XK_Insert,    Event::K_Insert   },
    { XK_Home,      Event::K_Home     },
    { XK_End,       Event::K_End      },
    { XK_Pause,     Event::K_Pause    },
    { XK_Return,    Event::K_Return   },
    { XK_space,     Event::K_Space    },
    { XK_Caps_Lock, Event::K_CapsLock },

    { XK_F1,        Event::K_F1       },
    {   48,         Event::K_0        },
    {   97,         Event::K_A        },

    { 0,            Event::K_NoKey    }
    };

  setupKeyTranslate(k,24);
  }

void *X11Api::display() {
  return dpy;
  }

void X11Api::alignGeometry(SystemApi::Window *w, Tempest::Window& owner) {
  XWindowAttributes xwa={};
  if(XGetWindowAttributes(dpy, HWND(w), &xwa)){
    Tempest::SizeEvent e(xwa.width, xwa.height);
    SystemApi::dispatchResize(owner,e);
    }
  }

SystemApi::Window *X11Api::implCreateWindow(Tempest::Window *owner, uint32_t w, uint32_t h) {
  //GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
  //XVisualInfo * vi = glXChooseVisual(dpy, 0, att);

  long visualMask = VisualScreenMask;
  int numberOfVisuals;
  XVisualInfo vInfoTemplate = {};
  vInfoTemplate.screen = DefaultScreen(dpy);
  XVisualInfo * vi = XGetVisualInfo(dpy, visualMask, &vInfoTemplate, &numberOfVisuals);

  Colormap cmap;
  cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

  XSetWindowAttributes swa={};
  swa.colormap   = cmap;
  swa.event_mask = PointerMotionMask | ExposureMask |
                   ButtonPressMask | ButtonReleaseMask |
                   KeyPressMask | KeyReleaseMask;

  HWND win = XCreateWindow( dpy, root, 0, 0, w, h,
                            0, vi->depth, InputOutput, vi->visual,
                            CWColormap | CWEventMask, &swa );
  XSetWMProtocols(dpy, win, &wmDeleteMessage(), 1);
  XStoreName(dpy, win, wndClassName);

  XFreeColormap( dpy, cmap );
  XFree(vi);

  auto ret = reinterpret_cast<SystemApi::Window*>(win.ptr());
  windows[ret] = owner;
  XMapWindow(dpy, win);
  XSync(dpy,False);
  if(owner!=nullptr)
    alignGeometry(win.ptr(),*owner);
  return ret;
  }

SystemApi::Window *X11Api::implCreateWindow(Tempest::Window *owner, SystemApi::ShowMode sm) {
  Screen* s = DefaultScreenOfDisplay(dpy);
  int width = s->width;
  int height = s->height;

  SystemApi::Window* hwnd = nullptr;

  switch(sm) {
    case Hidden:
      hwnd = implCreateWindow(owner,1, 1);
      // TODO: make window invisible
      break;
    case Normal:
      hwnd = implCreateWindow(owner,800, 600);
      break;
    case Minimized:
    case Maximized:
      // TODO
      hwnd = implCreateWindow(owner,width, height);
      break;
    case FullScreen:
      hwnd = implCreateWindow(owner,width, height);
      implSetAsFullscreen(hwnd,true);
      break;
    }

  return hwnd;
  }

void X11Api::implDestroyWindow(SystemApi::Window *w) {
  windows.erase(w); //NOTE: X11 can send events to ded window
  XDestroyWindow(dpy, HWND(w));
  }

bool X11Api::implSetAsFullscreen(SystemApi::Window *w, bool fullScreen) {
  XEvent e = {};
  e.xclient.type         = ClientMessage;
  e.xclient.window       = HWND(w);
  e.xclient.message_type = _NET_WM_STATE();
  e.xclient.format       = 32;
  e.xclient.data.l[0]    = 2;    // _NET_WM_STATE_TOGGLE
  e.xclient.data.l[1]    = _NET_WM_STATE_FULLSCREEN();
  e.xclient.data.l[2]    = 0;    // no second property to toggle

  if(fullScreen)
    e.xclient.data.l[3]  = 1;
  else
    e.xclient.data.l[3]  = 0;

  XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
  return true;
  }

bool X11Api::implIsFullscreen(SystemApi::Window *w) {
  Atom actualType;
  int actualFormat;
  unsigned long i, numItems, bytesAfter;
  unsigned char *propertyValue = NULL;
  long maxLength = 1024;

  if (XGetWindowProperty(dpy, HWND(w), _NET_WM_STATE(),
                           0l, maxLength, False, XA_ATOM, &actualType,
                           &actualFormat, &numItems, &bytesAfter,
                           &propertyValue) == Success) {
        int fullscreen = 0;
        Atom *atoms = (Atom *) propertyValue;

        for (i = 0; i < numItems; ++i) {
            if (atoms[i] == _NET_WM_STATE_FULLSCREEN()) {
                fullscreen = 1;
            }
        }

        if(fullscreen) {
          return true;
        }
  }
  return false;
  }

void X11Api::implSetCursorPosition(int x, int y) {
  activeCursorChange = 1;
  XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y);
  XFlush(dpy);
  }

void X11Api::implShowCursor(bool show) {
  if(windows.size()==0)
    return;
  if(show) {
    XUndefineCursor(dpy, HWND(windows.begin()->first));
    } else {
    Cursor invisibleCursor;
    ::Pixmap bitmapNoData;
    XColor black;
    static char noData[] = { 0,0,0,0,0,0,0,0 };
    black.red = black.green = black.blue = 0;

    bitmapNoData = XCreateBitmapFromData(dpy, HWND(windows.begin()->first), noData, 8, 8);
    invisibleCursor = XCreatePixmapCursor(dpy, bitmapNoData, bitmapNoData,
                                      &black, &black, 0, 0);
    XDefineCursor(dpy, HWND(windows.begin()->first), invisibleCursor);
    XFreeCursor(dpy, invisibleCursor);
    XFreePixmap(dpy, bitmapNoData);
    }

  XSync(dpy, False);
  }

Rect X11Api::implWindowClientRect(SystemApi::Window *w) {
  XWindowAttributes xwa;
  XGetWindowAttributes(dpy, HWND(w), &xwa);

  return Rect( xwa.x, xwa.y, xwa.width, xwa.height );
  }

void X11Api::implExit() {
  isExit.store(true);
  }

bool X11Api::implIsRunning() {
  return !isExit.load();
  }

int X11Api::implExec(SystemApi::AppCallBack &cb) {
  // main message loop
  while (!isExit.load()) {
    implProcessEvents(cb);
    }
  return 0;
  }

void X11Api::implProcessEvents(SystemApi::AppCallBack &cb) {
  // main message loop
  if(XPending(dpy)>0) {
    XEvent xev={};
    XNextEvent(dpy, &xev);

    HWND hWnd = xev.xclient.window;
    auto it = windows.find(hWnd.ptr());
    if(it==windows.end() || it->second==nullptr)
      return;
    Tempest::Window& cb = *it->second; //TODO: validation
    switch( xev.type ) {
      case ClientMessage: {
        if( xev.xclient.data.l[0] == long(wmDeleteMessage()) ){
          SystemApi::exit();
          }
        break;
        }
      case ButtonPress:
      case ButtonRelease: {
        bool isWheel = false;
        if( xev.type==ButtonPress && XPending(dpy) &&
            (xev.xbutton.button == Button4 || xev.xbutton.button == Button5) ){
          XEvent ev;
          XNextEvent(dpy, &ev);
          isWheel = (ev.type==ButtonRelease);
          }

        if( isWheel ){
          int ticks = 0;
          if( xev.xbutton.button == Button4 ) {
            ticks = 100;
            }
          else if ( xev.xbutton.button == Button5 ) {
            ticks = -100;
            }
          Tempest::MouseEvent e( xev.xbutton.x,
                                 xev.xbutton.y,
                                 Tempest::Event::ButtonNone,
                                 ticks,
                                 0,
                                 Event::MouseWheel );
          SystemApi::dispatchMouseWheel(cb, e);
          } else {
          MouseEvent e( xev.xbutton.x,
                        xev.xbutton.y,
                        toButton( xev.xbutton ),
                        0,
                        0,
                        xev.type==ButtonPress ? Event::MouseDown : Event::MouseUp );
          if(xev.type==ButtonPress)
            SystemApi::dispatchMouseDown(cb, e); else
            SystemApi::dispatchMouseUp(cb, e);
          }
        break;
        }
      case MotionNotify: {
        if(activeCursorChange == 1) {
          // FIXME: mouse behave crazy in OpenGothic
          activeCursorChange = 0;
          break;
        }
        MouseEvent e( xev.xmotion.x,
                      xev.xmotion.y,
                      Event::ButtonNone,
                      0,
                      0,
                      Event::MouseMove  );
        SystemApi::dispatchMouseMove(cb, e);
        break;
        }
      case KeyPress:
      case KeyRelease: {
        int keysyms_per_keycode_return = 0;
        KeySym *ksym = XGetKeyboardMapping( dpy, KeyCode(xev.xkey.keycode),
                                            1,
                                            &keysyms_per_keycode_return );

        char txt[10]={};
        XLookupString(&xev.xkey, txt, sizeof(txt)-1, ksym, nullptr );

        auto u16 = TextCodec::toUtf16(txt); // TODO: remove dynamic allocation
        auto key = SystemApi::translateKey(XLookupKeysym(&xev.xkey,0));

        uint32_t scan = xev.xkey.keycode;

        Tempest::KeyEvent e(Event::KeyType(key),uint32_t(u16.size()>0 ? u16[0] : 0),Event::M_NoModifier,(xev.type==KeyPress) ? Event::KeyDown : Event::KeyUp);
        if(xev.type==KeyPress)
          SystemApi::dispatchKeyDown(cb,e,scan); else
          SystemApi::dispatchKeyUp  (cb,e,scan);
        break;
        }
      }

    std::this_thread::yield();
    } else {
    if(cb.onTimer()==0)
      std::this_thread::yield();
    for(auto& i:windows) {
      if(i.second==nullptr)
        continue;
      // artificial move/resize event
      alignGeometry(i.first,*i.second);
      SystemApi::dispatchRender(*i.second);
      }
    }
  }

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestParallelRandomStatistics.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include <mpi.h>
#include <time.h>

#include "vtkDescriptiveStatistics.h"
#include "vtkPDescriptiveStatistics.h"
#include "vtkCorrelativeStatistics.h"
#include "vtkPCorrelativeStatistics.h"

#include "vtkDoubleArray.h"
#include "vtkMath.h"
#include "vtkMPIController.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"

// For debugging purposes, serial engines can be run on each slice of the distributed data set
#define DEBUG_WITH_SERIAL_STATS 0

int nVals = 1000000;

// This will be called by all processes
void RandomSampleStatistics( vtkMultiProcessController* controller, void* vtkNotUsed(arg) )
{
  // Get local rank
  int myRank = controller->GetLocalProcessId();

  // Seed random number generator
  vtkMath::RandomSeed( static_cast<int>( time( NULL ) ) * ( myRank + 1 ) );

  // Generate an input table that contains samples of mutually independent random variables over [0, 1]
  int nUniform = 2;
  int nNormal  = 2;
  int nVariables = nUniform + nNormal;

  vtkTable* inputData = vtkTable::New();
  vtkDoubleArray* doubleArray[4];
  vtkStdString columnNames[] = { "Standard Uniform 0",
                                 "Standard Uniform 1",
                                 "Standard Normal 0",
                                 "Standard Normal 1" };

  // Standard uniform samples
  for ( int c = 0; c < nUniform; ++ c )
    {
    doubleArray[c] = vtkDoubleArray::New();
    doubleArray[c]->SetNumberOfComponents( 1 );
    doubleArray[c]->SetName( columnNames[c] );

    double x;
    for ( int r = 0; r < nVals; ++ r )
      {
      x = vtkMath::Random();
      doubleArray[c]->InsertNextValue( x );
      }

    inputData->AddColumn( doubleArray[c] );
    doubleArray[c]->Delete();
    }

  // Standard normal samples
  for ( int c = nUniform; c < nVariables; ++ c )
    {
    doubleArray[c] = vtkDoubleArray::New();
    doubleArray[c]->SetNumberOfComponents( 1 );
    doubleArray[c]->SetName( columnNames[c] );

    double x;
    for ( int r = 0; r < nVals; ++ r )
      {
      x = vtkMath::Gaussian();
      doubleArray[c]->InsertNextValue( x );
      }

    inputData->AddColumn( doubleArray[c] );
    doubleArray[c]->Delete();
    }

#if DEBUG_WITH_SERIAL_STATS
  // Instantiate a (serial) descriptive statistics engine and set its ports
  vtkDescriptiveStatistics* ds = vtkDescriptiveStatistics::New();
  ds->SetInput( 0, inputData );

  // Select all columns
  for ( int c = 0; c < nVariables; ++ c )
    {
    ds->AddColumn( columnNames[c] );
    }

  // Test (serially) with Learn and Derive options only
  ds->SetLearn( true );
  ds->SetDerive( true );
  ds->SetAssess( true );
  ds->Update();

  cout << "\n## Proc "
       << myRank
       << " calculated the following statistics ( "
       << ds->GetSampleSize()
       << " entries per column ):\n";
  for ( vtkIdType r = 0; r < ds->GetOutput( 1 )->GetNumberOfRows(); ++ r )
    {
    cout << "   ";
    for ( int i = 0; i < ds->GetOutput( 1 )->GetNumberOfColumns(); ++ i )
      {
      cout << ds->GetOutput( 1 )->GetColumnName( i )
           << "="
           << ds->GetOutput( 1 )->GetValue( r, i ).ToString()
           << "  ";
      }
    cout << "\n";
    }

  // Clean up
  ds->Delete();
#endif //DEBUG_WITH_SERIAL_STATS

  // Synchronize and start clock
  controller->Barrier();
  time_t t0;
  time ( &t0 );

  // Instantiate a parallel descriptive statistics engine and set its ports
  vtkPDescriptiveStatistics* pds = vtkPDescriptiveStatistics::New();
  pds->SetInput( 0, inputData );
  vtkTable* outputData = pds->GetOutput( 0 );
  vtkTable* outputMeta = pds->GetOutput( 1 );

  // Select all columns
  for ( int c = 0; c < nVariables; ++ c )
    {
    pds->AddColumn( columnNames[c] );
    }

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pds->SetLearn( true );
  pds->SetDerive( true );
  pds->SetAssess( true );
  pds->SignedDeviationsOff(); // Use unsigned deviations
  pds->Update();

  // Synchronize and stop clock
  controller->Barrier();
  time_t t1;
  time ( &t1 );

  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Completed parallel calculation of descriptive statistics (with assessment):\n"
         << "   Total sample size: "
         << pds->GetSampleSize()
         << " \n"
         << "   Wall time: "
         << difftime( t1, t0 )
         << " sec.\n";

   for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
      {
      cout << "   ";
      for ( int c = 0; c < outputMeta->GetNumberOfColumns(); ++ c )
        {
        cout << outputMeta->GetColumnName( c )
             << "="
             << outputMeta->GetValue( r, c ).ToString()
             << "  ";
        }
      cout << "\n";
      }
    }

  // Verify that the DISTRIBUTED standard normal samples indeed statisfy the 68-95-99.7 rule
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Verifying whether the distributed standard normal samples satisfy the 68-95-99.7 rule:\n";
    }

  vtkVariantArray* relDev[2];
  relDev[0] = vtkVariantArray::SafeDownCast(
    outputData->GetColumnByName( "Relative Deviation(Standard Normal 0)" ) );
  relDev[1] = vtkVariantArray::SafeDownCast(
    outputData->GetColumnByName( "Relative Deviation(Standard Normal 1)" ) );

  if ( !relDev[0] || ! relDev[1] )
    {
    cout << "*** Error: "
         << "Empty output column(s) on process "
         << controller->GetLocalProcessId()
         << ".\n";
    }

  for ( int c = 0; c < nNormal; ++ c )
    {
    int outsideStdv_l[] = { 0, 0, 0 };
    double dev;
    int n = outputData->GetNumberOfRows();
    for ( vtkIdType r = 0; r < n; ++ r )
      {
      dev = relDev[c]->GetValue( r ).ToDouble();
      if ( dev >= 1. )
        {
        ++ outsideStdv_l[0];
        if ( dev >= 2. )
          {
          ++ outsideStdv_l[1];
          if ( dev >= 3. )
            {
            ++ outsideStdv_l[2];
            }
          }
        }
      }

    // Sum all local counters
    int outsideStdv_g[3];
    controller->AllReduce( outsideStdv_l,
                           outsideStdv_g,
                           3,
                           vtkCommunicator::SUM_OP );

    // Print out percentages of sample points within 1, 2, and 3 standard deviations of the mean.
    if ( ! controller->GetLocalProcessId() )
      {
      cout << "   "
           << outputData->GetColumnName( nUniform + c )
           << ":\n";
      for ( int i = 0; i < 3; ++ i )
        {
        cout << "      "
             << ( 1. - outsideStdv_g[i] / static_cast<double>( pds->GetSampleSize() ) ) * 100.
             << "\% within "
             << i + 1
             << " standard deviation(s) from the mean.\n";
        }
      }
    }

  // Clean up
  pds->Delete();

  // Synchronize and start clock
  controller->Barrier();
  time_t t2;
  time ( &t2 );

  // Instantiate a parallel correlative statistics engine and set its ports
  vtkPCorrelativeStatistics* pcs = vtkPCorrelativeStatistics::New();
  pcs->SetInput( 0, inputData );
  outputData = pcs->GetOutput( 0 );
  outputMeta = pcs->GetOutput( 1 );

  // Select column pairs (uniform vs. uniform, normal vs. normal)
  pcs->AddColumnPair( columnNames[0], columnNames[1] );
  pcs->AddColumnPair( columnNames[2], columnNames[3] );

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pcs->SetLearn( true );
  pcs->SetDerive( true );
  pcs->SetAssess( true );
  pcs->Update();

    // Synchronize and stop clock
  controller->Barrier();
  time_t t3;
  time ( &t3 );

  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Completed parallel calculation of correlative statistics (with assessment):\n"
         << "   Total sample size: "
         << pcs->GetSampleSize()
         << " \n"
         << "   Wall time: "
         << difftime( t3, t2 )
         << " sec.\n";

    for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
      {
      cout << "   ";
      for ( int c = 0; c < outputMeta->GetNumberOfColumns(); ++ c )
        {
        cout << outputMeta->GetColumnName( c )
             << "="
             << outputMeta->GetValue( r, c ).ToString()
             << "  ";
        }
      cout << "\n";
      }
    }

  // Clean up
  pcs->Delete();
  inputData->Delete();
}

//----------------------------------------------------------------------------
int main( int argc, char** argv )
{
  int testValue = 0;

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
  vtkMPIController* controller = vtkMPIController::New();
  controller->Initialize( &argc, &argv );

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if ( controller->IsA( "vtkThreadedController" ) )
    {
    // Set the number of processes to 2 for this example.
    controller->SetNumberOfProcesses( 2 );
    }

  // Check how many processes have been made available
  int numProcs = controller->GetNumberOfProcesses();
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "# Running test with "
         << numProcs
         << " processes...\n";
    }

  // Execute the function named "process" on both processes
  controller->SetSingleMethod( RandomSampleStatistics, 0 );
  controller->SingleMethodExecute();

  // Clean up and exit
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n# Test completed.\n\n";
    }

  controller->Finalize();
  controller->Delete();

  return testValue;
}
<commit_msg>ENH: time the parallel correlative engine, too ENH: report only human-understandable parts of the statistical model<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestParallelRandomStatistics.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*
 * Copyright 2008 Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the
 * U.S. Government. Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that this Notice and any
 * statement of authorship are reproduced on all copies.
 */
// .SECTION Thanks
// Thanks to Philippe Pebay and David Thompson from Sandia National Laboratories
// for implementing this test.

#include <mpi.h>
#include <time.h>

#include "vtkDescriptiveStatistics.h"
#include "vtkPDescriptiveStatistics.h"
#include "vtkCorrelativeStatistics.h"
#include "vtkPCorrelativeStatistics.h"

#include "vtkDoubleArray.h"
#include "vtkMath.h"
#include "vtkMPIController.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"

// For debugging purposes, serial engines can be run on each slice of the distributed data set
#define DEBUG_WITH_SERIAL_STATS 0

int nVals = 1000000;

// This will be called by all processes
void RandomSampleStatistics( vtkMultiProcessController* controller, void* vtkNotUsed(arg) )
{
  // Get local rank
  int myRank = controller->GetLocalProcessId();

  // Seed random number generator
  vtkMath::RandomSeed( static_cast<int>( time( NULL ) ) * ( myRank + 1 ) );

  // Generate an input table that contains samples of mutually independent random variables over [0, 1]
  int nUniform = 2;
  int nNormal  = 2;
  int nVariables = nUniform + nNormal;

  vtkTable* inputData = vtkTable::New();
  vtkDoubleArray* doubleArray[4];
  vtkStdString columnNames[] = { "Standard Uniform 0",
                                 "Standard Uniform 1",
                                 "Standard Normal 0",
                                 "Standard Normal 1" };

  // Standard uniform samples
  for ( int c = 0; c < nUniform; ++ c )
    {
    doubleArray[c] = vtkDoubleArray::New();
    doubleArray[c]->SetNumberOfComponents( 1 );
    doubleArray[c]->SetName( columnNames[c] );

    double x;
    for ( int r = 0; r < nVals; ++ r )
      {
      x = vtkMath::Random();
      doubleArray[c]->InsertNextValue( x );
      }

    inputData->AddColumn( doubleArray[c] );
    doubleArray[c]->Delete();
    }

  // Standard normal samples
  for ( int c = nUniform; c < nVariables; ++ c )
    {
    doubleArray[c] = vtkDoubleArray::New();
    doubleArray[c]->SetNumberOfComponents( 1 );
    doubleArray[c]->SetName( columnNames[c] );

    double x;
    for ( int r = 0; r < nVals; ++ r )
      {
      x = vtkMath::Gaussian();
      doubleArray[c]->InsertNextValue( x );
      }

    inputData->AddColumn( doubleArray[c] );
    doubleArray[c]->Delete();
    }

#if DEBUG_WITH_SERIAL_STATS
  // Instantiate a (serial) descriptive statistics engine and set its ports
  vtkDescriptiveStatistics* ds = vtkDescriptiveStatistics::New();
  ds->SetInput( 0, inputData );

  // Select all columns
  for ( int c = 0; c < nVariables; ++ c )
    {
    ds->AddColumn( columnNames[c] );
    }

  // Test (serially) with Learn and Derive options only
  ds->SetLearn( true );
  ds->SetDerive( true );
  ds->SetAssess( true );
  ds->Update();

  cout << "\n## Proc "
       << myRank
       << " calculated the following statistics ( "
       << ds->GetSampleSize()
       << " entries per column ):\n";
  for ( vtkIdType r = 0; r < ds->GetOutput( 1 )->GetNumberOfRows(); ++ r )
    {
    cout << "   ";
    for ( int i = 0; i < ds->GetOutput( 1 )->GetNumberOfColumns(); ++ i )
      {
      cout << ds->GetOutput( 1 )->GetColumnName( i )
           << "="
           << ds->GetOutput( 1 )->GetValue( r, i ).ToString()
           << "  ";
      }
    cout << "\n";
    }

  // Clean up
  ds->Delete();
#endif //DEBUG_WITH_SERIAL_STATS

  // Synchronize and start clock
  controller->Barrier();
  time_t t0;
  time ( &t0 );

  // Instantiate a parallel descriptive statistics engine and set its ports
  vtkPDescriptiveStatistics* pds = vtkPDescriptiveStatistics::New();
  pds->SetInput( 0, inputData );
  vtkTable* outputData = pds->GetOutput( 0 );
  vtkTable* outputMeta = pds->GetOutput( 1 );

  // Select all columns
  for ( int c = 0; c < nVariables; ++ c )
    {
    pds->AddColumn( columnNames[c] );
    }

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pds->SetLearn( true );
  pds->SetDerive( true );
  pds->SetAssess( true );
  pds->SignedDeviationsOff(); // Use unsigned deviations
  pds->Update();

  // Synchronize and stop clock
  controller->Barrier();
  time_t t1;
  time ( &t1 );

  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Completed parallel calculation of descriptive statistics (with assessment):\n"
         << "   Total sample size: "
         << pds->GetSampleSize()
         << " \n"
         << "   Wall time: "
         << difftime( t1, t0 )
         << " sec.\n";

   for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
      {
      cout << "   ";
      for ( int c = 0; c < outputMeta->GetNumberOfColumns(); ++ c )
        {
        vtkStdString colName = outputMeta->GetColumnName( c );

        // Do not report M aggregates
        if ( colName[0] == 'M' && colName[1] != 'e' )
          {
          continue;
          }

        cout << colName
             << "="
             << outputMeta->GetValue( r, c ).ToString()
             << "  ";
        }
      cout << "\n";
      }
    }

  // Verify that the DISTRIBUTED standard normal samples indeed statisfy the 68-95-99.7 rule
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Verifying whether the distributed standard normal samples satisfy the 68-95-99.7 rule:\n";
    }

  vtkVariantArray* relDev[2];
  relDev[0] = vtkVariantArray::SafeDownCast(
    outputData->GetColumnByName( "Relative Deviation(Standard Normal 0)" ) );
  relDev[1] = vtkVariantArray::SafeDownCast(
    outputData->GetColumnByName( "Relative Deviation(Standard Normal 1)" ) );

  if ( !relDev[0] || ! relDev[1] )
    {
    cout << "*** Error: "
         << "Empty output column(s) on process "
         << controller->GetLocalProcessId()
         << ".\n";
    }

  for ( int c = 0; c < nNormal; ++ c )
    {
    int outsideStdv_l[] = { 0, 0, 0 };
    double dev;
    int n = outputData->GetNumberOfRows();
    for ( vtkIdType r = 0; r < n; ++ r )
      {
      dev = relDev[c]->GetValue( r ).ToDouble();
      if ( dev >= 1. )
        {
        ++ outsideStdv_l[0];
        if ( dev >= 2. )
          {
          ++ outsideStdv_l[1];
          if ( dev >= 3. )
            {
            ++ outsideStdv_l[2];
            }
          }
        }
      }

    // Sum all local counters
    int outsideStdv_g[3];
    controller->AllReduce( outsideStdv_l,
                           outsideStdv_g,
                           3,
                           vtkCommunicator::SUM_OP );

    // Print out percentages of sample points within 1, 2, and 3 standard deviations of the mean.
    if ( ! controller->GetLocalProcessId() )
      {
      cout << "   "
           << outputData->GetColumnName( nUniform + c )
           << ":\n";
      for ( int i = 0; i < 3; ++ i )
        {
        cout << "      "
             << ( 1. - outsideStdv_g[i] / static_cast<double>( pds->GetSampleSize() ) ) * 100.
             << "\% within "
             << i + 1
             << " standard deviation(s) from the mean.\n";
        }
      }
    }

  // Clean up
  pds->Delete();

  // Synchronize and start clock
  controller->Barrier();
  time_t t2;
  time ( &t2 );

  // Instantiate a parallel correlative statistics engine and set its ports
  vtkPCorrelativeStatistics* pcs = vtkPCorrelativeStatistics::New();
  pcs->SetInput( 0, inputData );
  outputData = pcs->GetOutput( 0 );
  outputMeta = pcs->GetOutput( 1 );

  // Select column pairs (uniform vs. uniform, normal vs. normal)
  pcs->AddColumnPair( columnNames[0], columnNames[1] );
  pcs->AddColumnPair( columnNames[2], columnNames[3] );

  // Test (in parallel) with Learn, Derive, and Assess options turned on
  pcs->SetLearn( true );
  pcs->SetDerive( true );
  pcs->SetAssess( true );
  pcs->Update();

    // Synchronize and stop clock
  controller->Barrier();
  time_t t3;
  time ( &t3 );

  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n## Completed parallel calculation of correlative statistics (with assessment):\n"
         << "   Total sample size: "
         << pcs->GetSampleSize()
         << " \n"
         << "   Wall time: "
         << difftime( t3, t2 )
         << " sec.\n";

    for ( vtkIdType r = 0; r < outputMeta->GetNumberOfRows(); ++ r )
      {
      cout << "   ";
      for ( int c = 0; c < outputMeta->GetNumberOfColumns(); ++ c )
        {
        vtkStdString colName = outputMeta->GetColumnName( c );

        // Do not report M aggregates
        if ( colName[0] == 'M' && colName[1] != 'e' )
          {
          continue;
          }

        cout << colName
             << "="
             << outputMeta->GetValue( r, c ).ToString()
             << "  ";
        }
      cout << "\n";
      }
    }

  // Clean up
  pcs->Delete();
  inputData->Delete();
}

//----------------------------------------------------------------------------
int main( int argc, char** argv )
{
  int testValue = 0;

  // Note that this will create a vtkMPIController if MPI
  // is configured, vtkThreadedController otherwise.
  vtkMPIController* controller = vtkMPIController::New();
  controller->Initialize( &argc, &argv );

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if ( controller->IsA( "vtkThreadedController" ) )
    {
    // Set the number of processes to 2 for this example.
    controller->SetNumberOfProcesses( 2 );
    }

  // Check how many processes have been made available
  int numProcs = controller->GetNumberOfProcesses();
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "# Running test with "
         << numProcs
         << " processes...\n";
    }

  // Execute the function named "process" on both processes
  controller->SetSingleMethod( RandomSampleStatistics, 0 );
  controller->SingleMethodExecute();

  // Clean up and exit
  if ( ! controller->GetLocalProcessId() )
    {
    cout << "\n# Test completed.\n\n";
    }

  controller->Finalize();
  controller->Delete();

  return testValue;
}
<|endoftext|>


<commit_before>%%
%% Qt5xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 5
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include <Qt>

#ifndef __XHARBOUR__
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
#include <QtSerialBusVersion>
#endif
#endif

#include "qt5xhb_common.h"
#include "qt5xhb_macros.h"
#include "qt5xhb_utils.h"

#ifdef __XHARBOUR__
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
#include <QtSerialBusVersion>
#endif
#endif

HB_FUNC( QTVIRTUALKEYBOARD_VERSION_STR )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
  hb_retc( (const char *) QTVIRTUALKEYBOARD_VERSION_STR );
#else
  hb_retc( (const char *) "" );
#endif
}

HB_FUNC( QTVIRTUALKEYBOARD_VERSION )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
  hb_retni( QTVIRTUALKEYBOARD_VERSION );
#else
  hb_retni( 0 );
#endif
}
<commit_msg>codegen/QtVirtualKeyboard/QtVirtualKeyboardVersion.cpp: fixed<commit_after>%%
%% Qt5xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 5
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include <Qt>

#ifndef __XHARBOUR__
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
#include <QtVirtualKeyboardVersion>
#endif
#endif

#include "qt5xhb_common.h"
#include "qt5xhb_macros.h"
#include "qt5xhb_utils.h"

#ifdef __XHARBOUR__
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
#include <QtVirtualKeyboardVersion>
#endif
#endif

HB_FUNC( QTVIRTUALKEYBOARD_VERSION_STR )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
  hb_retc( (const char *) QTVIRTUALKEYBOARD_VERSION_STR );
#else
  hb_retc( (const char *) "" );
#endif
}

HB_FUNC( QTVIRTUALKEYBOARD_VERSION )
{
#if (QT_VERSION >= QT_VERSION_CHECK(5,8,0))
  hb_retni( QTVIRTUALKEYBOARD_VERSION );
#else
  hb_retni( 0 );
#endif
}
<|endoftext|>


<commit_before>// Filename: bulletRigidBodyNode.cxx
// Created by:  enn0x (19Nov10)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "bulletRigidBodyNode.h"
#include "bulletShape.h"

TypeHandle BulletRigidBodyNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::Constructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
BulletRigidBodyNode::
BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {

  // Synchronised transform
  _sync = TransformState::make_identity();
  _sync_disable = false;

  // Mass properties
  btScalar mass(0.0);
  btVector3 inertia(0, 0, 0);

  // Motion state and construction info
  MotionState *motion = new MotionState(_sync);
  btRigidBody::btRigidBodyConstructionInfo ci(mass, motion, _shape, inertia);

  // Additional damping
  if (bullet_additional_damping) {
    ci.m_additionalDamping = true;
    ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
    ci.m_additionalLinearDampingThresholdSqr = bullet_additional_damping_linear_threshold;
    ci.m_additionalAngularDampingFactor = bullet_additional_damping_angular_factor;
    ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
  }

  // Rigid body
  _rigid = new btRigidBody(ci);
  _rigid->setUserPointer(this);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::output
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
output(ostream &out) const {

  BulletBodyNode::output(out);

  out << " mass=" << get_mass();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_object
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
btCollisionObject *BulletRigidBodyNode::
get_object() const {

  return _rigid;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::shape_changed
//       Access: Published
//  Description: Hook which will be called whenever the total shape
//               of a body changed. Used for example to update
//               the mass properties (inertia) of a rigid body.
//               The default implementation does nothing.
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
shape_changed() {

  set_mass(get_mass());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_mass
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_mass(float mass) {

  btScalar bt_mass = mass;
  btVector3 bt_inertia(0.0, 0.0, 0.0);

  if (bt_mass > 0.0) {
    _rigid->getCollisionShape()->calculateLocalInertia(bt_mass, bt_inertia);
  }

  _rigid->setMassProps(bt_mass, bt_inertia);
  _rigid->updateInertiaTensor();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_mass
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_mass() const {

  btScalar inv_mass = _rigid->getInvMass();
  btScalar mass = inv_mass == btScalar(0.0) ? btScalar(0.0) : btScalar(1.0) / inv_mass;

  return mass;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_inertia
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_inertia(const LVecBase3f &inertia) {

  btVector3 inv_inertia(
    inertia.get_x() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_x()),
    inertia.get_y() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_y()),
    inertia.get_z() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_z())
    );

  _rigid->setInvInertiaDiagLocal(inv_inertia);
  _rigid->updateInertiaTensor();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_inertia
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_inertia() const {

  btVector3 inv_inertia = _rigid->getInvInertiaDiagLocal();
  LVector3f inertia(
    inv_inertia.x() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.x(),
    inv_inertia.y() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.y(),
    inv_inertia.z() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.z()
    );

  return inertia;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_force
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_force(const LVector3f &force, const LPoint3f &pos) {

  nassertv_always(!force.is_nan());
  nassertv_always(!pos.is_nan());

  _rigid->applyForce(LVecBase3f_to_btVector3(force),
                     LVecBase3f_to_btVector3(pos));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_central_force
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_central_force(const LVector3f &force) {

  nassertv_always(!force.is_nan());

  _rigid->applyCentralForce(LVecBase3f_to_btVector3(force));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_torque
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_torque(const LVector3f &torque) {

  nassertv_always(!torque.is_nan());

  _rigid->applyTorque(LVecBase3f_to_btVector3(torque));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_torque_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_torque_impulse(const LVector3f &torque) {

  nassertv_always(!torque.is_nan());

  _rigid->applyTorqueImpulse(LVecBase3f_to_btVector3(torque));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_impulse(const LVector3f &impulse, const LPoint3f &pos) {

  nassertv_always(!impulse.is_nan());
  nassertv_always(!pos.is_nan());

  _rigid->applyImpulse(LVecBase3f_to_btVector3(impulse),
                       LVecBase3f_to_btVector3(pos));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_central_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_central_impulse(const LVector3f &impulse) {

  nassertv_always(!impulse.is_nan());

  _rigid->applyCentralImpulse(LVecBase3f_to_btVector3(impulse));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::transform_changed
//       Access: Protected
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
transform_changed() {

  if (_sync_disable) return;

  NodePath np = NodePath::any_path((PandaNode *)this);
  CPT(TransformState) ts = np.get_net_transform();

  LMatrix4f m_sync = _sync->get_mat();
  LMatrix4f m_ts = ts->get_mat();

  if (!m_sync.almost_equal(m_ts)) {
    _sync = ts;

    btTransform trans = TransformState_to_btTrans(ts);
    _rigid->setCenterOfMassTransform(trans);

    if (ts->has_scale()) {
      LVecBase3f scale = ts->get_scale();
      if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
        for (int i=0; i<get_num_shapes(); i++) {
          PT(BulletShape) shape = _shapes[i];
          shape->set_local_scale(scale);
        }

        shape_changed();
      }
    }

    // Activate the body if it has been sleeping
    if (!_rigid->isActive()) {
      _rigid->activate(true);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::sync_p2b
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_p2b() {

  transform_changed();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::sync_b2p
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_b2p() {

  NodePath np = NodePath::any_path((PandaNode *)this);
  LVecBase3f scale = np.get_net_transform()->get_scale();

  btTransform trans = _rigid->getWorldTransform();
  CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);

  LMatrix4f m_sync = _sync->get_mat();
  LMatrix4f m_ts = ts->get_mat();

  if (!m_sync.almost_equal(m_ts)) {
    _sync = ts;
    _sync_disable = true;
    np.set_transform(NodePath(), ts);
    _sync_disable = false;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_linear_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_linear_velocity() const {

  return btVector3_to_LVector3f(_rigid->getLinearVelocity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_angular_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_angular_velocity() const {

  return btVector3_to_LVector3f(_rigid->getAngularVelocity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_velocity(const LVector3f &velocity) {

  nassertv_always(!velocity.is_nan());

  _rigid->setLinearVelocity(LVecBase3f_to_btVector3(velocity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_velocity(const LVector3f &velocity) {

  nassertv_always(!velocity.is_nan());

  _rigid->setAngularVelocity(LVecBase3f_to_btVector3(velocity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::clear_forces
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
clear_forces() {

  _rigid->clearForces();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_linear_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_linear_sleep_threshold() const {

  return _rigid->getLinearSleepingThreshold();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_angular_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_angular_sleep_threshold() const {

  return _rigid->getAngularSleepingThreshold();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_sleep_threshold(float threshold) {

  _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_sleep_threshold(float threshold) {

  _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_gravity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_gravity(const LVector3f &gravity) {

  nassertv_always(!gravity.is_nan());

  _rigid->setGravity(LVecBase3f_to_btVector3(gravity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_gravity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_gravity() const {

  return btVector3_to_LVector3f(_rigid->getGravity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_factor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_factor(const LVector3f &factor) {

  _rigid->setLinearFactor(LVecBase3f_to_btVector3(factor));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_factor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_factor(const LVector3f &factor) {

  _rigid->setAngularFactor(LVecBase3f_to_btVector3(factor));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::MotionState::getWorldTransform
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::MotionState::
getWorldTransform(btTransform &trans) const {

  trans = TransformState_to_btTrans(_sync);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::MotionState::setWorldTransform
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::MotionState::
setWorldTransform(const btTransform &trans) {

}

<commit_msg>Added some documentation.<commit_after>// Filename: bulletRigidBodyNode.cxx
// Created by:  enn0x (19Nov10)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "bulletRigidBodyNode.h"
#include "bulletShape.h"

TypeHandle BulletRigidBodyNode::_type_handle;

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::Constructor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
BulletRigidBodyNode::
BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {

  // Synchronised transform
  _sync = TransformState::make_identity();
  _sync_disable = false;

  // Mass properties
  btScalar mass(0.0);
  btVector3 inertia(0, 0, 0);

  // Motion state and construction info
  MotionState *motion = new MotionState(_sync);
  btRigidBody::btRigidBodyConstructionInfo ci(mass, motion, _shape, inertia);

  // Additional damping
  if (bullet_additional_damping) {
    ci.m_additionalDamping = true;
    ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
    ci.m_additionalLinearDampingThresholdSqr = bullet_additional_damping_linear_threshold;
    ci.m_additionalAngularDampingFactor = bullet_additional_damping_angular_factor;
    ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
  }

  // Rigid body
  _rigid = new btRigidBody(ci);
  _rigid->setUserPointer(this);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::output
//       Access: Public, Virtual
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
output(ostream &out) const {

  BulletBodyNode::output(out);

  out << " mass=" << get_mass();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_object
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
btCollisionObject *BulletRigidBodyNode::
get_object() const {

  return _rigid;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::shape_changed
//       Access: Published
//  Description: Hook which should be called whenever the total
//               shape of a body changed. Used for example to update
//               the mass properties (inertia) of a rigid body.
//               The default implementation does nothing.
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
shape_changed() {

  set_mass(get_mass());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_mass
//       Access: Published
//  Description: Sets the mass of a rigid body. This also modifies
//               the inertia, which is automatically computed from
//               the shape of the body. Setting a value of zero
//               for mass will make the body static. A value of
//               zero can be considered an infinite mass.
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_mass(float mass) {

  btScalar bt_mass = mass;
  btVector3 bt_inertia(0.0, 0.0, 0.0);

  if (bt_mass > 0.0) {
    _rigid->getCollisionShape()->calculateLocalInertia(bt_mass, bt_inertia);
  }

  _rigid->setMassProps(bt_mass, bt_inertia);
  _rigid->updateInertiaTensor();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_mass
//       Access: Published
//  Description: Returns the total mass of a rigid body.
//               A value of zero means that the body is staic, i.e.
//               has an infinite mass.
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_mass() const {

  btScalar inv_mass = _rigid->getInvMass();
  btScalar mass = inv_mass == btScalar(0.0) ? btScalar(0.0) : btScalar(1.0) / inv_mass;

  return mass;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_inertia
//       Access: Published
//  Description: Sets the inertia of a rigid body. Inertia is given
//               as a three-component vector. A component value of
//               zero means infinite inertia along this direction.
//               Setting the intertia will override the value which
//               is automatically calculated from the rigid bodies
//               shape. However, it is possible that automatic
//               calculation of intertia is trigger after calling
//               this method, and thus overwriting the explicitly
//               set value again. This happens when:
//               (a) the mass is set after the inertia.
//               (b) a shape is added or removed from the body.
//               (c) the scale of the body changed.
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_inertia(const LVecBase3f &inertia) {

  btVector3 inv_inertia(
    inertia.get_x() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_x()),
    inertia.get_y() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_y()),
    inertia.get_z() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_z())
    );

  _rigid->setInvInertiaDiagLocal(inv_inertia);
  _rigid->updateInertiaTensor();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_inertia
//       Access: Published
//  Description: Returns the inertia of the rigid body. Inertia is
//               given as a three component vector. A component
//               value of zero means infinite inertia along this
//               direction.
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_inertia() const {

  btVector3 inv_inertia = _rigid->getInvInertiaDiagLocal();
  LVector3f inertia(
    inv_inertia.x() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.x(),
    inv_inertia.y() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.y(),
    inv_inertia.z() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.z()
    );

  return inertia;
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_force
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_force(const LVector3f &force, const LPoint3f &pos) {

  nassertv_always(!force.is_nan());
  nassertv_always(!pos.is_nan());

  _rigid->applyForce(LVecBase3f_to_btVector3(force),
                     LVecBase3f_to_btVector3(pos));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_central_force
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_central_force(const LVector3f &force) {

  nassertv_always(!force.is_nan());

  _rigid->applyCentralForce(LVecBase3f_to_btVector3(force));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_torque
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_torque(const LVector3f &torque) {

  nassertv_always(!torque.is_nan());

  _rigid->applyTorque(LVecBase3f_to_btVector3(torque));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_torque_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_torque_impulse(const LVector3f &torque) {

  nassertv_always(!torque.is_nan());

  _rigid->applyTorqueImpulse(LVecBase3f_to_btVector3(torque));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_impulse(const LVector3f &impulse, const LPoint3f &pos) {

  nassertv_always(!impulse.is_nan());
  nassertv_always(!pos.is_nan());

  _rigid->applyImpulse(LVecBase3f_to_btVector3(impulse),
                       LVecBase3f_to_btVector3(pos));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::apply_central_impulse
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
apply_central_impulse(const LVector3f &impulse) {

  nassertv_always(!impulse.is_nan());

  _rigid->applyCentralImpulse(LVecBase3f_to_btVector3(impulse));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::transform_changed
//       Access: Protected
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
transform_changed() {

  if (_sync_disable) return;

  NodePath np = NodePath::any_path((PandaNode *)this);
  CPT(TransformState) ts = np.get_net_transform();

  LMatrix4f m_sync = _sync->get_mat();
  LMatrix4f m_ts = ts->get_mat();

  if (!m_sync.almost_equal(m_ts)) {
    _sync = ts;

    btTransform trans = TransformState_to_btTrans(ts);
    _rigid->setCenterOfMassTransform(trans);

    if (ts->has_scale()) {
      LVecBase3f scale = ts->get_scale();
      if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
        for (int i=0; i<get_num_shapes(); i++) {
          PT(BulletShape) shape = _shapes[i];
          shape->set_local_scale(scale);
        }

        shape_changed();
      }
    }

    // Activate the body if it has been sleeping
    if (!_rigid->isActive()) {
      _rigid->activate(true);
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::sync_p2b
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_p2b() {

  transform_changed();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::sync_b2p
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_b2p() {

  NodePath np = NodePath::any_path((PandaNode *)this);
  LVecBase3f scale = np.get_net_transform()->get_scale();

  btTransform trans = _rigid->getWorldTransform();
  CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);

  LMatrix4f m_sync = _sync->get_mat();
  LMatrix4f m_ts = ts->get_mat();

  if (!m_sync.almost_equal(m_ts)) {
    _sync = ts;
    _sync_disable = true;
    np.set_transform(NodePath(), ts);
    _sync_disable = false;
  }
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_linear_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_linear_velocity() const {

  return btVector3_to_LVector3f(_rigid->getLinearVelocity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_angular_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_angular_velocity() const {

  return btVector3_to_LVector3f(_rigid->getAngularVelocity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_velocity(const LVector3f &velocity) {

  nassertv_always(!velocity.is_nan());

  _rigid->setLinearVelocity(LVecBase3f_to_btVector3(velocity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_velocity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_velocity(const LVector3f &velocity) {

  nassertv_always(!velocity.is_nan());

  _rigid->setAngularVelocity(LVecBase3f_to_btVector3(velocity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::clear_forces
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
clear_forces() {

  _rigid->clearForces();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_linear_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_linear_sleep_threshold() const {

  return _rigid->getLinearSleepingThreshold();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_angular_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
float BulletRigidBodyNode::
get_angular_sleep_threshold() const {

  return _rigid->getAngularSleepingThreshold();
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_sleep_threshold(float threshold) {

  _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_sleep_threshold
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_sleep_threshold(float threshold) {

  _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_gravity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_gravity(const LVector3f &gravity) {

  nassertv_always(!gravity.is_nan());

  _rigid->setGravity(LVecBase3f_to_btVector3(gravity));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::get_gravity
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
LVector3f BulletRigidBodyNode::
get_gravity() const {

  return btVector3_to_LVector3f(_rigid->getGravity());
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_linear_factor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_linear_factor(const LVector3f &factor) {

  _rigid->setLinearFactor(LVecBase3f_to_btVector3(factor));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::set_angular_factor
//       Access: Published
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
set_angular_factor(const LVector3f &factor) {

  _rigid->setAngularFactor(LVecBase3f_to_btVector3(factor));
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::MotionState::getWorldTransform
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::MotionState::
getWorldTransform(btTransform &trans) const {

  trans = TransformState_to_btTrans(_sync);
}

////////////////////////////////////////////////////////////////////
//     Function: BulletRigidBodyNode::MotionState::setWorldTransform
//       Access: Public
//  Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::MotionState::
setWorldTransform(const btTransform &trans) {

}

<|endoftext|>


<commit_before>/*
 * $Id: field.cc,v 2.7 2005/10/20 11:24:12 martin Exp $
 * Copyright (c) 2004, 2005, Voidsoft AB
 */

#include <iostream>
#include "field.hh"
#include "tdspp.hh" // for TDSPP::Exception

/** Class Field */
/** Constructor */
Field::Field()
    : data(NULL) {
}

Field::Field(string name, int size) {
    colname = name;
    data = new char[size] = {0};
}

/** Destructor */
Field::~Field() {
    delete [] data;
}

string Field::tostr() {
    if (!data) throw TDSPP::Exception("Field::tostr: Data not initialized");
    return data;
}

/* Not implemented */
long Field::toint() {
    if (!data) throw TDSPP::Exception("Field::toint: Data not initialized");
    return 0;
}

/** Class Rows */
/** Constructor */
Rows::Rows()
    : currentrow(0) {
}

/** Destructor */
Rows::~Rows() {
    clear();
}

void Rows::clear(void) {
    while (rows.size()) {
        while (rows[rows.size()-1].size()) {
            delete rows[rows.size()-1].back();
            rows[rows.size()-1].pop_back();
        }
        rows.pop_back();
    }
}

void Rows::printheader(void) {
    cout << "| ";
    for (unsigned int i=0; i < rows[currentrow].size(); i++) {
        cout << rows[currentrow][i]->colname << " | ";
    }
    cout << endl;
}

void Rows::print(void) {
    for (unsigned int i=0; i < rows[currentrow].size(); i++) {
        cout << rows[currentrow][i]->colname <<
            "=" << rows[currentrow][i]->tostr() << endl;
    }
}
<commit_msg>More portable initialitation mode Extended initializer lists only available with -std=c++0x or -std=gnu++0x<commit_after>/*
 * $Id: field.cc,v 2.7 2005/10/20 11:24:12 martin Exp $
 * Copyright (c) 2004, 2005, Voidsoft AB
 */

#include <iostream>
#include "field.hh"
#include "tdspp.hh" // for TDSPP::Exception

/** Class Field */
/** Constructor */
Field::Field()
    : data(NULL) {
}

Field::Field(string name, int size) {
    colname = name;
    data = new char[size];
    data[0] = 0;
}

/** Destructor */
Field::~Field() {
    delete [] data;
}

string Field::tostr() {
    if (!data) throw TDSPP::Exception("Field::tostr: Data not initialized");
    return data;
}

/* Not implemented */
long Field::toint() {
    if (!data) throw TDSPP::Exception("Field::toint: Data not initialized");
    return 0;
}

/** Class Rows */
/** Constructor */
Rows::Rows()
    : currentrow(0) {
}

/** Destructor */
Rows::~Rows() {
    clear();
}

void Rows::clear(void) {
    while (rows.size()) {
        while (rows[rows.size()-1].size()) {
            delete rows[rows.size()-1].back();
            rows[rows.size()-1].pop_back();
        }
        rows.pop_back();
    }
}

void Rows::printheader(void) {
    cout << "| ";
    for (unsigned int i=0; i < rows[currentrow].size(); i++) {
        cout << rows[currentrow][i]->colname << " | ";
    }
    cout << endl;
}

void Rows::print(void) {
    for (unsigned int i=0; i < rows[currentrow].size(); i++) {
        cout << rows[currentrow][i]->colname <<
            "=" << rows[currentrow][i]->tostr() << endl;
    }
}
<|endoftext|>