cubing / AnimCubeJS

▶️ Play around with a Rubik's Cube simulator.
https://animcubejs.cubing.net/animcubejs.html
MIT License
29 stars 10 forks source link

Support tweaks or markers #38

Closed calfzhou closed 3 weeks ago

calfzhou commented 5 months ago

Coming from larspetrus/Roofpig.

Roofpig provides a tweaks feature, which is a free form tool, that can set any sticker to any color. Aside from colors, it can also put X es on stickers, for example:

image

This is very useful that I could use it to highlight some stickers.

I read AnimCubeJS's document, didn't find how to achieve similar effects. Would it be possible to implement this in AnimCubeJS?

bcube2 commented 5 months ago

As for highlighting some stickerrs, the facelets parameter in combination with the colors parameter can be used.

As for markers, I´ll let developers to comment on that.

mfeather1 commented 5 months ago

Here is a function to draw an X on facelets that can be added to AnimCube3.js:

  function drawX(g, xx, yy) {
    var x = [];
    var y = [];
    // scale down so there is a margin around the X 
    for (var i = 0; i < 4; i++) {
      x[i] = Math.floor(xx[i] + (xx[superRotate[2][i]] - xx[i]) * .30);
      y[i] = Math.floor(yy[i] + (yy[superRotate[2][i]] - yy[i]) * .30);
    }
    g.lineWidth = 4*dpr;
    g.strokeStyle = "black";
    g.beginPath();
    g.moveTo(x[0], y[0]);
    g.lineTo(x[2], y[2]);
    g.closePath();
    g.stroke();
    g.beginPath();
    g.moveTo(x[1], y[1]);
    g.lineTo(x[3], y[3]);
    g.closePath();
    g.stroke();
  }

Add a call to the drawX function in fixBlock (in section: "draw all visible faces and get dragging regions"), by adding the two lines shown:

  else {
    drawPolygon(graphics, fillX, fillY, colors[cube[i][p * 3 + q]]);
    fillPolygon(graphics, fillX, fillY, colors[cube[i][p * 3 + q]]);
    if (scube[i][p * 3 + q] == 1)        <-- Add
      drawX(graphics, fillX, fillY);     <-- Add
  }

Use the superfacelets parameter to indicate which facelets to mark with X: https://drive.google.com/file/d/1V5UVVYO-c_qGMqF1r8dBhmhz6Y5IKlmy/view?usp=sharing

calfzhou commented 4 months ago

@mfeather1 Many thanks! It works for me. And i also draw the 'X' on hint faces:

image
calfzhou commented 4 months ago

Found a problem that the "X" marker is locked to a position, not a sticker.

For example, I marked a yellow sticker with "X":

image

but once i take a move, e.g. R, the "X" will leave the yellow sticker:

image

Update:

fixed by call twistLayer2(scube, layer, num, middle) even if not a supercube.

image
calfzhou commented 4 months ago

Now i add a markers param to define every stickers' extra marker. The value of this markers param is just like superfacelets, while the number indices different markers:

image

Here is the diff (base on cube 7x7x7):

diff --git a/sources/codes/js-unminified/AnimCube7-unminified.js b/sources/codes/js-unminified/AnimCube7-unminified.js
index da1aff2..cf52ee2 100644
--- a/sources/codes/js-unminified/AnimCube7-unminified.js
+++ b/sources/codes/js-unminified/AnimCube7-unminified.js
@@ -25,6 +25,8 @@ function AnimCube7(params) {
   var scube = [];
   var initialCube = [];
   var initialSCube = [];
+  var mcube = [];
+  var initialMCube = [];
   // normal vectors
   var faceNormals = [
     [ 0.0, -1.0,  0.0], // U
@@ -305,6 +307,11 @@ function AnimCube7(params) {
         for (var j = 0; j < 49; j++)
           scube[i][j] = 0;
     }
+    for (var i = 0; i < 6; i++) {
+      for (var j = 0; j < 49; j++) {
+        mcube[i][j] = 0;
+      }
+    }
     var initialPosition = "lluu";
     // setup color configuration of the solved cube
     param = getParameter("colorscheme");
@@ -377,6 +384,15 @@ function AnimCube7(params) {
           }
         }
       }
+      // setup marker facelets
+      param = getParameter("markers");
+      if (param != null && param.length == 294) {
+        for (var i = 0; i < 6; i++) {
+          for (var j = 0; j < 49; j++) {
+            mcube[i][j] = parseInt(param[i * 49 + j])
+          }
+        }
+      }
     }
     moveText = 0;
     yzAlt = false;
