MCPcopy Index your code
hub / github.com/cjurjiu/AnimCubeAndroid

github.com/cjurjiu/AnimCubeAndroid @1.0.3

Chat with this repo
repository ↗ · DeepWiki ↗ · release 1.0.3 ↗ · + Follow
192 symbols 470 edges 8 files 63 documented · 33%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

AnimCube for Android Download License

An Android port (with added features) of Josef Jelinek's AnimCube Java Web applet.

Animating moves towards a solution Touch interactions

Table of contents

Usage

Add the cube to your view hierarchy:

<com.catalinjurjiu.animcubeandroid.AnimCube
     android:id="@+id/animcube"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     cube:backFacesDistance="4"/>

And you'll get:

No back faces With back faces

Animating moves

To start an animation, first you need to define the move sequence. This can be either either through XML:

<com.catalinjurjiu.animcubeandroid.AnimCube
     android:id="@+id/animcube"
     android:layout_width="match_parent"
     android:layout_height="match_parent"     
     cube:backFacesDistance="4"
     cube:moves="R2' U M U' R2' U M' U'"/>

Or from code:

AnimCube animCube = findViewById(R.id.animcube);
animCube.setMoveSequence("R2' U M U' R2' U M' U'");

Then, tell the cube to perform the specified moves:

animCube.animateMoveSequence();
//or animate it in reverse, from the end and with opposite twisting direction
animCube.animateMoveSequenceReversed(); 

Or you can animate only one move at a time:

animCube.animateMove();
//or in reverse
animCube.animateMoveReversed();

To stop an animation prematurely, use stopAnimation:

animCube.stopAnimation();

As a side effect, stopAnimation instantly the applies the move it interrupted.

You can also just apply a move sequence, or an individual move, without an animation:

animCube.applyMoveSequence();
//individual move
animCube.applyMove();

Both apply methods also have reverse equivalents.

Custom colors

If the default colors don't play nicely with your theme's color palette, or if you just don't fancy them, custom ones can be specified through XML.

To do so, just define your 6 custom colors as a XML color array, in arrays.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="custom_cube_colors">
        <item>#ce3232</item>
        <item>#ffa239</item>
        <item>#737581</item>
        <item>#e7dc00</item>
        <item>#01641c</item>
        <item>#141291</item>
    </array>
</resources>    

Then apply them on the cube through XML:

<com.catalinjurjiu.animcubeandroid.AnimCube
    android:id="@+id/animcube"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    cube:backFacesDistance="4"
    cube:backgroundColor="#3A393A"
    cube:cubeColors="@array/custom_cube_colors"
    cube:faceletsContourColor="#ffffff"/>

As it can be seen, the background color & the contour of the facelets can also be customized. This yields:

Saving the state

When a configuration change occurs, the cube knows how to save its state, but it needs to be told to do so. This will likely be change to happen automatically in the future.

For now however, ensuring the cube saves its state is relatively simple. Just add the following to your Activity/Fragment:

public class MainActivity extends Activity {
    public static final String ANIM_CUBE_SAVE_STATE_BUNDLE_ID = "animCube";
    private AnimCube animCube;
    ...

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBundle(ANIM_CUBE_SAVE_STATE_BUNDLE_ID, animCube.saveState());
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        animCube.restoreState(savedInstanceState.getBundle(ANIM_CUBE_SAVE_STATE_BUNDLE_ID));
    }
}

Event listeners

Animation events

To be notified whenever an animation is finished, you can register an OnCubeAnimationFinishedListener. This makes AnimCube call onAnimationFinished every time a call to animate, or apply for one or move moves has finished making its changes.

Note: When animating/applying a move sequence (i.e. not individual moves) onAnimationFinished is only called when the end of the move sequence is reached, or when stopAnimation is called. It is not called for every move in the sequence.

Cube changed events

All the animate/apply calls change the underlying cube model. Additionally, this can also happen when the cube is editable and the user manually twists a layer.

To be notified when the cube model is changed, use an OnCubeModelUpdatedListener. This also allows you to be notified when each move is applied, when animating a move sequence, since the OnCubeAnimationFinishedListener is only notified when the whole sequence has finished animating.

Note: The set OnCubeModelUpdatedListener is also notified for each move in a move sequence, when it is applied with AnimCube#applyMoveSequence & AnimCube#applyMoveSequenceReversed. This happens because, although to the user the whole move sequence seems to be applied instantly, internally the moves are applied one by one, and rendering occurrs only at the end.

Debuggable mode

TL;DR: Always use AnimCube.java, only use AnimCubeDebuggable.java when you need detailed logs to file an issue.

Long version:

Currently the library contains two classes: AnimCube.java & AnimCubeDebug.java. In terms of behavior they are equivalent, and generally you should only ever use AnimCube.java. Strictly speaking though, when it comes to the debug mode, their behavior differs.

When debug mode is on, AnimCube.java prints some warnings, if they happen. With debug mode off, the warnings are omitted and nothing else happens.

On the other hand, AnimCubeDebug.java prints a plethora of debug & info messages to LogCat when debug mode is on, and prints nothing when it's off.

The decision to have two different classes was not an easy one. Internally, both classes rely on utility methods to decide whether to print a certain message or not. However, even if in the end logging to logcat doesn't happen, the string message is still allocated. An alternative would've been to check the condition before allocating the string, but then the code itself would be polluted with tons of conditional checks.

By removing all debug & info logs from AnimCube.java, memory is not polluted with strings that never get printed when debug mode is off. Yet, all the debug messages can still be obtained if AnimCube is swapped with AnimCubeDebug when attempting to reproduce an issue.

To turn debug mode on from code, use AnimCube#setDebuggable(boolean). To enable it from XML, use the debuggable attribute:

