Knob animation: shifted mode binding.
As part of this, pass the osgGA GUIEventAdapter down into the pick callbacks, which seems reasonable to me. If anyone can foresee issues with this, please let me know and I can adjust the API.
This commit is contained in:
parent
e7f9486aa1
commit
e8156c6bd9
@ -26,7 +26,8 @@
|
||||
#include <osg/PolygonOffset>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgGA/GUIEventAdapter>
|
||||
|
||||
#include <simgear/scene/util/SGPickCallback.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||
@ -66,7 +67,7 @@ using OpenThreads::ScopedLock;
|
||||
_bindingsUp.push_back(new SGBinding(bindings[i], modelRoot));
|
||||
}
|
||||
}
|
||||
virtual bool buttonPressed(int button, const Info&)
|
||||
virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info&)
|
||||
{
|
||||
bool found = false;
|
||||
for( std::vector<int>::iterator it = _buttons.begin(); it != _buttons.end(); ++it ) {
|
||||
@ -206,7 +207,7 @@ using OpenThreads::ScopedLock;
|
||||
_squaredDown = dot(_toDown, _toDown);
|
||||
}
|
||||
|
||||
virtual bool buttonPressed(int button, const Info& info)
|
||||
virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info& info)
|
||||
{
|
||||
SGVec3d loc(info.local);
|
||||
SG_LOG(SG_INPUT, SG_DEBUG, "VNC pressed " << button << ": " << loc);
|
||||
@ -340,12 +341,24 @@ SGPickAnimation::innerSetupPickGroup(osg::Group* commonGroup, osg::Group& parent
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// insert count copies of binding list A, into the output list.
|
||||
// effectively makes the output list fire binding A multiple times
|
||||
// in sequence
|
||||
static void repeatBindings(const SGBindingList& a, SGBindingList& out, int count)
|
||||
{
|
||||
out.clear();
|
||||
for (int i=0; i<count; ++i) {
|
||||
out.insert(out.end(), a.begin(), a.end());
|
||||
}
|
||||
}
|
||||
|
||||
class SGKnobAnimation::KnobPickCallback : public SGPickCallback {
|
||||
public:
|
||||
KnobPickCallback(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
_direction(DIRECTION_NONE),
|
||||
_repeatInterval(configNode->getDoubleValue("interval-sec", 0.1))
|
||||
_repeatInterval(configNode->getDoubleValue("interval-sec", 0.1)),
|
||||
_stickyShifted(false)
|
||||
{
|
||||
const SGPropertyNode* act = configNode->getChild("action");
|
||||
if (act)
|
||||
@ -358,10 +371,41 @@ public:
|
||||
const SGPropertyNode* ccw = configNode->getChild("ccw");
|
||||
if (ccw)
|
||||
_bindingsCCW = readBindingList(ccw->getChildren("binding"), modelRoot);
|
||||
|
||||
if (configNode->hasChild("shift-action") || configNode->hasChild("shift-cw") ||
|
||||
configNode->hasChild("shift-ccw"))
|
||||
{
|
||||
// explicit shifted behaviour - just do exactly what was provided
|
||||
const SGPropertyNode* act = configNode->getChild("shift-action");
|
||||
if (act)
|
||||
_shiftedAction = readBindingList(act->getChildren("binding"), modelRoot);
|
||||
|
||||
const SGPropertyNode* cw = configNode->getChild("shift-cw");
|
||||
if (cw)
|
||||
_shiftedCW = readBindingList(cw->getChildren("binding"), modelRoot);
|
||||
|
||||
const SGPropertyNode* ccw = configNode->getChild("shift-ccw");
|
||||
if (ccw)
|
||||
_shiftedCCW = readBindingList(ccw->getChildren("binding"), modelRoot);
|
||||
} else {
|
||||
// default shifted behaviour - repeat normal bindings N times.
|
||||
int shiftRepeat = configNode->getIntValue("shift-repeat", 10);
|
||||
repeatBindings(_action, _shiftedAction, shiftRepeat);
|
||||
repeatBindings(_bindingsCW, _shiftedCW, shiftRepeat);
|
||||
repeatBindings(_bindingsCCW, _shiftedCCW, shiftRepeat);
|
||||
} // of default shifted behaviour
|
||||
}
|
||||
|
||||
virtual bool buttonPressed(int button, const Info&)
|
||||
virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* ea, const Info&)
|
||||
{
|
||||
_stickyShifted = ea->getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT;
|
||||
|
||||
// the 'be nice to Mac / laptop' users option; alt-clicking spins the
|
||||
// opposite direction. Should make this configurable
|
||||
if ((button == 0) && (ea->getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_ALT)) {
|
||||
button = 1;
|
||||
}
|
||||
|
||||
_direction = DIRECTION_NONE;
|
||||
if ((button == 0) || (button == 4)) {
|
||||
_direction = DIRECTION_CLOCKWISE;
|
||||
@ -372,7 +416,7 @@ public:
|
||||
}
|
||||
|
||||
_repeatTime = -_repeatInterval; // anti-bobble: delay start of repeat
|
||||
fire();
|
||||
fire(_stickyShifted);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -385,28 +429,32 @@ public:
|
||||
_repeatTime += dt;
|
||||
while (_repeatInterval < _repeatTime) {
|
||||
_repeatTime -= _repeatInterval;
|
||||
fire();
|
||||
fire(_stickyShifted);
|
||||
} // of repeat iteration
|
||||
}
|
||||
private:
|
||||
void fire()
|
||||
void fire(bool isShifted)
|
||||
{
|
||||
const SGBindingList& act(isShifted ? _shiftedAction : _action);
|
||||
const SGBindingList& cw(isShifted ? _shiftedCW : _bindingsCW);
|
||||
const SGBindingList& ccw(isShifted ? _shiftedCCW : _bindingsCCW);
|
||||
|
||||
switch (_direction) {
|
||||
case DIRECTION_CLOCKWISE:
|
||||
fireBindingListWithOffset(_action, 1, 1);
|
||||
fireBindingList(_bindingsCW);
|
||||
fireBindingListWithOffset(act, 1, 1);
|
||||
fireBindingList(cw);
|
||||
break;
|
||||
case DIRECTION_ANTICLOCKWISE:
|
||||
fireBindingListWithOffset(_action, -1, 1);
|
||||
fireBindingList(_bindingsCCW);
|
||||
fireBindingListWithOffset(act, -1, 1);
|
||||
fireBindingList(ccw);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
SGBindingList _action;
|
||||
SGBindingList _bindingsCW,
|
||||
_bindingsCCW;
|
||||
SGBindingList _action, _shiftedAction;
|
||||
SGBindingList _bindingsCW, _shiftedCW,
|
||||
_bindingsCCW, _shiftedCCW;
|
||||
|
||||
enum Direction
|
||||
{
|
||||
@ -418,6 +466,10 @@ private:
|
||||
Direction _direction;
|
||||
double _repeatInterval;
|
||||
double _repeatTime;
|
||||
|
||||
// FIXME - would be better to pass the current modifier state
|
||||
// into update(), but for now let's make it sticky
|
||||
bool _stickyShifted;
|
||||
};
|
||||
|
||||
class SGKnobAnimation::UpdateCallback : public osg::NodeCallback {
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
namespace osgGA { class GUIEventAdapter; }
|
||||
|
||||
// Used to implement scenery interaction.
|
||||
// The interface is still under development
|
||||
class SGPickCallback : public SGReferenced {
|
||||
@ -46,7 +48,7 @@ public:
|
||||
{ }
|
||||
|
||||
virtual ~SGPickCallback() {}
|
||||
virtual bool buttonPressed(int button, const Info& info)
|
||||
virtual bool buttonPressed(int button, const osgGA::GUIEventAdapter* event, const Info& info)
|
||||
{ return false; }
|
||||
virtual void update(double dt)
|
||||
{ }
|
||||
|
Loading…
Reference in New Issue
Block a user