1 #include "LDInputHandler.h"
2 #include "LDrawModelViewer.h"
3 #include <TCFoundation/TCAlertManager.h>
4 #include <TCFoundation/TCAlert.h>
5 #include <TCFoundation/TCMacros.h>
6 
7 #ifdef WIN32
8 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
9 #define new DEBUG_CLIENTBLOCK
10 #endif // _DEBUG
11 #endif // WIN32
12 
13 #ifdef COCOA
14 #include <Foundation/Foundation.h>
15 #define STOP_TIME ((NSDate *&)m_stopTime)
16 #endif // COCOA
17 
18 TCFloat LDInputHandler::sm_keyRotationSpeed = 0.5f;
19 
LDInputHandler(LDrawModelViewer * m_modelViewer)20 LDInputHandler::LDInputHandler(LDrawModelViewer *m_modelViewer):
21 	m_modelViewer(m_modelViewer),
22 	m_viewMode(VMExamine),
23 	m_mouseMode(MMNone),
24 	m_appleRightClick(false),
25 	m_numButtons(sizeof(m_buttonsDown) / sizeof(m_buttonsDown[0]))
26 #ifdef WIN32
27 	, m_haveStopTicks(false)
28 #endif // WIN32
29 #ifdef COCOA
30 	, m_stopTime(NULL)
31 #endif // COCOA
32 {
33 	memset(&m_buttonsDown, 0, sizeof(m_buttonsDown));
34 	TCAlertManager::registerHandler(LDrawModelViewer::frameDoneAlertClass(),
35 		this, (TCAlertCallback)&LDInputHandler::frameDone);
36 }
37 
~LDInputHandler(void)38 LDInputHandler::~LDInputHandler(void)
39 {
40 }
41 
dealloc(void)42 void LDInputHandler::dealloc(void)
43 {
44 #ifdef COCOA
45 	[STOP_TIME release];
46 #endif // COCOA
47 	TCAlertManager::unregisterHandler(this);
48 	TCObject::dealloc();
49 }
50 
cancelMouseDrag(void)51 void LDInputHandler::cancelMouseDrag(void)
52 {
53 	m_mouseMode = MMNone;
54 	for (int i = 0; i < m_numButtons; i++)
55 	{
56 		m_buttonsDown[i] = false;
57 	}
58 }
59 
setViewMode(LDInputHandler::ViewMode value)60 void LDInputHandler::setViewMode(LDInputHandler::ViewMode value)
61 {
62 	stopRotation();
63 	m_viewMode = value;
64 	if (m_modelViewer)
65 	{
66 		m_modelViewer->setViewMode((LDrawModelViewer::ViewMode)value);
67 		if (value == VMExamine)
68 		{
69 			m_modelViewer->setConstrainZoom(true);
70 		}
71 		else
72 		{
73 			m_modelViewer->setConstrainZoom(false);
74 		}
75 		m_modelViewer->requestRedraw();
76 	}
77 }
78 
stopRotation(void)79 void LDInputHandler::stopRotation(void)
80 {
81 	recordRotationStop();
82 	m_rotationSpeed = 0.0f;
83 	m_modelViewer->setXRotate(0.0f);
84 	m_modelViewer->setYRotate(0.0f);
85 	m_modelViewer->setRotationSpeed(m_rotationSpeed);
86 }
87 
updateSpinRateXY(int xPos,int yPos)88 void LDInputHandler::updateSpinRateXY(int xPos, int yPos)
89 {
90 	int deltaX = xPos - m_lastX;
91 	int deltaY = yPos - m_lastY;
92 	TCFloat magnitude = (TCFloat)sqrt((TCFloat)(deltaX * deltaX +
93 		deltaY * deltaY));
94 
95 	m_rotationSpeed = magnitude / 10.0f;
96 	if (fEq(m_rotationSpeed, 0.0f))
97 	{
98 		stopRotation();
99 	}
100 	else
101 	{
102 		m_modelViewer->setXRotate((TCFloat)deltaY);
103 		m_modelViewer->setYRotate((TCFloat)deltaX);
104 	}
105 	m_modelViewer->setRotationSpeed(m_rotationSpeed);
106 	m_modelViewer->requestRedraw();
107 }
108 
updateHeadXY(TCULong modifierKeys,int xPos,int yPos)109 void LDInputHandler::updateHeadXY(TCULong modifierKeys, int xPos, int yPos)
110 {
111 	TCFloat magnitude = (TCFloat)(xPos - m_clickX);
112 	TCFloat denom = 5000.0f;
113 	TCFloat fov = m_modelViewer->getFov();
114 
115 	denom /= (TCFloat)tan(deg2rad(fov));
116 	if (modifierKeys & MKShift)
117 	{
118 		debugPrintf("Faster.\n");
119 		denom /= 2.0f;
120 	}
121 	m_modelViewer->setCameraXRotate(magnitude / denom);
122 	magnitude = (TCFloat)(yPos - m_clickY);
123 	m_modelViewer->setCameraYRotate(magnitude / -denom);
124 	m_modelViewer->requestRedraw();
125 }
126 
updatePanXY(int xPos,int yPos)127 void LDInputHandler::updatePanXY(int xPos, int yPos)
128 {
129 	if (m_viewMode == VMExamine)
130 	{
131 		int deltaX = xPos - m_lastX;
132 		int deltaY = yPos - m_lastY;
133 
134 		m_modelViewer->panXY(deltaX, deltaY);
135 		m_modelViewer->requestRedraw();
136 	}
137 }
138 
updateZoomY(int yPos)139 void LDInputHandler::updateZoomY(int yPos)
140 {
141 	TCFloat magnitude = (TCFloat)(yPos - m_clickY);
142 
143 	m_modelViewer->setZoomSpeed(magnitude / 2.0f);
144 	m_modelViewer->requestRedraw();
145 }
146 
leftDown(TCULong modifierKeys,int xPos,int yPos)147 bool LDInputHandler::leftDown(TCULong modifierKeys, int xPos, int yPos)
148 {
149 	if (modifierKeys & MKShift)
150 	{
151 		if (!m_modelViewer->getUseLighting() ||
152 			m_modelViewer->getContrastingLightDirModel() == NULL)
153 		{
154 			// Allowing this will likely just lead to confusion.
155 			return false;
156 		}
157 		m_mouseMode = MMLight;
158 		m_modelViewer->setShowLightDir(true);
159 		m_modelViewer->requestRedraw();
160 	}
161 	else if (modifierKeys & MKControl)
162 	{
163 		m_mouseMode = MMPan;
164 	}
165 	else
166 	{
167 		m_mouseMode = MMNormal;
168 		updateSpinRateXY(xPos, yPos);
169 	}
170 	clearRotationStop();
171 	return true;
172 }
173 
mouseDown(TCULong modifierKeys,MouseButton button,int x,int y)174 bool LDInputHandler::mouseDown(
175 	TCULong modifierKeys,
176 	MouseButton button,
177 	int x,
178 	int y)
179 {
180 	if (button < MBFirst || button > MBLast)
181 	{
182 		return false;
183 	}
184 	if (modifierKeys & MKAppleControl && button == MBLeft)
185 	{
186 		m_appleRightClick = true;
187 		button = MBRight;
188 	}
189 	// Don't process chorded mouse clicks.
190 	for (int i = 0; i < m_numButtons; i++)
191 	{
192 		if (i != button && m_buttonsDown[i])
193 		{
194 			return false;
195 		}
196 	}
197 	m_buttonsDown[button] = true;
198 	m_lastX = m_lastFrameX = m_clickX = x;
199 	m_lastY = m_lastFrameY = m_clickY = y;
200 	switch (button)
201 	{
202 	case MBLeft:
203 		if (!leftDown(modifierKeys, x, y))
204 		{
205 			return false;
206 		}
207 		break;
208 	case MBRight:
209 		m_modelViewer->setClipZoom((modifierKeys & MKControl) != 0);
210 		m_mouseMode = MMZoom;
211 		break;
212 	case MBMiddle:
213 		m_mouseMode = MMPan;
214 		break;
215 	default:
216 		return false;
217 	}
218 	TCAlertManager::sendAlert(captureAlertClass(), this);
219 	return true;
220 }
221 
mouseCaptureChanged(void)222 bool LDInputHandler::mouseCaptureChanged(void)
223 {
224 	if (m_buttonsDown[MBLeft])
225 	{
226 		if (m_viewMode == VMFlyThrough || m_viewMode == VMWalk)
227 		{
228 			m_modelViewer->setCameraXRotate(0.0f);
229 			m_modelViewer->setCameraYRotate(0.0f);
230 		}
231 		else
232 		{
233 			m_modelViewer->setXRotate(0.0f);
234 			m_modelViewer->setYRotate(0.0f);
235 			m_modelViewer->setRotationSpeed(0.0f);
236 		}
237 		m_modelViewer->setShowLightDir(false);
238 	}
239 	if (m_buttonsDown[MBRight])
240 	{
241 		m_modelViewer->setZoomSpeed(0.0f);
242 	}
243 	m_mouseMode = MMNone;
244 	for (int i = 0; i < m_numButtons; i++)
245 	{
246 		m_buttonsDown[i] = false;
247 	}
248 	return true;
249 }
250 
mouseUp(TCULong modifierKeys,MouseButton button,int x,int y)251 bool LDInputHandler::mouseUp(
252 	TCULong modifierKeys,
253 	MouseButton button,
254 	int x,
255 	int y)
256 {
257 	if (button < MBFirst || button > MBLast)
258 	{
259 		return false;
260 	}
261 	if (button == MBLeft && m_appleRightClick)
262 	{
263 		m_appleRightClick = false;
264 		button = MBRight;
265 	}
266 	if (!m_buttonsDown[button])
267 	{
268 		return false;
269 	}
270 	if (x != m_lastX || y != m_lastY)
271 	{
272 		mouseMove(modifierKeys, x, y);
273 	}
274 	switch (button)
275 	{
276 	case MBLeft:
277 		if (m_viewMode == VMFlyThrough || m_viewMode == VMWalk)
278 		{
279 			m_modelViewer->setCameraXRotate(0.0f);
280 			m_modelViewer->setCameraYRotate(0.0f);
281 		}
282 		else if (checkSpin())
283 		{
284 			m_rotationSpeed =
285 				(TCFloat)sqrt((TCFloat)(m_lastXRotate * m_lastXRotate +
286 				m_lastYRotate * m_lastYRotate)) / 10.0f;
287 			m_modelViewer->setXRotate(m_lastXRotate);
288 			m_modelViewer->setYRotate(m_lastYRotate);
289 			m_modelViewer->setRotationSpeed(m_rotationSpeed);
290 		}
291 		m_modelViewer->setShowLightDir(false);
292 		if (m_modelViewer->getExamineMode() == LDrawModelViewer::EMLatLong)
293 		{
294 			// In latitude/longitude mode, we don't want it to spin along both
295 			// axes at once, because once the latitude gets to 90 or -90, it
296 			// just stops.
297 			if (fabs(m_modelViewer->getXRotate()) >
298 				fabs(m_modelViewer->getYRotate()))
299 			{
300 				m_modelViewer->setYRotate(0.0f);
301 			}
302 			else if (fabs(m_modelViewer->getYRotate()) >
303 				fabs(m_modelViewer->getXRotate()))
304 			{
305 				m_modelViewer->setXRotate(0.0f);
306 			}
307 			else if (fabs(m_modelViewer->getYRotate()) ==
308 				fabs(m_modelViewer->getXRotate()) &&
309 				m_modelViewer->getXRotate() != 0.0f)
310 			{
311 				m_modelViewer->setXRotate(0.0f);
312 			}
313 		}
314 		break;
315 	case MBRight:
316 		m_modelViewer->setZoomSpeed(0.0f);
317 	default:
318 		break;
319 	}
320 	TCAlertManager::sendAlert(releaseAlertClass(), this);
321 	m_modelViewer->requestRedraw();
322 	m_buttonsDown[button] = false;
323 	m_mouseMode = MMNone;
324 	return true;
325 }
326 
updateLightXY(int xPos,int yPos)327 void LDInputHandler::updateLightXY(int xPos, int yPos)
328 {
329 	m_modelViewer->mouseMoveLight(xPos - m_lastX, yPos - m_lastY);
330 	m_modelViewer->requestRedraw();
331 }
332 
updateXY(TCULong modifierKeys,int xPos,int yPos)333 void LDInputHandler::updateXY(TCULong modifierKeys, int xPos, int yPos)
334 {
335 	if (m_viewMode == VMExamine)
336 	{
337 		//m_lastMoveTime = getTimeRef();
338 		updateSpinRateXY(xPos, yPos);
339 	}
340 	else
341 	{
342 		updateHeadXY(modifierKeys, xPos, yPos);
343 	}
344 }
345 
mouseMove(TCULong modifierKeys,int x,int y)346 bool LDInputHandler::mouseMove(TCULong modifierKeys, int x, int y)
347 {
348 	bool retValue = true;
349 
350 	switch (m_mouseMode)
351 	{
352 	case MMNormal:
353 		updateXY(modifierKeys, x, y);
354 		break;
355 	case MMZoom:
356 		updateZoomY(y);
357 		break;
358 	case MMPan:
359 		updatePanXY(x, y);
360 		break;
361 	case MMLight:
362 		updateLightXY(x, y);
363 		break;
364 	default:
365 		retValue = false;
366 		break;
367 	}
368 	m_lastX = x;
369 	m_lastY = y;
370 	return retValue;
371 }
372 
mouseWheel(TCULong modifierKeys,TCFloat amount)373 bool LDInputHandler::mouseWheel(TCULong modifierKeys, TCFloat amount)
374 {
375 	// Don't process while while any mouse buttons are pressed.
376 	for (int i = 0; i < m_numButtons; i++)
377 	{
378 		if (m_buttonsDown[i])
379 		{
380 			return false;
381 		}
382 	}
383 	m_modelViewer->setClipZoom((modifierKeys & MKControl) != 0);
384 	m_modelViewer->zoom((TCFloat)amount * -0.5f);
385 	m_modelViewer->requestRedraw();
386 	return true;
387 }
388 
setMouseUpPending(bool value)389 void LDInputHandler::setMouseUpPending(bool value)
390 {
391 	m_mouseUpPending = value;
392 	m_mouseUpHandled = true;
393 }
394 
frameDone(TCAlert * alert)395 void LDInputHandler::frameDone(TCAlert *alert)
396 {
397 	if (m_mouseMode == MMNormal && m_viewMode == VMExamine &&
398 		alert->getSender() == m_modelViewer)
399 	{
400 		// We're spinning, and a frame just completed drawing, so
401 		// check to see if we should stop the spinning.
402 		m_mouseUpHandled = false;
403 		TCAlertManager::sendAlert(peekMouseUpAlertClass(), this);
404 		if (!m_mouseUpHandled ||
405 			(m_mouseUpHandled && m_mouseUpPending))
406 		{
407 			updateSpinRateXY(m_lastX, m_lastY);
408 		}
409 		m_lastFrameX = m_lastX;
410 		m_lastFrameY = m_lastY;
411 	}
412 }
413 
updateCameraMotion(TCVector & cameraMotion,TCFloat motionAmount,TCFloat strafeAmount)414 void LDInputHandler::updateCameraMotion(
415 	TCVector &cameraMotion,
416 	TCFloat motionAmount,
417 	TCFloat strafeAmount)
418 {
419 	for (int i = 0; i < 2; i++)
420 	{
421 		if (cameraMotion[i] > 0.0f)
422 		{
423 			cameraMotion[i] = strafeAmount;
424 		}
425 		else if (cameraMotion[i] < 0.0f)
426 		{
427 			cameraMotion[i] = -strafeAmount;
428 		}
429 	}
430 	if (cameraMotion[2] > 0.0f)
431 	{
432 		cameraMotion[2] = motionAmount;
433 	}
434 	else if (cameraMotion[2] < 0.0f)
435 	{
436 		cameraMotion[2] = -motionAmount;
437 	}
438 }
439 
updateCameraRotation(TCFloat rotationAmount,TCFloat rollAmount)440 void LDInputHandler::updateCameraRotation(
441 	TCFloat rotationAmount,
442 	TCFloat rollAmount)
443 {
444 	TCFloat value = m_modelViewer->getCameraXRotate();
445 
446 	if (value > 0)
447 	{
448 		m_modelViewer->setCameraXRotate(rotationAmount);
449 	}
450 	else if (value < 0)
451 	{
452 		m_modelViewer->setCameraXRotate(-rotationAmount);
453 	}
454 	value = m_modelViewer->getCameraYRotate();
455 	if (value > 0)
456 	{
457 		m_modelViewer->setCameraYRotate(rotationAmount);
458 	}
459 	else if (value < 0)
460 	{
461 		m_modelViewer->setCameraYRotate(-rotationAmount);
462 	}
463 	value = m_modelViewer->getCameraZRotate();
464 	if (value > 0)
465 	{
466 		m_modelViewer->setCameraZRotate(rollAmount);
467 	}
468 	else if (value < 0)
469 	{
470 		m_modelViewer->setCameraZRotate(-rollAmount);
471 	}
472 }
473 
keyDown(TCULong modifierKeys,KeyCode keyCode)474 bool LDInputHandler::keyDown(TCULong modifierKeys, KeyCode keyCode)
475 {
476 	if (m_viewMode == VMExamine)
477 	{
478 		TCFloat rotationSpeed = sm_keyRotationSpeed;
479 
480 		if (modifierKeys & MKShift)
481 		{
482 			rotationSpeed *= 2.0f;
483 		}
484 		switch (keyCode)
485 		{
486 		case KCUp:
487 			m_modelViewer->setXRotate(-1.0f);
488 			m_rotationSpeed = rotationSpeed;
489 			break;
490 		case KCDown:
491 			m_modelViewer->setXRotate(1.0f);
492 			m_rotationSpeed = rotationSpeed;
493 			break;
494 		case KCLeft:
495 			m_modelViewer->setYRotate(-1.0f);
496 			m_rotationSpeed = rotationSpeed;
497 			break;
498 		case KCRight:
499 			m_modelViewer->setYRotate(1.0f);
500 			m_rotationSpeed = rotationSpeed;
501 			break;
502 		case KCShift:
503 			if (fEq(m_modelViewer->getRotationSpeed(), 0.0f))
504 			{
505 				return true;
506 			}
507 			m_rotationSpeed = rotationSpeed;
508 			break;
509 		case KCSpace:
510 			stopRotation();
511 			break;
512 		default:
513 			return false;
514 		}
515 		m_modelViewer->setRotationSpeed(m_rotationSpeed);
516 		m_modelViewer->requestRedraw();
517 		return true;
518 	}
519 	else if (m_viewMode == VMFlyThrough || m_viewMode == VMWalk)
520 	{
521 		TCVector cameraMotion = m_modelViewer->getCameraMotion();
522 		TCFloat fov = m_modelViewer->getFov();
523 		TCFloat motionAmount = m_modelViewer->getDefaultDistance() / 400.0f;
524 		TCFloat rotationAmount = 0.01f * (TCFloat)tan(deg2rad(fov));
525 		TCFloat rollAmount = 0.01f;
526 		TCFloat strafeAmount = 1.0f * (TCFloat)sqrt(fov / 45.0f);
527 
528 		if (modifierKeys & MKShift)
529 		{
530 			motionAmount *= 2.0f;
531 			strafeAmount *= 2.0f;
532 			rotationAmount *= 2.0f;
533 			rollAmount *= 2.0f;
534 		}
535 		switch (keyCode)
536 		{
537 		case KCW:
538 			cameraMotion[2] = -motionAmount;
539 			break;
540 		case KCS:
541 			cameraMotion[2] = motionAmount;
542 			break;
543 		case KCA:
544 			cameraMotion[0] = -strafeAmount;
545 			break;
546 		case KCD:
547 			cameraMotion[0] = strafeAmount;
548 			break;
549 		case KCR:
550 			cameraMotion[1] = strafeAmount;
551 			break;
552 		case KCF:
553 			cameraMotion[1] = -strafeAmount;
554 			break;
555 		case KCE:
556 			m_modelViewer->setCameraZRotate(rollAmount);
557 			break;
558 		case KCQ:
559 			m_modelViewer->setCameraZRotate(-rollAmount);
560 			break;
561 		case KCUp:
562 			m_modelViewer->setCameraYRotate(rotationAmount);
563 			break;
564 		case KCDown:
565 			m_modelViewer->setCameraYRotate(-rotationAmount);
566 			break;
567 		case KCLeft:
568 			m_modelViewer->setCameraXRotate(-rotationAmount);
569 			break;
570 		case KCRight:
571 			m_modelViewer->setCameraXRotate(rotationAmount);
572 			break;
573 		case KCShift:
574 			updateCameraMotion(cameraMotion, motionAmount, strafeAmount);
575 			updateCameraRotation(rotationAmount, rollAmount);
576 			break;
577 		default:
578 			return false;
579 			break;
580 		}
581 		m_modelViewer->setCameraMotion(cameraMotion);
582 		m_modelViewer->requestRedraw();
583 		//forceRedraw(2);
584 		return true;
585 	}
586 	return false;
587 }
588 
keyUp(TCULong,KeyCode keyCode)589 bool LDInputHandler::keyUp(TCULong /*modifierKeys*/, KeyCode keyCode)
590 {
591 	if (m_viewMode == VMExamine)
592 	{
593 		switch (keyCode)
594 		{
595 		case KCUp:
596 		case KCDown:
597 			m_modelViewer->setXRotate(0.0f);
598 			break;
599 		case KCLeft:
600 		case KCRight:
601 			m_modelViewer->setYRotate(0.0f);
602 			break;
603 		case KCShift:
604 			m_rotationSpeed = sm_keyRotationSpeed;
605 			break;
606 		default:
607 			return false;
608 		}
609 		if (m_modelViewer->getXRotate() == 0.0f &&
610 			m_modelViewer->getYRotate() == 0.0f)
611 		{
612 			m_rotationSpeed = 0.0f;
613 		}
614 		m_modelViewer->setRotationSpeed(m_rotationSpeed);
615 		m_modelViewer->requestRedraw();
616 		return true;
617 	}
618 	else if (m_viewMode == VMFlyThrough || m_viewMode == VMWalk)
619 	{
620 		TCVector cameraMotion = m_modelViewer->getCameraMotion();
621 
622 		switch (keyCode)
623 		{
624 		case KCW:
625 			cameraMotion[2] = 0.0f;
626 			break;
627 		case KCS:
628 			cameraMotion[2] = 0.0f;
629 			break;
630 		case KCA:
631 			cameraMotion[0] = 0.0f;
632 			break;
633 		case KCD:
634 			cameraMotion[0] = 0.0f;
635 			break;
636 		case KCR:
637 			cameraMotion[1] = 0.0f;
638 			break;
639 		case KCF:
640 			cameraMotion[1] = 0.0f;
641 			break;
642 		case KCE:
643 			m_modelViewer->setCameraZRotate(0.0f);
644 			break;
645 		case KCQ:
646 			m_modelViewer->setCameraZRotate(0.0f);
647 			break;
648 		case KCUp:
649 			m_modelViewer->setCameraYRotate(0.0f);
650 			break;
651 		case KCDown:
652 			m_modelViewer->setCameraYRotate(0.0f);
653 			break;
654 		case KCLeft:
655 			m_modelViewer->setCameraXRotate(0.0f);
656 			break;
657 		case KCRight:
658 			m_modelViewer->setCameraXRotate(0.0f);
659 			break;
660 		case KCShift:
661 			{
662 				TCFloat fov = m_modelViewer->getFov();
663 				TCFloat motionAmount = m_modelViewer->getDefaultDistance() /
664 					400.0f;
665 				TCFloat rotationAmount = 0.01f * (TCFloat)tan(deg2rad(fov));
666 				TCFloat strafeAmount = 1.0f * (TCFloat)sqrt(fov / 45.0f);
667 
668 				updateCameraMotion(cameraMotion, motionAmount, strafeAmount);
669 				updateCameraRotation(rotationAmount, 0.01f);
670 			}
671 			break;
672 		default:
673 			return 1;
674 			break;
675 		}
676 		m_modelViewer->setCameraMotion(cameraMotion);
677 		m_modelViewer->requestRedraw();
678 		//forceRedraw(2);
679 		return 0;
680 	}
681 	return false;
682 }
683 
getAlertSender(void)684 TCObject *LDInputHandler::getAlertSender(void)
685 {
686 	return m_modelViewer;
687 }
688 
recordRotationStop(void)689 void LDInputHandler::recordRotationStop(void)
690 {
691 	if (!fEq(m_modelViewer->getXRotate(), 0.0f) ||
692 		!fEq(m_modelViewer->getYRotate(), 0.0f))
693 	{
694 		m_lastXRotate = m_modelViewer->getXRotate();
695 		m_lastYRotate = m_modelViewer->getYRotate();
696 #ifdef WIN32
697 		m_stopTicks = GetTickCount();
698 		m_haveStopTicks = true;
699 #endif // WIN32
700 #ifdef COCOA
701 		[STOP_TIME release];
702 		STOP_TIME = [[NSDate alloc] init];
703 #endif // COCOA
704 	}
705 }
706 
clearRotationStop(void)707 void LDInputHandler::clearRotationStop(void)
708 {
709 #ifdef WIN32
710 	m_haveStopTicks = false;
711 #endif // WIN32
712 #ifdef COCOA
713 	[STOP_TIME release];
714 	STOP_TIME = nil;
715 #endif // COCOA
716 }
717 
checkSpin(void)718 bool LDInputHandler::checkSpin(void)
719 {
720 	bool retValue = false;
721 #ifdef WIN32
722 	if (m_haveStopTicks)
723 	{
724 		retValue = GetTickCount() - m_stopTicks < 50;
725 		m_haveStopTicks = false;
726 	}
727 #endif // WIN32
728 #ifdef COCOA
729 	retValue = STOP_TIME != nil && [STOP_TIME timeIntervalSinceNow] > -0.1f;
730 	[STOP_TIME release];
731 	STOP_TIME = nil;
732 #endif // COCOA
733 	return retValue;
734 }
735