<com.catalinjurjiu.animcubeandroid.AnimCube
    android:id="@+id/animcube"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    cube:debuggable="true"/>

By default, debug mode is disabled.

Parameters available in XML

Many of the original parameters have been kept with equivalent behavior. However, certain names were changed.

This section describes just the configuration params supported by AnimCube-Android, however if you are interested in an actual changelog between the list of parameters provided by the original and this version, see the Changelog from original AnimCube.

Parameters list: * backgroundColor * cubeColors * faceletContourColor * initialState * moves * editable * backFacesDistance * touchSensitivity * initialRotation * perspective * scale * singleRotationSpeed * doubleRotationSpeed * verticalAlign * debuggable

backgroundColor - color | reference

Specifies the background color of the cube view.

cubeColors - reference

Specifies 6 custom colors to be used by the cube, instead of the default colors. Must be an array defined in XML.

faceletContourColor - color | reference

Specifies the color of the region between cube facelets.

initialState - string | reference

Specifies the initial state of the cube. Needs to contain an array of exactly 54 color indexes. Valid indexes are in the range [0,5], with each index corresponding to the following default color: * 0 - White * 1 - Yellow * 2 - Orange * 3 - Red * 4 - Blue * 5 - Green

If custom colors are defined, then the indexes will map on the array of custom colors. For example, if in a custom color scheme Black replaces White, then the index 0 would map to Black.

Example value of initialState for a solved cube:

cube:initialState="000000000111111111222222222333333333444444444555555555"

By default, the cube is in the state mentioned above as example.

moves - string | reference

Sets the sequence of moves that need to be performed (and optionally, animated). Some of the moves affect centers and they can be moved to another layer from the user's point of view. Such movements do not affect the notation from the user's point of view. The characters are not fixed to particular centers.

For example, if an "M" is performed and then an "F" is needed, it should affect the front layer seen in the front position and not the bottom layer, where the center that was in the front position is now placed. The chosen way is very familiar to the "corner-starters" (solving the cube starting from the corners).

The sequence is defined in extended Singmaster's notation. The basis for the turns are six letters of the following meaning.

  • U - Up (rotate top layer)
  • D - Down (rotate bottom layer)
  • F - Front (rotate front layer)
  • B - Back (rotate back layer)
  • L - Left (rotate left layer)
  • R - Right (rotate right layer)

The letter case is important here, because the same - but lowercase - letters are used for different moves. Modifiers can be appended to the move character.

  • Separate characters mean turning the corresponding layer 90 degrees clock-wise.
  • Appending apostrophe "'" or digit "3" means turning 90 degrees counter clock-wise.
  • Appending digit "2" means 180 degrees rotation of the corresponding layer (clock-wise).
  • You can use combination "2'" for double counter clock-wise turn. This combination is useful if you want to show the most efficient directions when using finger shortcuts.

There are also some advanced modifiers that are written immediately after the move letter and right before the basic modifiers already defined. The possible modifiers are:

  • m - middle layer turn between the specified layer and the opposite one
  • c - whole-cube turn in the direction of the specified layer
  • s - slice turn; two opposite layers are turned in the same directions ("Rs" is equal to "R L'" or "L' R")
  • a - anti-slice turn; two opposite layers are turned in the opposite directions ("Ra" is equal to "R L" or "L R")
  • t - thick turn; two adjacent layers (the specified one and the adjacent one) are turned simultaneously

The library supports some additional characters to represent specific moves. The center layers can be rotated using the following characters in combination with previous modifiers.

  • E - equator (between U and D layers in the U'/D direction)
  • S - standing (between F and B layers in the F/B' direction)
  • M - middle (between L and R layers in the L/R' direction)

The library also supports turns of the entire cube. This feature can be used to rotate the cube in order to show the cube in the best position for the current situation to watch the move sequence. The available symbols to rotate the cube are shown in the following table (they can be also combined with the modifiers).

  • X - rotate around x-axis (in the same direction as "R" or "L'" is performed)
  • Y - rotate around y-axis (in the same direction as "F" or "B'" is performed)
  • Z - rotate around z-axis (in the same direction as "U" or "D'" is performed)

There is also a possibility to rotate two adjacent layers simultaneously. The notation and meaning is similar to the fac

Extension points exported contracts — how you extend this code

OnCubeModelUpdatedListener (Interface)
Interface definition for a callback to be invoked when the cube model has changed. [1 implementers]
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCube.java
OnCubeAnimationFinishedListener (Interface)
Interface definition for a callback to be invoked when the cube has finished animating a move. [1 implementers]
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCube.java

Core symbols most depended-on inside this repo

d
called by 33
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/LogUtil.java
e
called by 33
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/LogUtil.java
vProd
called by 21
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeUtils.java
vCopy
called by 18
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeUtils.java
vScale
called by 18
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeUtils.java
deepCopy2DArray
called by 14
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeUtils.java
repaint
called by 13
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCubeDebug.java
repaint
called by 13
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCube.java

Shape

Method 181
Class 9
Interface 2

Languages

Java100%

Modules by API surface

animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCube.java81 symbols
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/AnimCubeDebug.java76 symbols
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeUtils.java14 symbols
app/src/main/java/com/catalinjurjiu/demoanimcubeandroid/MainActivity.java10 symbols
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/LogUtil.java5 symbols
app/src/test/java/com/catalinjujiu/testrubikrenderer/ExampleUnitTest.java2 symbols
app/src/androidTest/java/com/catalinjujiu/testrubikrenderer/ExampleInstrumentedTest.java2 symbols
animcubeandroid/src/main/java/com/catalinjurjiu/animcubeandroid/CubeConstants.java2 symbols

For agents

$ claude mcp add AnimCubeAndroid \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact