-}
-
-FGPanelNode::FGPanelNode(SGPropertyNode* props)
-{
- int i;
-
- // Make an FGPanel object. But *don't* call init() or bind() on
- // it -- those methods touch static state.
- _panel = fgReadPanel(props->getStringValue("path"));
-
- // Never mind. We *have* to call init to make sure the static
- // state is initialized (it's not, if there aren't any 2D
- // panels). This is a memory leak and should be fixed!`
- _panel->init();
-
- // Initialize the matrices to the identity. PLib prints warnings
- // when trying to invert singular matrices (e.g. when not using a
- // 3D panel).
- for(i=0; i<4; i++)
- for(int j=0; j<4; j++)
- _lastModelview[4*i+j] = _lastProjection[4*i+j] = i==j ? 1 : 0;
-
- // Read out the pixel-space info
- _xmax = _panel->getWidth();
- _ymax = _panel->getHeight();
-
- // And the corner points
- SGPropertyNode* pt = props->getChild("bottom-left");
- _bottomLeft[0] = pt->getFloatValue("x-m");
- _bottomLeft[1] = pt->getFloatValue("y-m");
- _bottomLeft[2] = pt->getFloatValue("z-m");
-
- pt = props->getChild("top-left");
- _topLeft[0] = pt->getFloatValue("x-m");
- _topLeft[1] = pt->getFloatValue("y-m");
- _topLeft[2] = pt->getFloatValue("z-m");
-
- pt = props->getChild("bottom-right");
- _bottomRight[0] = pt->getFloatValue("x-m");
- _bottomRight[1] = pt->getFloatValue("y-m");
- _bottomRight[2] = pt->getFloatValue("z-m");
-
- // Now generate our transformation matrix. For shorthand, use
- // "a", "b", and "c" as our corners and "m" as the matrix. The
- // vector u goes from a to b, v from a to c, and w is a
- // perpendicular cross product.
- float *a = _bottomLeft, *b = _bottomRight, *c = _topLeft, *m = _xform;
- float u[3], v[3], w[3];
- for(i=0; i<3; i++) u[i] = b[i] - a[i]; // U = B - A
- for(i=0; i<3; i++) v[i] = c[i] - a[i]; // V = C - A
-
- w[0] = u[1]*v[2] - v[1]*u[2]; // W = U x V
- w[1] = u[2]*v[0] - v[2]*u[0];
- w[2] = u[0]*v[1] - v[0]*u[1];
-
- // Now generate a trivial basis transformation matrix. If we want
- // to map the three unit vectors to three arbitrary vectors U, V,
- // and W, then those just become the columns of the 3x3 matrix.
- m[0] = u[0]; m[4] = v[0]; m[8] = w[0]; m[12] = a[0]; // |Ux Vx Wx|
- m[1] = u[1]; m[5] = v[1]; m[9] = w[1]; m[13] = a[1]; // m = |Uy Vy Wy|
- m[2] = u[2]; m[6] = v[2]; m[10] = w[2]; m[14] = a[2]; // |Uz Vz Wz|
- m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
-
- // The above matrix maps the unit (!) square to the panel
- // rectangle. Postmultiply scaling factors that match the
- // pixel-space size of the panel.
- for(i=0; i<4; i++) {
- m[0+i] *= 1.0/_xmax;
- m[4+i] *= 1.0/_ymax;
+private:
+ FGPanelNode* _panelNode;
+};
+
+class FGPanelPickCallback : public SGPickCallback {
+public:
+ FGPanelPickCallback(FGPanelNode* p) :
+ panel(p)
+ {}
+
+ virtual bool buttonPressed( int b,
+ const osgGA::GUIEventAdapter&,
+ const Info& info )
+ {
+ if (!panel->getPanel()) {
+ return false;
+ }
+
+ button = b;
+ // convert to panel coordinates
+ osg::Matrixd m = osg::Matrixd::inverse(panel->transformMatrix());
+ picked = toOsg(info.local) * m;
+ SG_LOG( SG_INSTR, SG_DEBUG, "panel pick: " << toSG(picked) );
+
+ // send to the panel
+ return panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_DOWN,
+ picked.x(), picked.y());
+ }
+
+ virtual void update(double dt, int keyModState)
+ {
+ panel->getPanel()->updateMouseDelay(dt);
+ }
+
+ virtual void buttonReleased( int,
+ const osgGA::GUIEventAdapter&,
+ const Info* )
+ {
+ panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_UP,
+ picked.x(), picked.y());
+ }
+
+private:
+ FGPanelNode* panel;
+ int button;
+ osg::Vec3 picked;
+};
+
+class FGPanelSwitchCallback : public osg::NodeCallback {
+public:
+ FGPanelSwitchCallback(FGPanelNode* pn) :
+ panel(pn),
+ visProp(fgGetNode("/sim/panel/visibility"))
+ {
+ }
+
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ assert(dynamic_cast<osg::Switch*>(node));
+ osg::Switch* sw = static_cast<osg::Switch*>(node);
+
+ if (!visProp->getBoolValue()) {
+ sw->setValue(0, false);
+ return;