@@ -636,6 +652,7 @@ function AnimCube7(params) {
       for (var j = 0; j < 49; j++) {
         initialCube[i][j] = cube[i][j];
         initialSCube[i][j] = scube[i][j];
+        initialMCube[i][j] = mcube[i][j];
       }
     if (initialMove.length > 0)
       doMove(cube, initialMove[0], 0, initialMove[0].length, false);
@@ -1103,6 +1120,7 @@ function AnimCube7(params) {
       for (var j = 0; j < 49; j++) {
         cube[i][j] = initialCube[i][j];
         scube[i][j] = initialSCube[i][j];
+        mcube[i][j] = initialMCube[i][j];
       }
     if (initialMove.length > 0 && typeof initialMove[curMove] != 'undefined')
       doMove(cube, initialMove[curMove], 0, initialMove[curMove].length, false);
@@ -1325,6 +1343,7 @@ function AnimCube7(params) {

   function twistLayer(cube, layer, num, middle) {
     twistLayer2(cube, layer, num, middle);
+    twistLayer2(mcube, layer, num, middle);
     if (superCube == true && num > 0 && num < 4) {
       twistLayer2(scube, layer, num, middle);
       twistSuperLayer(layer, num, middle);
@@ -1855,9 +1874,11 @@ function AnimCube7(params) {
                     drawPolygon(graphics, fillX, fillY, "#fdfdfd");
                   */
          drawSuperArrow(graphics, fillX, fillY, i, scube[i][p * 7 + q], colors[cube[i][p * 7 + q]]);
+                  drawMarker(graphics, fillX, fillY, mcube[i][p * 7 + q]);
                 }
                 else {
                   fillPolygon(graphics, fillX, fillY, colors[cube[i][p * 7 + q]]);
+                  drawMarker(graphics, fillX, fillY, mcube[i][p * 7 + q]);
                   if (hintBorder)
                     drawPolygon(graphics, fillX, fillY, darker(colors[cube[i][p * 7 + q]]));
                   else
@@ -1908,10 +1929,12 @@ function AnimCube7(params) {
                 drawPolygon(graphics, fillX, fillY, "#fdfdfd");
                 fillPolygon(graphics, fillX, fillY, "#fdfdfd");
                 drawSuperArrow(graphics, fillX, fillY, i, scube[i][p * 7 + q], colors[cube[i][p * 7 + q]]);
+                drawMarker(graphics, fillX, fillY, mcube[i][p * 7 + q]);
               }
               else {
                 drawPolygon(graphics, fillX, fillY, colors[cube[i][p * 7 + q]]);
                 fillPolygon(graphics, fillX, fillY, colors[cube[i][p * 7 + q]]);
+                drawMarker(graphics, fillX, fillY, mcube[i][p * 7 + q]);
               }
             }
           }
@@ -2379,6 +2402,62 @@ function AnimCube7(params) {

   var superRotate = [[0, 1, 2, 3], [3, 0, 1, 2], [2, 3, 0, 1], [1, 2, 3, 0]];

+  function drawMarker(g, xx, yy, m) {
+    var x = [];
+    var y = [];
+    // scale down so there is a margin around the X
+    for (var i = 0; i < 4; i++) {
+      x[i] = Math.floor(xx[i] + (xx[superRotate[2][i]] - xx[i]) * .20);
+      y[i] = Math.floor(yy[i] + (yy[superRotate[2][i]] - yy[i]) * .20);
+    }
+    g.lineWidth = 2*dpr;
+    g.strokeStyle = "black";
+
+    if (m === 1) {
+      // an "X"
+      g.beginPath();
+      g.moveTo(x[0], y[0]);
+      g.lineTo(x[2], y[2]);
+      g.closePath();
+      g.stroke();
+      g.beginPath();
+      g.moveTo(x[1], y[1]);
+      g.lineTo(x[3], y[3]);
+      g.closePath();
+      g.stroke();
+    } else if (m === 2) {
+      // a square "□"
+      g.beginPath();
+      g.moveTo(x[0], y[0]);
+      g.lineTo(x[1], y[1]);
+      g.lineTo(x[2], y[2]);
+      g.lineTo(x[3], y[3]);
+      g.closePath();
+      g.stroke();
+    } else if (m === 3) {
+      // a "+"
+      g.beginPath();
+      g.moveTo((x[0] + x[1]) / 2, (y[0] + y[1]) / 2);
+      g.lineTo((x[2] + x[3]) / 2, (y[2] + y[3]) / 2);
+      g.closePath();
+      g.stroke();
+      g.beginPath();
+      g.moveTo((x[0] + x[3]) / 2, (y[0] + y[3]) / 2);
+      g.lineTo((x[1] + x[2]) / 2, (y[1] + y[2]) / 2);
+      g.closePath();
+      g.stroke();
+    } else if (m === 4) {
+      // a 45°-rotated square "◇"
+      g.beginPath();
+      g.moveTo((x[0] + x[1]) / 2, (y[0] + y[1]) / 2);
+      g.lineTo((x[1] + x[2]) / 2, (y[1] + y[2]) / 2);
+      g.lineTo((x[2] + x[3]) / 2, (y[2] + y[3]) / 2);
+      g.lineTo((x[3] + x[0]) / 2, (y[3] + y[0]) / 2);
+      g.closePath();
+      g.stroke();
+    }
+  }
+
   function drawSuperArrow(g, xx, yy, face, superTwist, color) {
     var x = [];
     var y = [];
@@ -2685,6 +2764,7 @@ function AnimCube7(params) {
       for (var j = 0; j < 49; j++) {
         cube[i][j] = initialCube[i][j];
         scube[i][j] = initialSCube[i][j];
+        mcube[i][j] = initialMCube[i][j];
        }
     if (initialMove.length > 0 && typeof initialMove[curMove] != 'undefined')
       doMove(cube, initialMove[curMove], 0, initialMove[curMove].length, false);
@@ -3095,6 +3175,8 @@ function AnimCube7(params) {
       scube[i] = [];
       initialCube[i] = [];
       initialSCube[i] = [];
+      mcube[i] = [];
+      initialMCube[i] = [];
     }
     for (var i = 0; i < 42; i++) {
       dragCornersX[i] = [];
mfeather1 commented 4 months ago

Glad to see that you've got it working, and then some! :)