1
0
Fork 0
flightgear/src/GUI/MouseCursor.cxx
Richard Harrison 2c8aad12ba Model relative property tree root binding.
Change fgcommand to take an optional property tree root element.

This fixes the animation bindings to use the defined property tree root - to support multiplayer (or other) model that can bind to the correct part of the property tree.

Requires a corresponding fix in sg to allow the command methods to take an optional root parameter.

What this means is that when inside someone else's multiplayer model (e.g. backseat, or co-pilot), the multipalyer (AI) model will correctly modify properties inside the correct part of the property tree inside (/ai), rather than modifying the properties inside the same part of the tree as the non-ai model.

This means that a properly setup model will operate within it's own space in the property tree; and permit more generic multiplayer code to be written.

This is probably responsible for some of the pollution of the root property tree with MP aircraft properties.
2017-07-05 11:37:17 +02:00

246 lines
7 KiB
C++

// MouseCursor.cxx - abstract inteface for mouse cursor control
// Copyright (C) 2013 James Turner <zakalawe@mac.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "MouseCursor.hxx"
#include <cstring>
#include <boost/foreach.hpp>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>
#include <simgear/debug/logstream.hxx>
#include <simgear/simgear_config.h>
#include <simgear/structure/commands.hxx>
#ifdef SG_MAC
#include "CocoaMouseCursor.hxx"
#endif
#ifdef SG_WINDOWS
#include "WindowsMouseCursor.hxx"
#endif
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Viewer/renderer.hxx>
#include <Main/fg_os.hxx> // for fgWarpMouse
namespace
{
/**
* @brief when no native cursor implementation is available, use the osgViewer support. This
* has several limitations but is better than nothing
*/
class StockOSGCursor : public FGMouseCursor
{
public:
StockOSGCursor() :
mCursorObscured(false),
mCursorVisible(true),
mCursor(osgViewer::GraphicsWindow::InheritCursor)
{
mActualCursor = mCursor;
globals->get_renderer()->getViewer()->getWindows(mWindows);
}
virtual void setCursor(Cursor aCursor)
{
mCursor = translateCursor(aCursor);
updateCursor();
}
virtual void setCursorVisible(bool aVis)
{
if (mCursorObscured == aVis) {
return;
}
mCursorVisible = aVis;
updateCursor();
}
virtual void hideCursorUntilMouseMove()
{
if (mCursorObscured) {
return;
}
mCursorObscured = true;
updateCursor();
}
virtual void mouseMoved()
{
if (mCursorObscured) {
mCursorObscured = false;
updateCursor();
}
}
private:
osgViewer::GraphicsWindow::MouseCursor translateCursor(Cursor aCursor)
{
switch (aCursor) {
case CURSOR_ARROW: return osgViewer::GraphicsWindow::RightArrowCursor;
case CURSOR_HAND: return osgViewer::GraphicsWindow::HandCursor;
case CURSOR_CLOSED_HAND: return osgViewer::GraphicsWindow::HandCursor;
case CURSOR_CROSSHAIR: return osgViewer::GraphicsWindow::CrosshairCursor;
case CURSOR_IBEAM: return osgViewer::GraphicsWindow::TextCursor;
case CURSOR_LEFT_RIGHT: return osgViewer::GraphicsWindow::LeftRightCursor;
case CURSOR_UP_DOWN: return osgViewer::GraphicsWindow::UpDownCursor;
default:
return osgViewer::GraphicsWindow::RightArrowCursor;
}
}
void updateCursor()
{
osgViewer::GraphicsWindow::MouseCursor cur = osgViewer::GraphicsWindow::InheritCursor;
if (mCursorObscured || !mCursorVisible) {
cur = osgViewer::GraphicsWindow::NoCursor;
} else {
cur = mCursor;
}
if (cur == mActualCursor) {
return;
}
BOOST_FOREACH(osgViewer::GraphicsWindow* gw, mWindows) {
gw->setCursor(cur);
}
mActualCursor = cur;
}
bool mCursorObscured;
bool mCursorVisible;
osgViewer::GraphicsWindow::MouseCursor mCursor, mActualCursor;
std::vector<osgViewer::GraphicsWindow*> mWindows;
};
} // of anonymous namespace
static FGMouseCursor* static_instance = NULL;
FGMouseCursor::FGMouseCursor() :
mAutoHideTimeMsec(10000)
{
}
FGMouseCursor* FGMouseCursor::instance()
{
if (static_instance == NULL) {
#ifdef SG_MAC
if (true) {
static_instance = new CocoaMouseCursor;
}
#endif
#ifdef SG_WINDOWS
// set osgViewer cursor inherit, otherwise it will interefere
std::vector<osgViewer::GraphicsWindow*> gws;
globals->get_renderer()->getViewer()->getWindows(gws);
BOOST_FOREACH(osgViewer::GraphicsWindow* gw, gws) {
gw->setCursor(osgViewer::GraphicsWindow::InheritCursor);
}
// Windows native curosr disabled while interaction with OSG
// is resolved - right now NCHITs (non-client-area hits)
// overwire the InheritCursor value above, and hence our cursor
// get stuck.
// and create our real implementation
// static_instance = new WindowsMouseCursor;
#endif
// X11
if (static_instance == NULL) {
static_instance = new StockOSGCursor;
}
// initialise mouse-hide delay from global properties
globals->get_commands()->addCommand("set-cursor", static_instance, &FGMouseCursor::setCursorCommand);
}
return static_instance;
}
void FGMouseCursor::setAutoHideTimeMsec(unsigned int aMsec)
{
mAutoHideTimeMsec = aMsec;
}
bool FGMouseCursor::setCursorCommand(const SGPropertyNode* arg, SGPropertyNode*)
{
// JMT 2013 - I would prefer this was a seperate 'warp' command, but
// historically set-cursor has done both.
if (arg->hasValue("x") || arg->hasValue("y")) {
SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
int x = arg->getIntValue("x", mx->getIntValue());
int y = arg->getIntValue("y", my->getIntValue());
fgWarpMouse(x, y);
mx->setIntValue(x);
my->setIntValue(y);
}
Cursor c = cursorFromString(arg->getStringValue("cursor"));
setCursor(c);
return true;
}
typedef struct {
const char * name;
FGMouseCursor::Cursor cursor;
} MouseCursorMap;
const MouseCursorMap mouse_cursor_map[] = {
{ "inherit", FGMouseCursor::CURSOR_ARROW },
{ "crosshair", FGMouseCursor::CURSOR_CROSSHAIR },
{ "left-right", FGMouseCursor::CURSOR_LEFT_RIGHT },
{ "hand", FGMouseCursor::CURSOR_HAND },
{ "closed-hand", FGMouseCursor::CURSOR_CLOSED_HAND },
{ "text", FGMouseCursor::CURSOR_IBEAM },
// aliases
{ "drag-horizontal", FGMouseCursor::CURSOR_LEFT_RIGHT },
{ "drag-vertical", FGMouseCursor::CURSOR_UP_DOWN },
{ 0, FGMouseCursor::CURSOR_ARROW }
};
FGMouseCursor::Cursor FGMouseCursor::cursorFromString(const char* cursor_name)
{
for (unsigned int k = 0; mouse_cursor_map[k].name != 0; k++) {
if (!strcmp(mouse_cursor_map[k].name, cursor_name)) {
return mouse_cursor_map[k].cursor;
}
}
SG_LOG(SG_GENERAL, SG_WARN, "unknown cursor:" << cursor_name);
return CURSOR_ARROW;
}