Revision f0533889
Added by Leszek Koltunski over 5 years ago
| src/main/java/org/distorted/main/RubikSurfaceView.java | ||
|---|---|---|
| 180 | 180 | return new Static4D(0f, 0f, 0f, 1f); | 
| 181 | 181 | } | 
| 182 | 182 |  | 
| 183 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 184 |  | |
| 185 | private void setUpDragOrRotate(boolean down, float x, float y) | |
| 186 |       {
 | |
| 187 | int mode = RubikState.getMode(); | |
| 188 |  | |
| 189 | if( mode==MODE_DRAG ) | |
| 190 |         {
 | |
| 191 | mDragging = true; | |
| 192 | mBeginningRotation = false; | |
| 193 | mContinuingRotation = false; | |
| 194 | } | |
| 195 | else | |
| 196 |         {
 | |
| 197 | Static4D touchPoint1 = new Static4D(x, y, 0, 0); | |
| 198 | Static4D rotatedTouchPoint1= rotateVectorByInvertedQuat(touchPoint1, mQuatAccumulated); | |
| 199 | Static4D rotatedCamera= rotateVectorByInvertedQuat(CAMERA_POINT, mQuatAccumulated); | |
| 200 |  | |
| 201 | if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint1,rotatedCamera) ) | |
| 202 |           {
 | |
| 203 | mDragging = false; | |
| 204 | mContinuingRotation = false; | |
| 205 |  | |
| 206 | if( mode==MODE_ROTATE ) | |
| 207 |             {
 | |
| 208 | mBeginningRotation= mPreRender.canRotate(); | |
| 209 | } | |
| 210 | else if( mode==MODE_REPLACE ) | |
| 211 |             {
 | |
| 212 | mBeginningRotation= false; | |
| 213 |  | |
| 214 | if( down ) | |
| 215 |               {
 | |
| 216 | RubikStateSolver solver = (RubikStateSolver) RubikState.SVER.getStateClass(); | |
| 217 | mLastCubitFace = mMovement.getTouchedFace(); | |
| 218 | float[] point = mMovement.getTouchedPoint3D(); | |
| 219 | int color = solver.getCurrentColor(); | |
| 220 | RubikObject object = mPreRender.getObject(); | |
| 221 | mLastCubit = object.getCubit(point); | |
| 222 | mPreRender.setTextureMap( mLastCubit, mLastCubitFace, color ); | |
| 223 | mLastCubitColor = SolverMain.cubitIsLocked(object.getObjectList(), object.getSize(), mLastCubit); | |
| 224 | } | |
| 225 | } | |
| 226 | } | |
| 227 | else | |
| 228 |           {
 | |
| 229 | mDragging = true; | |
| 230 | mBeginningRotation = false; | |
| 231 | mContinuingRotation = false; | |
| 232 | } | |
| 233 | } | |
| 234 | } | |
| 235 |  | |
| 236 | 183 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
| 237 | 184 | // cast the 3D axis we are currently rotating along to the 2D in-screen-surface axis | 
| 238 | 185 |  | 
| ... | ... | |
| 363 | 310 | mCurrRotSpeed = timeDiff>0 ? (lastAngle-firstAngle)/timeDiff : 0; | 
| 364 | 311 | } | 
| 365 | 312 |  | 
| 313 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 314 |  | |
| 315 | private boolean canBeginRotate(float x, float y) | |
| 316 |       {
 | |
| 317 | return (mX-x)*(mX-x) + (mY-y)*(mY-y) > 1.0f/(ROTATION_SENSITIVITY*ROTATION_SENSITIVITY); | |
| 318 | } | |
| 319 |  | |
| 320 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 321 |  | |
| 322 | private boolean shouldChangeDirection(float x, float y) | |
| 323 |       {
 | |
| 324 | return (mX-x)*(mX-x) + (mY-y)*(mY-y) > 1.0f/(DIRECTION_SENSITIVITY*DIRECTION_SENSITIVITY); | |
| 325 | } | |
| 326 |  | |
| 327 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 328 |  | |
| 329 | private void setUpDragOrRotate(boolean down, float x, float y) | |
| 330 |       {
 | |
| 331 | int mode = RubikState.getMode(); | |
| 332 |  | |
| 333 | if( mode==MODE_DRAG ) | |
| 334 |         {
 | |
| 335 | mDragging = true; | |
| 336 | mBeginningRotation = false; | |
| 337 | mContinuingRotation = false; | |
| 338 | } | |
| 339 | else | |
| 340 |         {
 | |
| 341 | Static4D touchPoint1 = new Static4D(x, y, 0, 0); | |
| 342 | Static4D rotatedTouchPoint1= rotateVectorByInvertedQuat(touchPoint1, mQuatAccumulated); | |
| 343 | Static4D rotatedCamera= rotateVectorByInvertedQuat(CAMERA_POINT, mQuatAccumulated); | |
| 344 |  | |
| 345 | if( mMovement!=null && mMovement.faceTouched(rotatedTouchPoint1,rotatedCamera) ) | |
| 346 |           {
 | |
| 347 | mDragging = false; | |
| 348 | mContinuingRotation = false; | |
| 349 |  | |
| 350 | if( mode==MODE_ROTATE ) | |
| 351 |             {
 | |
| 352 | mBeginningRotation= mPreRender.canRotate(); | |
| 353 | } | |
| 354 | else if( mode==MODE_REPLACE ) | |
| 355 |             {
 | |
| 356 | mBeginningRotation= false; | |
| 357 |  | |
| 358 | if( down ) | |
| 359 |               {
 | |
| 360 | RubikStateSolver solver = (RubikStateSolver) RubikState.SVER.getStateClass(); | |
| 361 | mLastCubitFace = mMovement.getTouchedFace(); | |
| 362 | float[] point = mMovement.getTouchedPoint3D(); | |
| 363 | int color = solver.getCurrentColor(); | |
| 364 | RubikObject object = mPreRender.getObject(); | |
| 365 | mLastCubit = object.getCubit(point); | |
| 366 | mPreRender.setTextureMap( mLastCubit, mLastCubitFace, color ); | |
| 367 | mLastCubitColor = SolverMain.cubitIsLocked(object.getObjectList(), object.getSize(), mLastCubit); | |
| 368 | } | |
| 369 | } | |
| 370 | } | |
| 371 | else | |
| 372 |           {
 | |
| 373 | mDragging = true; | |
| 374 | mBeginningRotation = false; | |
| 375 | mContinuingRotation = false; | |
| 376 | } | |
| 377 | } | |
| 378 | } | |
| 379 |  | |
| 380 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 381 |  | |
| 382 | private void actionDown(float x, float y) | |
| 383 |       {
 | |
| 384 | mX = x; | |
| 385 | mY = y; | |
| 386 | setUpDragOrRotate(true,x,y); | |
| 387 | } | |
| 388 |  | |
| 389 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 390 |  | |
| 391 | private void actionMove(float x, float y) | |
| 392 |       {
 | |
| 393 | if( mBeginningRotation ) | |
| 394 |         {
 | |
| 395 | if( canBeginRotate(x,y) ) | |
| 396 |           {
 | |
| 397 | mStartRotX = x; | |
| 398 | mStartRotY = y; | |
| 399 |  | |
| 400 | Static4D touchPoint2 = new Static4D(x, y, 0, 0); | |
| 401 | Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated); | |
| 402 |  | |
| 403 | Static2D res = mMovement.newRotation(rotatedTouchPoint2); | |
| 404 | RubikObject object = mPreRender.getObject(); | |
| 405 |  | |
| 406 | mCurrentAxis = (int)res.get0(); | |
| 407 | float offset = res.get1(); | |
| 408 | mCurrentRow = (int)(object.returnMultiplier()*offset); | |
| 409 | computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] ); | |
| 410 | mRotationFactor = object.returnRotationFactor(offset); | |
| 411 |  | |
| 412 | object.beginNewRotation( mCurrentAxis, mCurrentRow ); | |
| 413 |  | |
| 414 | if( RubikState.getCurrentState()==RubikState.READ ) | |
| 415 |             {
 | |
| 416 | RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); | |
| 417 | solving.resetElapsed(); | |
| 418 |  | |
| 419 | final RubikActivity act = (RubikActivity)getContext(); | |
| 420 |  | |
| 421 | act.runOnUiThread(new Runnable() | |
| 422 |               {
 | |
| 423 | @Override | |
| 424 | public void run() | |
| 425 |                 {
 | |
| 426 | RubikState.switchState( act, RubikState.SOLV); | |
| 427 | } | |
| 428 | }); | |
| 429 | } | |
| 430 |  | |
| 431 | addSpeedProbe(0.0f); | |
| 432 |  | |
| 433 | mBeginningRotation = false; | |
| 434 | mContinuingRotation= true; | |
| 435 | } | |
| 436 | } | |
| 437 | else if( mContinuingRotation ) | |
| 438 |         {
 | |
| 439 | float angle = continueRotation(x-mStartRotX,y-mStartRotY); | |
| 440 | mCurrentAngle = SWIPING_SENSITIVITY*angle; | |
| 441 | mPreRender.getObject().continueRotation(mCurrentAngle); | |
| 442 |  | |
| 443 | addSpeedProbe(mCurrentAngle); | |
| 444 | } | |
| 445 | else if( mDragging ) | |
| 446 |         {
 | |
| 447 | mTempCurrent.set(quatFromDrag(mX-x,y-mY)); | |
| 448 | mPreRender.setQuatCurrentOnNextRender(); | |
| 449 |  | |
| 450 | if( shouldChangeDirection(x,y) ) | |
| 451 |           {
 | |
| 452 | mX = x; | |
| 453 | mY = y; | |
| 454 | mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); | |
| 455 | mTempCurrent.set(0f, 0f, 0f, 1f); | |
| 456 | mPreRender.setQuatCurrentOnNextRender(); | |
| 457 | mPreRender.setQuatAccumulatedOnNextRender(); | |
| 458 | } | |
| 459 | } | |
| 460 | else | |
| 461 |         {
 | |
| 462 | setUpDragOrRotate(false,x,y); | |
| 463 | } | |
| 464 | } | |
| 465 |  | |
| 466 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 467 |  | |
| 468 | private void actionUp() | |
| 469 |       {
 | |
| 470 | if( mDragging ) | |
| 471 |         {
 | |
| 472 | mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); | |
| 473 | mTempCurrent.set(0f, 0f, 0f, 1f); | |
| 474 | mPreRender.setQuatCurrentOnNextRender(); | |
| 475 | mPreRender.setQuatAccumulatedOnNextRender(); | |
| 476 | } | |
| 477 |  | |
| 478 | if( mContinuingRotation ) | |
| 479 |         {
 | |
| 480 | computeCurrentSpeed(); | |
| 481 | int angle = mPreRender.getObject().computeNearestAngle(mCurrentAngle, mCurrRotSpeed); | |
| 482 | mPreRender.finishRotation(angle); | |
| 483 |  | |
| 484 | if( RubikState.getCurrentState()==RubikState.SOLV && angle!=0 ) | |
| 485 |           {
 | |
| 486 | RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); | |
| 487 | solving.addMove(mCurrentAxis, mCurrentRow, angle); | |
| 488 | } | |
| 489 | } | |
| 490 |  | |
| 491 | if( mLastCubitColor>=0 ) | |
| 492 |         {
 | |
| 493 | mPreRender.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor ); | |
| 494 | } | |
| 495 | } | |
| 496 |  | |
| 366 | 497 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
| 367 | 498 | // PUBLIC API | 
| 368 | 499 | /////////////////////////////////////////////////////////////////////////////////////////////////// | 
| ... | ... | |
| 402 | 533 |  | 
| 403 | 534 | switch(action) | 
| 404 | 535 |          {
 | 
| 405 | case MotionEvent.ACTION_DOWN: mX = x; | |
| 406 | mY = y; | |
| 407 | setUpDragOrRotate(true,x,y); | |
| 408 | break; | |
| 409 | case MotionEvent.ACTION_MOVE: if( mBeginningRotation ) | |
| 410 |                                          {
 | |
| 411 | if( (mX-x)*(mX-x)+(mY-y)*(mY-y) > 1.0f/(ROTATION_SENSITIVITY*ROTATION_SENSITIVITY) ) | |
| 412 |                                            {
 | |
| 413 | mStartRotX = x; | |
| 414 | mStartRotY = y; | |
| 415 |  | |
| 416 | Static4D touchPoint2 = new Static4D(x, y, 0, 0); | |
| 417 | Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated); | |
| 418 |  | |
| 419 | Static2D res = mMovement.newRotation(rotatedTouchPoint2); | |
| 420 | RubikObject object = mPreRender.getObject(); | |
| 421 |  | |
| 422 | mCurrentAxis = (int)res.get0(); | |
| 423 | float offset = res.get1(); | |
| 424 | mCurrentRow = (int)(object.returnMultiplier()*offset); | |
| 425 | computeCurrentAxis( object.getRotationAxis()[mCurrentAxis] ); | |
| 426 | mRotationFactor = object.returnRotationFactor(offset); | |
| 427 |  | |
| 428 | object.beginNewRotation( mCurrentAxis, mCurrentRow ); | |
| 429 |  | |
| 430 | if( RubikState.getCurrentState()==RubikState.READ ) | |
| 431 |                                              {
 | |
| 432 | RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); | |
| 433 | solving.resetElapsed(); | |
| 434 |  | |
| 435 | final RubikActivity act = (RubikActivity)getContext(); | |
| 436 |  | |
| 437 | act.runOnUiThread(new Runnable() | |
| 438 |                                                {
 | |
| 439 | @Override | |
| 440 | public void run() | |
| 441 |                                                  {
 | |
| 442 | RubikState.switchState( act, RubikState.SOLV); | |
| 443 | } | |
| 444 | }); | |
| 445 | } | |
| 446 |  | |
| 447 | addSpeedProbe(0.0f); | |
| 448 |  | |
| 449 | mBeginningRotation = false; | |
| 450 | mContinuingRotation= true; | |
| 451 | } | |
| 452 | } | |
| 453 | else if( mContinuingRotation ) | |
| 454 |                                          {
 | |
| 455 | float angle = continueRotation(x-mStartRotX,y-mStartRotY); | |
| 456 | mCurrentAngle = SWIPING_SENSITIVITY*angle; | |
| 457 | mPreRender.getObject().continueRotation(mCurrentAngle); | |
| 458 |  | |
| 459 | addSpeedProbe(mCurrentAngle); | |
| 460 | } | |
| 461 | else if( mDragging ) | |
| 462 |                                          {
 | |
| 463 | mTempCurrent.set(quatFromDrag(mX-x,y-mY)); | |
| 464 | mPreRender.setQuatCurrentOnNextRender(); | |
| 465 |  | |
| 466 | if( (mX-x)*(mX-x) + (mY-y)*(mY-y) > 1.0f/(DIRECTION_SENSITIVITY*DIRECTION_SENSITIVITY) ) | |
| 467 |                                            {
 | |
| 468 | mX = x; | |
| 469 | mY = y; | |
| 470 | mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); | |
| 471 | mTempCurrent.set(0f, 0f, 0f, 1f); | |
| 472 | mPreRender.setQuatCurrentOnNextRender(); | |
| 473 | mPreRender.setQuatAccumulatedOnNextRender(); | |
| 474 | } | |
| 475 | } | |
| 476 | else | |
| 477 |                                          {
 | |
| 478 | setUpDragOrRotate(false,x,y); | |
| 479 | } | |
| 480 | break; | |
| 481 | case MotionEvent.ACTION_UP : if( mDragging ) | |
| 482 |                                          {
 | |
| 483 | mTempAccumulated.set(quatMultiply(mQuatCurrent, mQuatAccumulated)); | |
| 484 | mTempCurrent.set(0f, 0f, 0f, 1f); | |
| 485 | mPreRender.setQuatCurrentOnNextRender(); | |
| 486 | mPreRender.setQuatAccumulatedOnNextRender(); | |
| 487 | } | |
| 488 |  | |
| 489 | if( mContinuingRotation ) | |
| 490 |                                          {
 | |
| 491 | computeCurrentSpeed(); | |
| 492 | int angle = mPreRender.getObject().computeNearestAngle(mCurrentAngle, mCurrRotSpeed); | |
| 493 | mPreRender.finishRotation(angle); | |
| 494 |  | |
| 495 | if( RubikState.getCurrentState()==RubikState.SOLV ) | |
| 496 |                                            {
 | |
| 497 | RubikStateSolving solving = (RubikStateSolving)RubikState.SOLV.getStateClass(); | |
| 498 |  | |
| 499 | if( angle!=0 ) | |
| 500 | solving.addMove(mCurrentAxis, mCurrentRow, angle); | |
| 501 | } | |
| 502 | } | |
| 503 | if( mLastCubitColor>=0 ) | |
| 504 |                                          {
 | |
| 505 | mPreRender.setTextureMap( mLastCubit, mLastCubitFace, mLastCubitColor ); | |
| 506 | } | |
| 507 | break; | |
| 536 | case MotionEvent.ACTION_DOWN: actionDown(x,y); break; | |
| 537 | case MotionEvent.ACTION_MOVE: actionMove(x,y); break; | |
| 538 | case MotionEvent.ACTION_UP : actionUp() ; break; | |
| 508 | 539 | } | 
| 509 | 540 |  | 
| 510 | 541 | return true; | 
Also available in: Unified diff
Split up the onTouch() part of the View.