5 #include "panelnode.hxx"
12 #include <simgear/compiler.h>
13 #include <simgear/structure/exception.hxx>
14 #include <simgear/debug/logstream.hxx>
16 #include <simgear/scene/util/OSGMath.hxx>
17 #include <simgear/scene/util/SGPickCallback.hxx>
18 #include <simgear/scene/util/SGSceneUserData.hxx>
19 #include <simgear/scene/util/SGNodeMasks.hxx>
21 #include <Main/fg_os.hxx>
22 #include <Cockpit/panel.hxx>
23 #include <Cockpit/panel_io.hxx>
28 class FGPanelPickCallback : public SGPickCallback {
30 FGPanelPickCallback(FGPanelNode* p) :
34 virtual bool buttonPressed(int b, const Info& info)
37 // convert to panel coordinates
38 osg::Matrixd m = osg::Matrixd::inverse(panel->transformMatrix());
39 picked = toOsg(info.local) * m;
40 SG_LOG( SG_INSTR, SG_DEBUG, "panel pick: " << toSG(picked) );
43 return panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_DOWN,
44 picked.x(), picked.y());
47 virtual void update(double /* dt */)
49 panel->getPanel()->updateMouseDelay();
52 virtual void buttonReleased(void)
54 panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_UP,
55 picked.x(), picked.y());
64 FGPanelNode::FGPanelNode(SGPropertyNode* props) :
65 _resizeToViewport(false)
67 // Make an FGPanel object. But *don't* call init() or bind() on
68 // it -- those methods touch static state.
69 const char *path = props->getStringValue("path");
70 _panel = fgReadPanel(path);
72 throw sg_io_exception(string("Failed to load panel ") + path);
74 // And the corner points
75 SGPropertyNode* pt = props->getChild("bottom-left");
76 _bottomLeft[0] = pt->getFloatValue("x-m");
77 _bottomLeft[1] = pt->getFloatValue("y-m");
78 _bottomLeft[2] = pt->getFloatValue("z-m");
80 pt = props->getChild("top-left");
81 _topLeft[0] = pt->getFloatValue("x-m");
82 _topLeft[1] = pt->getFloatValue("y-m");
83 _topLeft[2] = pt->getFloatValue("z-m");
85 pt = props->getChild("bottom-right");
86 _bottomRight[0] = pt->getFloatValue("x-m");
87 _bottomRight[1] = pt->getFloatValue("y-m");
88 _bottomRight[2] = pt->getFloatValue("z-m");
90 _panel->setDepthTest( props->getBoolValue("depth-test") );
95 FGPanelNode::FGPanelNode(FGPanel* p) :
97 _resizeToViewport(true)
102 void FGPanelNode::initWithPanel()
106 // Never mind. We *have* to call init to make sure the static
107 // state is initialized (it's not, if there aren't any 2D
108 // panels). This is a memory leak and should be fixed!`
112 // Read out the pixel-space info
113 _xmax = _panel->getWidth();
114 _ymax = _panel->getHeight();
117 // Now generate our transformation matrix. For shorthand, use
118 // "a", "b", and "c" as our corners and "m" as the matrix. The
119 // vector u goes from a to b, v from a to c, and w is a
120 // perpendicular cross product.
121 osg::Vec3 a = _bottomLeft;
122 osg::Vec3 b = _bottomRight;
123 osg::Vec3 c = _topLeft;
128 osg::Matrix& m = _xform;
129 // Now generate a trivial basis transformation matrix. If we want
130 // to map the three unit vectors to three arbitrary vectors U, V,
131 // and W, then those just become the columns of the 3x3 matrix.
132 m(0,0) = u[0]; m(1,0) = v[0]; m(2,0) = w[0]; m(3,0) = a[0];// |Ux Vx Wx|
133 m(0,1) = u[1]; m(1,1) = v[1]; m(2,1) = w[1]; m(3,1) = a[1];//m = |Uy Vy Wy|
134 m(0,2) = u[2]; m(1,2) = v[2]; m(2,2) = w[2]; m(3,2) = a[2];// |Uz Vz Wz|
135 m(0,3) = 0; m(1,3) = 0; m(2,3) = 0; m(3,3) = 1;
137 // The above matrix maps the unit (!) square to the panel
138 // rectangle. Postmultiply scaling factors that match the
139 // pixel-space size of the panel.
146 setUseDisplayList(false);
147 setDataVariance(Object::DYNAMIC);
149 getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
150 getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
153 FGPanelNode::~FGPanelNode()
158 osg::Matrix FGPanelNode::transformMatrix() const
160 if (!_resizeToViewport) {
164 double s = _panel->getAspectScale();
165 osg::Matrix m = osg::Matrix::scale(s, s, 1.0);
166 m *= osg::Matrix::translate(_panel->getXOffset(), _panel->getYOffset(), 0.0);
172 FGPanelNode::drawImplementation(osg::State& state) const
174 osg::ref_ptr<osg::RefMatrix> mv = new osg::RefMatrix;
175 mv->set(transformMatrix() * state.getModelViewMatrix());
176 state.applyModelViewMatrix(mv.get());
182 FGPanelNode::computeBound() const
185 osg::Matrix m(transformMatrix());
186 coords[0] = m.preMult(osg::Vec3(0,0,0));
187 coords[1] = m.preMult(osg::Vec3(_xmax,0,0));
188 coords[2] = m.preMult(osg::Vec3(0,_ymax,0));
191 bb.expandBy(coords[0]);
192 bb.expandBy(coords[1]);
193 bb.expandBy(coords[2]);
197 void FGPanelNode::accept(osg::PrimitiveFunctor& functor) const
200 osg::Matrix m(transformMatrix());
202 coords[0] = m.preMult(osg::Vec3(0,0,0));
203 coords[1] = m.preMult(osg::Vec3(_xmax,0,0));
204 coords[2] = m.preMult(osg::Vec3(_xmax, _ymax, 0));
205 coords[3] = m.preMult(osg::Vec3(0,_ymax,0));
207 functor.setVertexArray(4, coords);
208 functor.drawArrays( GL_QUADS, 0, 4);
211 static osg::Node* createGeode(FGPanelNode* panel)
213 osg::Geode* geode = new osg::Geode;
214 geode->addDrawable(panel);
216 geode->setNodeMask(SG_NODEMASK_PICK_BIT | SG_NODEMASK_2DPANEL_BIT);
218 SGSceneUserData* userData;
219 userData = SGSceneUserData::getOrCreateSceneUserData(geode);
220 userData->setPickCallback(new FGPanelPickCallback(panel));
224 osg::Node* FGPanelNode::createNode(FGPanel* p)
226 FGPanelNode* drawable = new FGPanelNode(p);
227 return createGeode(drawable);
230 osg::Node* FGPanelNode::load(SGPropertyNode *n)
232 FGPanelNode* drawable = new FGPanelNode(n);
233 return createGeode(drawable);