-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathHandControl.h
253 lines (210 loc) · 5.31 KB
/
HandControl.h
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#pragma once
#pragma region Header Files
// STL Header
#include <functional>
#include <vector>
// Boost Header
#include <boost/chrono.hpp>
#include <boost/circular_buffer.hpp>
// QT Header
#include <QtGui/QtGui>
#include "NIButton.h"
#pragma endregion
/**
* The icon of hand position
*/
class QHandIcon : public QGraphicsItem
{
public:
enum HAND_STATE
{
HS_GENERAL,
HS_FIXING,
HS_FIXED
};
public:
QPen m_penGeneral; /**< The pen used in HS_GENERAL status */
QPen m_penFixing; /**< The pen used in HS_FIXING status */
QPen m_penFixingProgress; /**< The pen used in HS_FIXING status for progress */
QPen m_penFixed; /**< The pen used in HS_FIXED status (border) */
QBrush m_brushFixed; /**< The brush used in HS_FIXED status (fill) */
public:
QHandIcon( float fSize = 50 )
{
m_eStatus = HS_GENERAL;
m_fProgress = 0.0f;
// drawing parameter in HS_GENERAL status
m_penGeneral.setColor( qRgba( 255, 255, 0, 128 ) );
m_penGeneral.setWidth( 5 );
// drawing parameter in HS_FIXING status
m_penFixing.setColor( qRgba( 255, 255, 0, 255 ) );
m_penFixing.setWidth( 5 );
m_penFixingProgress.setColor( qRgba( 0, 255, 0, 255 ) );
m_penFixingProgress.setWidth( 15 );
// drawing parameter in HS_FIXED status
m_penFixed.setColor( qRgba( 0, 0, 0, 0 ) );
m_brushFixed = QBrush(qRgba( 255, 0, 0, 128 ));
SetSize( fSize );
hide();
}
/**
* Set the size of the hand icon
*/
void SetSize( float fSize )
{
float fHS = fSize / 2;
m_Rect.setRect( -fHS, -fHS, fSize, fSize );
}
/**
* Update the status of the hand (the draw method will be changed)
*/
void SetStatus( const HAND_STATE& eStatus )
{
m_eStatus = eStatus;
}
/**
* Update the hand icon progress. Only make effect when status is HS_FIXING
*/
void SetProgress( const float& fVal )
{
m_fProgress = fVal;
}
QRectF boundingRect() const
{
return m_Rect;
}
void paint( QPainter *pPainter, const QStyleOptionGraphicsItem *option, QWidget *widget );
private:
QRectF m_Rect;
HAND_STATE m_eStatus;
float m_fProgress;
};
/**
* Hand control system
*/
class QHandControl : public QGraphicsItemGroup
{
public:
float m_fHandMoveThreshold; /**< The movement threshold for fixing hand (2D) */
float m_fHandForwardDistance; /**< The forward distance threshold for initial fix hand */
boost::chrono::milliseconds m_tdPreFixTime; /**< The time start to fix */
boost::chrono::milliseconds m_tdFixTime; /**< The time to fix */
boost::chrono::milliseconds m_tdInvokeTime; /**< The time to invoke button */ //TODO: no work now
std::function<void()> m_funcStartInput;
std::function<void()> m_funcEndInput;
public:
QHandControl()
{
m_fHandMoveThreshold = 25;
m_fHandForwardDistance = 250;
m_tdPreFixTime = boost::chrono::milliseconds( 100 );
m_tdFixTime = boost::chrono::milliseconds( 500 );
m_tdInvokeTime = boost::chrono::milliseconds( 300 );
m_funcStartInput = [](){};
m_funcEndInput = [](){};
m_aTrackList.set_capacity( 150 );
SetRect( QRectF( 0, 0, 640, 480 ) );
BuildButtons();
addToGroup( &m_HandIcon );
addToGroup( &m_qButtons );
m_eControlStatus = NICS_INPUT;
UpdateStatus( NICS_NO_HAND );
}
/**
* Reset hand status, clear history
*/
void HandReset()
{
UpdateStatus( NICS_STANDBY );
m_aTrackList.clear();
}
/**
* Update current hand point information
*/
void UpdateHandPoint( const QPointF& rPt2D, const QVector3D& rPt3D );
/**
* Set the hand as lost
*/
void HandLost()
{
UpdateStatus( NICS_NO_HAND );
}
/**
* Set the region of this widget
*/
void SetRect( const QRectF& rRect )
{
m_qRect = rRect;
m_HandIcon.SetSize( rRect.width() / 12 );
}
QRectF boundingRect() const
{
return m_qRect;
}
private:
typedef boost::chrono::system_clock::time_point TTimePoint;
enum EControlStatus
{
NICS_NO_HAND,
NICS_STANDBY,
NICS_FIXING,
NICS_FIXED,
NICS_INPUT,
};
/**
* Structure to save required data at each yime point
*/
struct SHandPos
{
TTimePoint tpTime;
QPointF mPos2D;
QVector3D mPos3D;
SHandPos(){}
SHandPos( const QPointF& pos2D, const QVector3D& pos3D )
{
tpTime = boost::chrono::system_clock::now();
mPos2D = pos2D;
mPos3D = pos3D;
}
};
private:
template<typename _TDuration>
bool Is2DPosFixFor( const _TDuration& rDuration, float fMoveRange = 10 )
{
if( m_aTrackList.size() < 2 )
return false;
auto itStartPt = m_aTrackList.rbegin();
auto itPt = itStartPt + 1;
for( ; itPt != m_aTrackList.rend(); ++ itPt )
{
// check position
if( QLineF( itStartPt->mPos2D, itPt->mPos2D ).length() > fMoveRange )
return false;
// check time
if( itStartPt->tpTime - itPt->tpTime > rDuration )
return true;
}
return false;
}
bool UpdateStatus( const EControlStatus& eStatus );
const SHandPos& CurrentPos() const
{
return m_aTrackList.back();
}
void BuildButtons();
template<typename _TD1, typename _TD2>
float ComputeProgress( const _TD1& time1, const _TD2& time2 )
{
return float(boost::chrono::duration_cast<_TD2>( time1 ).count()) / time2.count();
}
private:
QHandIcon m_HandIcon;
QGraphicsItemGroup m_qButtons;
QRectF m_qRect;
EControlStatus m_eControlStatus;
SHandPos m_FixPos;
boost::circular_buffer<SHandPos> m_aTrackList;
std::vector<QBaseProgressButton*> m_vButtons;
std::vector<QBaseProgressButton*>::iterator m_itCurrentButton;
TTimePoint m_tpFirstIn;
};