Revision 8d50e08d
Added by Leszek Koltunski over 5 years ago
| src/main/java/org/distorted/main/RubikSurfaceView.java | ||
|---|---|---|
| 42 | 42 |
public class RubikSurfaceView extends GLSurfaceView |
| 43 | 43 |
{
|
| 44 | 44 |
private static final int NUM_SPEED_PROBES = 10; |
| 45 |
private static final int INVALID_POINTER_ID = -1; |
|
| 45 | 46 |
|
| 46 | 47 |
public static final int MODE_ROTATE = 0; |
| 47 | 48 |
public static final int MODE_DRAG = 1; |
| ... | ... | |
| 72 | 73 |
private boolean mDragging, mBeginningRotation, mContinuingRotation; |
| 73 | 74 |
private int mScreenWidth, mScreenHeight, mScreenMin; |
| 74 | 75 |
|
| 75 |
private float mX, mY; |
|
| 76 |
private int mPtrID1, mPtrID2; |
|
| 77 |
private float mX, mY, mBegX1, mBegY1, mBegX2, mBegY2; |
|
| 76 | 78 |
private float mStartRotX, mStartRotY; |
| 77 | 79 |
private float mAxisX, mAxisY; |
| 78 | 80 |
private float mRotationFactor; |
| ... | ... | |
| 156 | 158 |
mMovement = movement; |
| 157 | 159 |
} |
| 158 | 160 |
|
| 161 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 162 |
|
|
| 163 |
private Static4D quatFromAngle(float angle) |
|
| 164 |
{
|
|
| 165 |
float cosA = (float)Math.cos(angle); |
|
| 166 |
float sinA =-(float)Math.sin(angle); |
|
| 167 |
|
|
| 168 |
return new Static4D(0, 0, sinA, cosA); |
|
| 169 |
} |
|
| 170 |
|
|
| 159 | 171 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 160 | 172 |
|
| 161 | 173 |
private Static4D quatFromDrag(float dragX, float dragY) |
| ... | ... | |
| 383 | 395 |
|
| 384 | 396 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 385 | 397 |
|
| 386 |
private void actionDown(float x, float y)
|
|
| 398 |
private void dragging(float x, float y)
|
|
| 387 | 399 |
{
|
| 388 |
mX = x; |
|
| 389 |
mY = y; |
|
| 390 |
setUpDragOrRotate(true,x,y); |
|
| 400 |
mTempCurrent.set(quatFromDrag(mX-x,y-mY)); |
|
| 401 |
mPreRender.setQuatCurrentOnNextRender(); |
|
| 402 |
|
|
| 403 |
if( retFingerDragDistanceInInches(mX,mY,x,y) > DIRECTION_SENSITIVITY ) |
|
| 404 |
{
|
|
| 405 |
mX = x; |
|
| 406 |
mY = y; |
|
| 407 |
mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); |
|
| 408 |
mTempCurrent.set(0f, 0f, 0f, 1f); |
|
| 409 |
mPreRender.setQuatCurrentOnNextRender(); |
|
| 410 |
mPreRender.setQuatAccumulatedOnNextRender(); |
|
| 411 |
} |
|
| 391 | 412 |
} |
| 392 | 413 |
|
| 393 | 414 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 394 | 415 |
|
| 395 |
private void actionMove(float x, float y)
|
|
| 416 |
private void continuingRotation(float x, float y)
|
|
| 396 | 417 |
{
|
| 397 |
if( mBeginningRotation ) |
|
| 398 |
{
|
|
| 399 |
if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY ) |
|
| 400 |
{
|
|
| 401 |
mStartRotX = x; |
|
| 402 |
mStartRotY = y; |
|
| 403 |
|
|
| 404 |
Static4D touchPoint2 = new Static4D(x, y, 0, 0); |
|
| 405 |
Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated); |
|
| 418 |
float angle = continueRotation(x-mStartRotX,y-mStartRotY); |
|
| 419 |
mCurrentAngle = SWIPING_SENSITIVITY*angle; |
|
| 420 |
mPreRender.getObject().continueRotation(mCurrentAngle); |
|
| 406 | 421 |
|
| 407 |
Static2D res = mMovement.newRotation(rotatedTouchPoint2);
|
|
| 408 |
RubikObject object = mPreRender.getObject();
|
|
| 422 |
addSpeedProbe(x,y);
|
|
| 423 |
}
|
|
| 409 | 424 |
|
| 410 |
mCurrentAxis = (int)res.get0(); |
|
| 411 |
float offset = res.get1(); |
|
| 412 |
mCurrentRow = (int)(object.returnMultiplier()*offset); |
|
| 413 |
computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] ); |
|
| 414 |
mRotationFactor = object.returnRotationFactor(offset); |
|
| 425 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 415 | 426 |
|
| 416 |
object.beginNewRotation( mCurrentAxis, mCurrentRow ); |
|
| 427 |
private void beginningRotation(float x, float y) |
|
| 428 |
{
|
|
| 429 |
mStartRotX = x; |
|
| 430 |
mStartRotY = y; |
|
| 417 | 431 |
|
| 418 |
if( RubikState.getCurrentState()==RubikState.READ ) |
|
| 419 |
{
|
|
| 420 |
RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); |
|
| 421 |
solving.resetElapsed(); |
|
| 432 |
Static4D touchPoint2 = new Static4D(x, y, 0, 0); |
|
| 433 |
Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated); |
|
| 422 | 434 |
|
| 423 |
final RubikActivity act = (RubikActivity)getContext(); |
|
| 435 |
Static2D res = mMovement.newRotation(rotatedTouchPoint2); |
|
| 436 |
RubikObject object = mPreRender.getObject(); |
|
| 424 | 437 |
|
| 425 |
act.runOnUiThread(new Runnable() |
|
| 426 |
{
|
|
| 427 |
@Override |
|
| 428 |
public void run() |
|
| 429 |
{
|
|
| 430 |
RubikState.switchState( act, RubikState.SOLV); |
|
| 431 |
} |
|
| 432 |
}); |
|
| 433 |
} |
|
| 438 |
mCurrentAxis = (int)res.get0(); |
|
| 439 |
float offset = res.get1(); |
|
| 440 |
mCurrentRow = (int)(object.returnMultiplier()*offset); |
|
| 441 |
computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] ); |
|
| 442 |
mRotationFactor = object.returnRotationFactor(offset); |
|
| 434 | 443 |
|
| 435 |
addSpeedProbe(x,y);
|
|
| 444 |
object.beginNewRotation( mCurrentAxis, mCurrentRow );
|
|
| 436 | 445 |
|
| 437 |
mBeginningRotation = false; |
|
| 438 |
mContinuingRotation= true; |
|
| 439 |
} |
|
| 440 |
} |
|
| 441 |
else if( mContinuingRotation ) |
|
| 446 |
if( RubikState.getCurrentState()==RubikState.READ ) |
|
| 442 | 447 |
{
|
| 443 |
float angle = continueRotation(x-mStartRotX,y-mStartRotY); |
|
| 444 |
mCurrentAngle = SWIPING_SENSITIVITY*angle; |
|
| 445 |
mPreRender.getObject().continueRotation(mCurrentAngle); |
|
| 448 |
RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); |
|
| 449 |
solving.resetElapsed(); |
|
| 450 |
|
|
| 451 |
final RubikActivity act = (RubikActivity)getContext(); |
|
| 446 | 452 |
|
| 447 |
addSpeedProbe(x,y); |
|
| 453 |
act.runOnUiThread(new Runnable() |
|
| 454 |
{
|
|
| 455 |
@Override |
|
| 456 |
public void run() |
|
| 457 |
{
|
|
| 458 |
RubikState.switchState( act, RubikState.SOLV); |
|
| 459 |
} |
|
| 460 |
}); |
|
| 448 | 461 |
} |
| 449 |
else if( mDragging ) |
|
| 462 |
|
|
| 463 |
addSpeedProbe(x,y); |
|
| 464 |
|
|
| 465 |
mBeginningRotation = false; |
|
| 466 |
mContinuingRotation= true; |
|
| 467 |
} |
|
| 468 |
|
|
| 469 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 470 |
|
|
| 471 |
private void actionMove(MotionEvent event) |
|
| 472 |
{
|
|
| 473 |
if( mPtrID2 == INVALID_POINTER_ID ) |
|
| 450 | 474 |
{
|
| 451 |
mTempCurrent.set(quatFromDrag(mX-x,y-mY));
|
|
| 452 |
mPreRender.setQuatCurrentOnNextRender();
|
|
| 475 |
float x = (event.getX() - mScreenWidth*0.5f)/mScreenMin;
|
|
| 476 |
float y = (mScreenHeight*0.5f -event.getY())/mScreenMin;
|
|
| 453 | 477 |
|
| 454 |
if( retFingerDragDistanceInInches(mX,mY,x,y) > DIRECTION_SENSITIVITY )
|
|
| 478 |
if( mBeginningRotation )
|
|
| 455 | 479 |
{
|
| 456 |
mX = x; |
|
| 457 |
mY = y; |
|
| 458 |
mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); |
|
| 459 |
mTempCurrent.set(0f, 0f, 0f, 1f); |
|
| 460 |
mPreRender.setQuatCurrentOnNextRender(); |
|
| 461 |
mPreRender.setQuatAccumulatedOnNextRender(); |
|
| 480 |
if( retFingerDragDistanceInInches(mX,mY,x,y) > ROTATION_SENSITIVITY ) |
|
| 481 |
{
|
|
| 482 |
beginningRotation(x,y); |
|
| 483 |
} |
|
| 484 |
} |
|
| 485 |
else if( mContinuingRotation ) |
|
| 486 |
{
|
|
| 487 |
continuingRotation(x,y); |
|
| 488 |
} |
|
| 489 |
else if( mDragging ) |
|
| 490 |
{
|
|
| 491 |
dragging(x,y); |
|
| 492 |
} |
|
| 493 |
else |
|
| 494 |
{
|
|
| 495 |
setUpDragOrRotate(false,x,y); |
|
| 462 | 496 |
} |
| 463 | 497 |
} |
| 464 | 498 |
else |
| 465 | 499 |
{
|
| 466 |
setUpDragOrRotate(false,x,y); |
|
| 500 |
int index1 = event.findPointerIndex(mPtrID1); |
|
| 501 |
int index2 = event.findPointerIndex(mPtrID2); |
|
| 502 |
|
|
| 503 |
float nX1 = event.getX(index1); |
|
| 504 |
float nY1 = event.getY(index1); |
|
| 505 |
float nX2 = event.getX(index2); |
|
| 506 |
float nY2 = event.getY(index2); |
|
| 507 |
|
|
| 508 |
float angle1 = (float) Math.atan2(mBegY1-mBegY2, mBegX1-mBegX2); |
|
| 509 |
float angle2 = (float) Math.atan2( nY1-nY2 , nX1-nX2 ); |
|
| 510 |
|
|
| 511 |
mTempCurrent.set(quatFromAngle(angle1-angle2)); |
|
| 512 |
mPreRender.setQuatCurrentOnNextRender(); |
|
| 467 | 513 |
} |
| 468 | 514 |
} |
| 469 | 515 |
|
| 516 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 517 |
|
|
| 518 |
private void actionDown(MotionEvent event) |
|
| 519 |
{
|
|
| 520 |
mPtrID1 = event.getPointerId(0); |
|
| 521 |
|
|
| 522 |
mX = (event.getX() - mScreenWidth*0.5f)/mScreenMin; |
|
| 523 |
mY = (mScreenHeight*0.5f -event.getY())/mScreenMin; |
|
| 524 |
|
|
| 525 |
setUpDragOrRotate(true,mX,mY); |
|
| 526 |
} |
|
| 527 |
|
|
| 470 | 528 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 471 | 529 |
|
| 472 | 530 |
private void actionUp() |
| 473 | 531 |
{
|
| 532 |
mPtrID1 = INVALID_POINTER_ID; |
|
| 533 |
|
|
| 474 | 534 |
if( mDragging ) |
| 475 | 535 |
{
|
| 476 | 536 |
mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); |
| ... | ... | |
| 498 | 558 |
} |
| 499 | 559 |
} |
| 500 | 560 |
|
| 561 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 562 |
|
|
| 563 |
private void actionDown2(MotionEvent event) |
|
| 564 |
{
|
|
| 565 |
mPtrID2 = event.getPointerId(event.getActionIndex()); |
|
| 566 |
|
|
| 567 |
int index1 = event.findPointerIndex(mPtrID1); |
|
| 568 |
mBegX1 = event.getX(index1); |
|
| 569 |
mBegY1 = event.getY(index1); |
|
| 570 |
|
|
| 571 |
mX = (mBegX1 - mScreenWidth*0.5f)/mScreenMin; |
|
| 572 |
mY = (mScreenHeight*0.5f -mBegY1)/mScreenMin; |
|
| 573 |
|
|
| 574 |
int index2 = event.findPointerIndex(mPtrID2); |
|
| 575 |
mBegX2 = event.getX(index2); |
|
| 576 |
mBegY2 = event.getY(index2); |
|
| 577 |
} |
|
| 578 |
|
|
| 579 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 580 |
|
|
| 581 |
private void actionUp2() |
|
| 582 |
{
|
|
| 583 |
mPtrID2 = INVALID_POINTER_ID; |
|
| 584 |
} |
|
| 585 |
|
|
| 501 | 586 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 502 | 587 |
// PUBLIC API |
| 503 | 588 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 517 | 602 |
mFirstIndex =0; |
| 518 | 603 |
mLastIndex =0; |
| 519 | 604 |
|
| 605 |
mPtrID1 = INVALID_POINTER_ID; |
|
| 606 |
mPtrID2 = INVALID_POINTER_ID; |
|
| 607 |
|
|
| 520 | 608 |
mRenderer = new RubikRenderer(this); |
| 521 | 609 |
mPreRender = new RubikPreRender(this); |
| 522 | 610 |
|
| ... | ... | |
| 542 | 630 |
@Override |
| 543 | 631 |
public boolean onTouchEvent(MotionEvent event) |
| 544 | 632 |
{
|
| 545 |
int action = event.getAction(); |
|
| 546 |
float x = (event.getX() - mScreenWidth*0.5f)/mScreenMin; |
|
| 547 |
float y = (mScreenHeight*0.5f -event.getY())/mScreenMin; |
|
| 633 |
int action = event.getActionMasked(); |
|
| 548 | 634 |
|
| 549 | 635 |
switch(action) |
| 550 | 636 |
{
|
| 551 |
case MotionEvent.ACTION_DOWN: actionDown(x,y); break; |
|
| 552 |
case MotionEvent.ACTION_MOVE: actionMove(x,y); break; |
|
| 553 |
case MotionEvent.ACTION_UP : actionUp() ; break; |
|
| 637 |
case MotionEvent.ACTION_DOWN : actionDown(event) ; break; |
|
| 638 |
case MotionEvent.ACTION_MOVE : actionMove(event) ; break; |
|
| 639 |
case MotionEvent.ACTION_UP : actionUp() ; break; |
|
| 640 |
case MotionEvent.ACTION_POINTER_DOWN: actionDown2(event); break; |
|
| 641 |
case MotionEvent.ACTION_POINTER_UP : actionUp2() ; break; |
|
| 554 | 642 |
} |
| 555 | 643 |
|
| 556 | 644 |
return true; |
Also available in: Unified diff
Initial attempt at two-finger rotation.
Mostly works; still, one corner case doesnt:
- put two fingers down, start rotating
- lift one of them up
- put it back down
depending if we lifted the first or second finger, weird things may happen.