1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
#ifndef VPYTHON_MOUSEOBJECT_HPP
#define VPYTHON_MOUSEOBJECT_HPP
// Copyright (c) 2000, 2001, 2002, 2003 by David Scherer and others.
// See the file license.txt for complete license terms.
// See the file authors.txt for a complete list of contributors.
#include "renderable.hpp"
#include "util/atomic_queue.hpp"
#include <queue>
#include <utility>
#include <bitset>
namespace cvisual {
/** This common base class implements common functionality for event and mouse.
* It should never be used directly.
*/
class mousebase
{
protected:
std::string button_name();
std::bitset<4> modifiers;
std::bitset<5> eventtype;
std::bitset<3> buttons;
public:
mousebase() {}
virtual ~mousebase();
// The position of the mouse, either currently, or when the even happened.
vector position;
// The position of the camera in the scene.
vector cam;
// The object nearest to the cursor when this event happened.
shared_ptr<renderable> pick;
// The position on the object that intersects with ray.
vector pickpos;
/* 'buttonstate' contains the following state flags as defined by 'button'.
*/
enum modifiers_t { shift, ctrl, alt, command };
/* 'eventtype' contains state flags as defined by 'event'.
*/
enum event_t { press, release, click, drag, drop };
enum button_t { left, right, middle };
inline bool is_press() const { return eventtype.test( press); }
inline bool is_release() const { return eventtype.test( release); }
inline bool is_click() const { return eventtype.test( click); }
inline bool is_drag() const { return eventtype.test( drag); }
inline bool is_drop() const { return eventtype.test( drop); }
std::string* get_buttons() const;
inline bool is_shift() const { return modifiers.test( shift); }
inline bool is_ctrl() const { return modifiers.test( ctrl); }
inline bool is_alt() const { return modifiers.test( alt); } // option on Mac keyboard
inline bool is_command() const { return modifiers.test( command); }
inline vector get_pos() const { return position; }
inline vector get_camera() const { return cam; }
inline vector get_ray() const { return (position - cam).norm(); }
inline vector get_pickpos() const { return pickpos; }
shared_ptr<renderable> get_pick();
inline void set_shift( bool _shift) { modifiers.set( shift, _shift); }
inline void set_ctrl( bool _ctrl) { modifiers.set( ctrl, _ctrl); }
inline void set_alt( bool _alt) { modifiers.set( alt, _alt); } // option on Mac keyboard
inline void set_command( bool _command) { modifiers.set( command, _command); }
inline void set_press( bool _press) { eventtype.set( press, _press); }
inline void set_release( bool _release) { eventtype.set( release, _release); }
inline void set_click( bool _click) { eventtype.set( click, _click); }
inline void set_drag( bool _drag) { eventtype.set( drag, _drag); }
inline void set_drop( bool _drop) { eventtype.set( drop, _drop); }
inline void set_leftdown( bool _ld) { buttons.set( left, _ld); }
inline void set_rightdown( bool _rd) { buttons.set( right, _rd); }
inline void set_middledown( bool _md) { buttons.set( middle, _md); }
vector project1( vector normal, double dist);
vector project2( vector normal, vector point = vector(0,0,0));
// These functions will return an object constructed from std::string, or None.
std::string get_press();
std::string get_release();
std::string get_click();
std::string get_drag();
std::string get_drop();
};
/* Objects of this class represent the state of the mouse at a distinct event:
* either press, release, click, drag, or drop.
*/
class event: public mousebase
{
public:
event(){}
};
/* A class exported to python as the single object display.mouse.
* All of the python access for data within this class get the present value of
* the data.
*/
class mouse_t : public mousebase
{
private:
// The bool tells whether or not the click was a left click or not.
atomic_queue<shared_ptr<event> > events;
int click_count; // number of queued events which are left clicks
public:
mouse_t() : click_count(0) {}
virtual ~mouse_t();
// The following member functions are synchronized - no additional locking
// is requred.
int num_events() const;
void clear_events(int);
int num_clicks() const;
// Exposed as the function display.mouse.getevent()
shared_ptr<event> pop_event();
// Exposed as the function mouse.getclick()
shared_ptr<event> pop_click();
/** Push a new event onto the queue. This function is not exposed to Python.
*/
void push_event( shared_ptr<event>);
};
// Convenience functions for creating event objects.
// which represents which mouse button is involved:
// 1 for left
// 2 for right
// 3 for middle
// no other number is valid.
shared_ptr<event> click_event( int which, const mouse_t& mouse);
shared_ptr<event> drop_event( int which, const mouse_t& mouse);
shared_ptr<event> press_event( int which, const mouse_t& mouse);
shared_ptr<event> drag_event( int which, const mouse_t& mouse);
shared_ptr<event> release_event( int which, const mouse_t& mouse);
// Utility object for tracking mouse press, release, clicks, drags, and drops.
struct mousebutton
{
bool down;
bool dragging;
float last_down_x;
float last_down_y;
mousebutton()
: down(false), dragging(false),
last_down_x(-1.0f), last_down_y(-1.0f) {}
// When the button is pressed, call this function with its screen
// coordinate position. It returns true if this is a unique event
bool press( float x, float y)
{
if (down) {
return false;
}
down = true;
last_down_x = x;
last_down_y = y;
dragging = false;
return true;
}
// Returns true when a drag event should be generated, false otherwise
bool is_dragging()
{
if (down && !dragging) {
dragging = true;
return true;
}
return false;
}
// Returns (is_unique, is_drop)
std::pair<bool, bool> release()
{
bool unique = down;
down = false;
last_down_x = -1;
last_down_y = -1;
return std::make_pair(unique, dragging);
}
};
/*
* A thin wrapper for buffering cursor visibility information between the python loop
* and the rendering loop.
*/
class cursor_object
{
public:
//mutex mtx;
bool visible; // whether cursor should be visible
bool last_visible; // previous state of cursor visibility
inline cursor_object() : visible(true), last_visible(true) {}
void set_visible( bool vis) { visible = vis; }
//bool get_visible() { mutex::lock L(mtx); return visible; }
bool get_visible() { return visible; }
};
} // !namespace cvisual
#endif // !VPYTHON_MOUSEOBJECT_HPP
|