├── Factory Scripts
├── MusicGen.littlefootModes
│ ├── A min.mode
│ ├── C Maj.mode
│ ├── E min.mode
│ ├── F Maj.mode
│ └── G Maj.mode
├── Seaboard.littlefootModes
│ ├── Piano.mode
│ ├── MPE.mode
│ ├── Multi Channel.mode
│ └── Single Channel.mode
├── Note Grid.littlefootModes
│ ├── MPE.mode
│ ├── Multi Channel.mode
│ └── Single Channel.mode
├── Drum Block.littlefootModes
│ ├── 2x2 MPE Mode.mode
│ ├── 3x3 MPE Mode.mode
│ ├── 4x4 MPE Mode.mode
│ ├── 2x2 Multi Channel Mode.mode
│ ├── 3x3 Multi Channel Mode.mode
│ ├── 4x4 Multi Channel Mode.mode
│ ├── 2x2 Single Channel Mode.mode
│ ├── 3x3 Single Channel Mode.mode
│ └── 4x4 Single Channel Mode.mode
├── BLOCKSvaders.littlefoot
├── BreakBLOCKS.littlefoot
├── RISE Controller.littlefoot
├── Fader Block.littlefoot
├── XYZ Pad.littlefoot
├── Mixer Block.littlefoot
├── MusicGen.littlefoot
├── Control Grid.littlefoot
└── Drum Block.littlefoot
├── Example Scripts
├── PressureMap.littlefoot
├── BuzzyBee.littlefoot
├── SonOfPong.littlefoot
├── DynamicParameters.littlefoot
├── ColourPressureMap.littlefoot
├── Mario.littlefoot
├── Pacman.littlefoot
├── TicTacToe.littlefoot
└── MusicGen.littlefoot
└── LICENSE.txt
/Factory Scripts/MusicGen.littlefootModes/A min.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Factory Scripts/MusicGen.littlefootModes/C Maj.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Factory Scripts/MusicGen.littlefootModes/E min.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Factory Scripts/MusicGen.littlefootModes/F Maj.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Factory Scripts/MusicGen.littlefootModes/G Maj.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example Scripts/PressureMap.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 | */
5 |
6 | void touchStart (int index, float x, float y, float z, float vz)
7 | {
8 | addPressurePoint (0xffffff, x, y, z * 100.0);
9 | }
10 |
11 | void touchMove (int index, float x, float y, float z, float vz)
12 | {
13 | addPressurePoint (0xffffff, x, y, z * 20.0);
14 | }
15 |
16 | void repaint()
17 | {
18 | clearDisplay();
19 | drawPressureMap();
20 | fadePressureMap();
21 | }
22 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | This software is distributed under the terms of the Creative Commons
2 | Public Domain Dedication [CC0]:
3 |
4 | To the extent possible under law, ROLI Ltd
5 | has waived all copyright, and related or neighboring rights,
6 | to this work.
7 |
8 | In no way are the patent or trademark rights of any person affected
9 | by CC0, nor are the rights that other persons may have in the work
10 | or in how the work is used, such as publicity or privacy rights.
11 |
12 | ROLI Ltd. makes no warranties about the work, and disclaims
13 | liability for all uses of the work, to the fullest extent permitted
14 | by applicable law.
15 |
16 | When using or citing the work, you should not imply endorsement by
17 | ROLI Ltd.
18 |
--------------------------------------------------------------------------------
/Example Scripts/BuzzyBee.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 | */
8 |
9 | int x;
10 | int y;
11 |
12 | int xDir;
13 | int yDir;
14 |
15 | void repaint()
16 | {
17 | clearDisplay();
18 |
19 | fillRect (beeColour, x, y, 2, 2);
20 |
21 | if (xDir == 0)
22 | {
23 | x += 1;
24 | if (x >= 13)
25 | {
26 | xDir = 1;
27 | }
28 | }
29 | else
30 | {
31 | if (x <= 1)
32 | {
33 | xDir = 0;
34 | }
35 | x -= 1;
36 | }
37 |
38 | if (yDir == 0)
39 | {
40 | y += 1;
41 | if (y >= 7)
42 | {
43 | yDir = 1;
44 | }
45 | }
46 | else if (yDir == 1)
47 | {
48 | if (y <= 1)
49 | {
50 | yDir = 2;
51 | y = 7;
52 | }
53 | else
54 | {
55 | y -= 1;
56 | }
57 | }
58 | else if (yDir == 2)
59 | {
60 | y += 1;
61 | if (y >= 13)
62 | {
63 | yDir = 3;
64 | }
65 | }
66 | else if (yDir == 3)
67 | {
68 | if (y <= 1)
69 | {
70 | yDir = 0;
71 | }
72 | y -= 1;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Example Scripts/SonOfPong.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 | */
5 |
6 | int ballX, ballY;
7 | bool ballXVec, ballYVec;
8 | bool hasStarted;
9 |
10 | int paddleL, paddleR;
11 |
12 | void repaint()
13 | {
14 | fillRect (0x000000, 0, 0, 15, 15);
15 |
16 | if (! hasStarted)
17 | {
18 | ballX = 7;
19 | ballY = 7;
20 |
21 | ballXVec = true;
22 | ballYVec = false;
23 | hasStarted = true;
24 |
25 | paddleL = 7;
26 | paddleR = 7;
27 | }
28 |
29 | if (ballXVec)
30 | {
31 | ballX += 1;
32 | if (ballX >= 13)
33 | {
34 | ballX = 13;
35 | ballXVec = false;
36 | }
37 | }
38 | else
39 | {
40 | if (ballX <= 2)
41 | {
42 | ballX = 2;
43 | ballXVec = true;
44 | }
45 | ballX -= 1;
46 | }
47 |
48 | if (ballYVec)
49 | {
50 | ballY += 1;
51 | if (ballY >= 15)
52 | {
53 | ballY = 15;
54 | ballYVec = false;
55 | }
56 | }
57 | else
58 | {
59 | if (ballY <= 1)
60 | {
61 | ballYVec = true;
62 | }
63 | ballY -= 1;
64 | }
65 |
66 | fillRect (0xFFFF00, ballX, ballY, 1, 1);
67 |
68 | fillRect (0xFFFF00, 0, paddleL - 2, 1, 5);
69 | fillRect (0xFFFF00, 14, paddleR - 2, 1, 5);
70 | }
71 |
--------------------------------------------------------------------------------
/Factory Scripts/Seaboard.littlefootModes/Piano.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Factory Scripts/Seaboard.littlefootModes/MPE.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Factory Scripts/Seaboard.littlefootModes/Multi Channel.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Factory Scripts/Seaboard.littlefootModes/Single Channel.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example Scripts/DynamicParameters.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | */
21 |
22 | void repaint()
23 | {
24 | clearDisplay();
25 |
26 | if (draw)
27 | fillRect (makeARGB (int (alpha), red, green, blue), xPos, yPos, width, height);
28 | }
29 |
--------------------------------------------------------------------------------
/Factory Scripts/Note Grid.littlefootModes/MPE.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Factory Scripts/Note Grid.littlefootModes/Multi Channel.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Factory Scripts/Note Grid.littlefootModes/Single Channel.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Example Scripts/ColourPressureMap.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | */
12 |
13 | int getPressureColour (int index)
14 | {
15 | int col = pressureColour3;
16 |
17 | if (index == 1)
18 | {
19 | col = pressureColour0;
20 | }
21 | else if (index == 2)
22 | {
23 | col = pressureColour1;
24 | }
25 | else if (index == 3)
26 | {
27 | col = pressureColour2;
28 | }
29 |
30 | return col;
31 | }
32 |
33 | void touchStart (int index, float x, float y, float z, float vz)
34 | {
35 | addPressurePoint (getPressureColour (index), x, y, z * float (scaling));
36 | }
37 |
38 | void touchMove (int index, float x, float y, float z, float vz)
39 | {
40 | addPressurePoint (getPressureColour (index), x, y, z * float (scaling));
41 | }
42 |
43 | void repaint()
44 | {
45 | clearDisplay();
46 | drawPressureMap();
47 | fadePressureMap();
48 | }
49 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/2x2 MPE Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/3x3 MPE Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/4x4 MPE Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/2x2 Multi Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/3x3 Multi Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/4x4 Multi Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/2x2 Single Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/3x3 Single Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefootModes/4x4 Single Channel Mode.mode:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Example Scripts/Mario.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 | */
5 |
6 | void repaint()
7 | {
8 | clearDisplay();
9 |
10 | // Hands fill
11 | fillRect (makeARGB (255, 239, 193, 49), 2, 9, 12, 3);
12 |
13 | // Left foot
14 | fillRect (makeARGB (255, 64, 40, 3), 2, 14, 4, 1);
15 | fillRect (makeARGB (255, 64, 40, 3), 3, 13, 3, 1);
16 |
17 | // Right foot
18 | fillRect (makeARGB (255, 64, 40, 3), 10, 14, 4, 1);
19 | fillRect (makeARGB (255, 64, 40, 3), 10, 13, 3, 1);
20 |
21 | // Dungarees
22 | fillRect (makeARGB (255, 7, 0, 250), 4, 12, 3, 1);
23 | fillRect (makeARGB (255, 7, 0, 250), 9, 12, 3, 1);
24 | fillRect (makeARGB (255, 7, 0, 250), 4, 11, 8, 1);
25 | fillRect (makeARGB (255, 7, 0, 250), 5, 10, 6, 1);
26 | fillRect (makeARGB (255, 7, 0, 250), 5, 9, 1, 1);
27 | fillRect (makeARGB (255, 7, 0, 250), 7, 9, 2, 1);
28 | fillRect (makeARGB (255, 7, 0, 250), 10, 9, 1, 1);
29 | fillRect (makeARGB (255, 7, 0, 250), 6, 8, 4, 1);
30 | fillRect (makeARGB (255, 7, 0, 250), 6, 7, 1, 1);
31 | fillRect (makeARGB (255, 7, 0, 250), 9, 7, 1, 1);
32 | fillRect (makeARGB (255, 7, 0, 250), 6, 6, 1, 1);
33 | fillRect (makeARGB (255, 7, 0, 250), 9, 6, 1, 1);
34 |
35 | // Buttons
36 | fillRect (makeARGB (255, 251, 242, 57), 6, 9, 1, 1);
37 | fillRect (makeARGB (255, 251, 242, 57), 9, 9, 1, 1);
38 |
39 | // Shirt
40 | fillRect (makeARGB (255, 203, 34, 41), 7, 6, 2, 2);
41 | fillRect (makeARGB (255, 203, 34, 41), 4, 6, 2, 3);
42 | fillRect (makeARGB (255, 203, 34, 41), 10, 6, 2, 3);
43 | fillRect (makeARGB (255, 203, 34, 41), 3, 7, 1, 2);
44 | fillRect (makeARGB (255, 203, 34, 41), 2, 8, 1, 1);
45 | fillRect (makeARGB (255, 203, 34, 41), 4, 9, 1, 1);
46 | fillRect (makeARGB (255, 203, 34, 41), 12, 7, 1, 2);
47 | fillRect (makeARGB (255, 203, 34, 41), 13, 8, 1, 1);
48 | fillRect (makeARGB (255, 203, 34, 41), 11, 9, 1, 1);
49 |
50 | // Head
51 | fillRect (makeARGB (255, 239, 193, 49), 5, 1, 6, 5);
52 | fillRect (makeARGB (255, 239, 193, 49), 4, 1, 1, 3);
53 | fillRect (makeARGB (255, 239, 193, 49), 11, 2, 2, 2);
54 | fillRect (makeARGB (255, 239, 193, 49), 13, 3, 1, 1);
55 |
56 | // Moustache
57 | fillRect (makeARGB (255, 12, 12, 12), 9, 4, 4, 1);
58 | fillRect (makeARGB (255, 12, 12, 12), 10, 3, 1, 1);
59 |
60 | // Eyes
61 | fillRect (makeARGB (255, 12, 12, 12), 9, 1, 1, 2);
62 |
63 | // Hat
64 | fillRect (makeARGB (255, 203, 34, 41), 4, 0, 9, 1);
65 |
66 | // Hair
67 | fillRect (makeARGB (255, 64, 40, 3), 4, 2, 1, 2);
68 | fillRect (makeARGB (255, 64, 40, 3), 5, 4, 1, 1);
69 | fillRect (makeARGB (255, 64, 40, 3), 5, 1, 3, 1);
70 | fillRect (makeARGB (255, 64, 40, 3), 6, 1, 1, 3);
71 | fillRect (makeARGB (255, 64, 40, 3), 7, 3, 1, 1);
72 | }
73 |
--------------------------------------------------------------------------------
/Example Scripts/Pacman.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 | */
5 |
6 | float position;
7 | float speed;
8 |
9 | int mouthWidth;
10 | float mouthSpeed;
11 | float mouthHeight;
12 | float mouthMaxHeight;
13 |
14 | bool msPacman;
15 | int pacmanSize;
16 |
17 | void initialise()
18 | {
19 | position = -14.0;
20 | speed = 0.3;
21 |
22 | mouthWidth = 9;
23 | mouthSpeed = 2.0;
24 | mouthHeight = 7.0;
25 | mouthMaxHeight = 12.0;
26 |
27 | msPacman = false;
28 |
29 | pacmanSize = 14;
30 | }
31 |
32 | void repaint()
33 | {
34 | clearDisplay();
35 |
36 | int pos = int (position);
37 |
38 | paintFood (pos, 1);
39 | paintPacmanAt (pos, 1);
40 | paintPacmanMouthAt (pos, 1);
41 |
42 | if (msPacman)
43 | paintAccessories (pos, 1);
44 |
45 | update();
46 | }
47 |
48 | void paintPacmanAt (int x, int y)
49 | {
50 | int colour = makeARGB (255, 255, 255, 0);
51 |
52 | fillRect (colour, x + 4, y, 5, 1);
53 | fillRect (colour, x + 2, y + 1, 9, 1);
54 | fillRect (colour, x + 1, y + 2, 11, 1);
55 | fillRect (colour, x + 1, y + 3, 11, 1);
56 | fillRect (colour, x + 0, y + 4, 13, 1);
57 | fillRect (colour, x + 0, y + 5, 13, 1);
58 | fillRect (colour, x + 0, y + 6, 13, 1);
59 | fillRect (colour, x + 0, y + 7, 13, 1);
60 | fillRect (colour, x + 0, y + 8, 13, 1);
61 | fillRect (colour, x + 1, y + 9, 11, 1);
62 | fillRect (colour, x + 1, y + 10, 11, 1);
63 | fillRect (colour, x + 2, y + 11, 9, 1);
64 | fillRect (colour, x + 4, y + 12, 5, 1);
65 | }
66 |
67 | void paintPacmanMouthAt (int x, int y)
68 | {
69 | int colour = makeARGB (255, 0, 0, 0);
70 |
71 | int cx = x + 4;
72 | int cy = y + 6;
73 |
74 | for (int i = 0; i < mouthWidth; ++i)
75 | {
76 | int h = getMouthHeight (i, mouthHeight);
77 | fillRect (colour, cx + i, cy - h / 2, 1, h);
78 | }
79 | }
80 |
81 | void paintAccessories (int x, int y)
82 | {
83 | int red = makeARGB (255, 255, 0, 0);
84 | fillRect (red, x + 0, y + 4, 2, 2);
85 | fillRect (red, x + 2, y + 2, 2, 2);
86 | fillRect (red, x + 4, y + 0, 2, 2);
87 | fillRect (red, x - 1, y + 1, 3, 4);
88 | fillRect (red, x + 1, y + 1, 2, 2);
89 | fillRect (red, x + 1, y - 1, 4, 2);
90 |
91 | int aqua = makeARGB (255, 51, 153, 255);
92 | fillRect (aqua, x + 2, y, 2, 2);
93 | fillRect (aqua, x, y + 2, 2, 2);
94 |
95 | int black = makeARGB (255, 0, 0, 0);
96 | fillRect (black, x + 4, y + 4, 2, 1);
97 | fillRect (black, x + 3, y + 5, 1, 1);
98 |
99 | for (int i = mouthWidth - 3; i < mouthWidth; ++i)
100 | {
101 | int cx = x + 3;
102 | int cy = y + 6;
103 | int h = getMouthHeight (i, mouthHeight);
104 | int halfHeight = int (h / 2.0);
105 |
106 | fillRect (red, cx + i, cy - halfHeight, 1, 1);
107 | fillRect (red, cx + i, cy + halfHeight, 1, 1);
108 | }
109 | }
110 |
111 | void paintFood (int x, int y)
112 | {
113 | int colour = makeARGB (255, 0, 0, 255);
114 |
115 | int cy = y + 6;
116 |
117 | int spacing = 2;
118 |
119 | for (int i = 0; i < 14; i += spacing)
120 | {
121 | if (i > x + (pacmanSize / 2) - 1)
122 | fillPixel (colour, i, cy);
123 | }
124 | }
125 |
126 | int getMouthHeight (int x, float h)
127 | {
128 | return int (x / 8.0 * h);
129 | }
130 |
131 | void update()
132 | {
133 | position += speed;
134 |
135 | if (position > 14)
136 | position = 0 - pacmanSize;
137 |
138 | mouthHeight += mouthSpeed;
139 |
140 | if (mouthHeight > mouthMaxHeight || mouthHeight < 0)
141 | {
142 | mouthSpeed *= -1.0;
143 | }
144 | }
145 |
146 | void touchMove (int index, float x, float y, float z, float vz)
147 | {
148 | speed = 0.3 + z * 2.0;
149 | }
150 |
151 | void touchEnd (int index, float x, float y, float z, float vz)
152 | {
153 | speed = 0.3;
154 | }
155 |
156 | void handleButtonDown (int index)
157 | {
158 | msPacman = ! msPacman;
159 | }
160 |
--------------------------------------------------------------------------------
/Example Scripts/TicTacToe.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 | */
5 |
6 | int tl, t, tr;
7 | int ml, m, mr;
8 | int bl, b, br;
9 |
10 | int currentTurn;
11 |
12 | int winner;
13 |
14 | void initialise()
15 | {
16 | tl = 0;
17 | t = 0;
18 | tr = 0;
19 | ml = 0;
20 | m = 0;
21 | mr = 0;
22 | bl = 0;
23 | b = 0;
24 | br = 0;
25 |
26 | currentTurn = 1;
27 | winner = 0;
28 | }
29 |
30 | void repaint()
31 | {
32 | clearDisplay();
33 |
34 | if (winner == 0)
35 | {
36 | drawGrid();
37 | drawSigns();
38 | }
39 | else
40 | {
41 | drawWinner();
42 | }
43 | }
44 |
45 | void drawWinner()
46 | {
47 | if (winner == 1)
48 | {
49 | int xColour = makeARGB (255, 0, 255, 0);
50 | fillRect (xColour, 0, 0, 15, 15);
51 | }
52 | else if (winner == 2)
53 | {
54 | int oColour = makeARGB (255, 0, 0, 255);
55 | fillRect (oColour, 0, 0, 15, 15);
56 | }
57 | }
58 |
59 | void drawGrid()
60 | {
61 | int white = makeARGB (255, 200, 200, 200);
62 |
63 | if (tl == 0) drawRect (white, 0, 0, 5, 5);
64 | if (t == 0) drawRect (white, 5, 0, 5, 5);
65 | if (tr == 0) drawRect (white, 10, 0, 5, 5);
66 | if (ml == 0) drawRect (white, 0, 5, 5, 5);
67 | if (m == 0) drawRect (white, 5, 5, 5, 5);
68 | if (mr == 0) drawRect (white, 10, 5, 5, 5);
69 | if (bl == 0) drawRect (white, 0, 10, 5, 5);
70 | if (b == 0) drawRect (white, 5, 10, 5, 5);
71 | if (br == 0) drawRect (white, 10, 10, 5, 5);
72 | }
73 |
74 | void drawRect (int colour, int x, int y, int w, int h)
75 | {
76 | fillRect (colour, x, y, 1, h);
77 | fillRect (colour, x, y, w, 1);
78 |
79 | fillRect (colour, x + w - 1, y, 1, h);
80 | fillRect (colour, x, y + h - 1, w, 1);
81 | }
82 |
83 | void drawSigns()
84 | {
85 | evaluate (tl, 0, 0);
86 | evaluate (t , 5, 0);
87 | evaluate (tr, 10, 0);
88 |
89 | evaluate (ml, 0, 5);
90 | evaluate (m, 5, 5);
91 | evaluate (mr, 10, 5);
92 |
93 | evaluate (bl, 0, 10);
94 | evaluate (b, 5, 10);
95 | evaluate (br, 10, 10);
96 | }
97 |
98 | void evaluate (int value, int x, int y)
99 | {
100 | if (value == 1)
101 | drawX (x, y);
102 | else if (value == 2)
103 | drawO (x, y);
104 | }
105 |
106 | void drawX (int x, int y)
107 | {
108 | int xColour = makeARGB (255, 0, 255, 0);
109 |
110 | fillRect (xColour, x, y, 1, 1);
111 | fillRect (xColour, x + 1, y + 1, 1, 1);
112 | fillRect (xColour, x + 2, y + 2, 1, 1);
113 | fillRect (xColour, x + 3, y + 3, 1, 1);
114 | fillRect (xColour, x + 4, y + 4, 1, 1);
115 |
116 | fillRect (xColour, x + 4, y, 1, 1);
117 | fillRect (xColour, x + 3, y + 1, 1, 1);
118 | fillRect (xColour, x + 2, y + 2, 1, 1);
119 | fillRect (xColour, x + 1, y + 3, 1, 1);
120 | fillRect (xColour, x, y + 4, 1, 1);
121 | }
122 |
123 | void drawO (int x, int y)
124 | {
125 | int oColour = makeARGB (255, 0, 0, 255);
126 |
127 | fillRect (oColour, x, y, 5, 1);
128 | fillRect (oColour, x, y + 4, 5, 1);
129 | fillRect (oColour, x, y, 1, 5);
130 | fillRect (oColour, x + 4, y, 1, 5);
131 | }
132 |
133 | void touchStart (int index, float x, float y, float z, float vz)
134 | {
135 | int xPos = int (x * 7);
136 | int yPos = int (y * 7);
137 |
138 | int index = getIndex (xPos, yPos);
139 |
140 | if (setValueForIndex (index, currentTurn))
141 | {
142 | currentTurn = currentTurn == 1 ? 2 : 1;
143 | }
144 |
145 | if (xHasWon()) winner = 1;
146 | else if (oHasWon()) winner = 2;
147 | }
148 |
149 | int getIndex (int x, int y)
150 | {
151 | int xInd = x / 5;
152 | int yInd = y / 5;
153 |
154 | return yInd * 3 + xInd;
155 | }
156 |
157 | bool setValueForIndex (int index, int value)
158 | {
159 | if (index == 0) { tl = tl == 0 ? value : tl; return true; }
160 | if (index == 1) { t = t == 0 ? value : t ; return true; }
161 | if (index == 2) { tr = tr == 0 ? value : tr; return true; }
162 | if (index == 3) { ml = ml == 0 ? value : ml; return true; }
163 | if (index == 4) { m = m == 0 ? value : m ; return true; }
164 | if (index == 5) { mr = mr == 0 ? value : mr; return true; }
165 | if (index == 6) { bl = bl == 0 ? value : bl; return true; }
166 | if (index == 7) { b = b == 0 ? value : b ; return true; }
167 | if (index == 8) { br = br == 0 ? value : br; return true; }
168 |
169 | return false;
170 | }
171 |
172 | bool xHasWon() { return hasWon (1); }
173 | bool oHasWon() { return hasWon (2); }
174 |
175 | bool hasWon (int player)
176 | {
177 | return (tl == player && t == player && tr == player)
178 | || (ml == player && m == player && mr == player)
179 | || (bl == player && b == player && br == player)
180 |
181 | || (tl == player && ml == player && bl == player)
182 | || (t == player && m == player && b == player)
183 | || (tr == player && mr == player && br == player)
184 |
185 | || (tl == player && m == player && br == player)
186 | || (tr == player && m == player && bl == player);
187 | }
188 |
189 | void handleButtonDown (int index)
190 | {
191 | initialise();
192 | }
193 |
--------------------------------------------------------------------------------
/Factory Scripts/BLOCKSvaders.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | */
4 |
5 | int gameState_Over;
6 | int gameState_Play;
7 | int gameState_Prepare;
8 | int gameState;
9 |
10 | int score;
11 | int highScore;
12 |
13 | float playerX;
14 | float playerY;
15 | float targetPlayerX;
16 | float playerSpeedX;
17 |
18 | float enemyX;
19 | float enemyY;
20 | float enemySpeedY;
21 |
22 | float enemySpeedIncreasePerKill;
23 |
24 | float bulletX;
25 | float bulletY;
26 | float bulletSpeedY;
27 |
28 | float explosionX;
29 | float explosionY;
30 | float explosionWidth;
31 | float explosionGrowPerFrame;
32 | float explosionMax;
33 |
34 | int gameOverMsec;
35 | int gameStartMsec;
36 |
37 | int msecPerCountdownTick;
38 | int numCountdownTicks;
39 |
40 | int randomSeed;
41 |
42 | ///////////////////////////
43 | // Initialisation
44 |
45 | void initialise()
46 | {
47 | // game state enum
48 | gameState_Over = 0;
49 | gameState_Prepare = 1;
50 | gameState_Play = 2;
51 |
52 | gameState = gameState_Over;
53 |
54 | enemySpeedIncreasePerKill = 0.03;
55 |
56 | bulletSpeedY = 0.5;
57 |
58 | highScore = 0;
59 |
60 | explosionGrowPerFrame = 0.6;
61 | explosionMax = 5.0;
62 |
63 | gameOverMsec = -9999;
64 |
65 | msecPerCountdownTick = 500;
66 | numCountdownTicks = 3;
67 |
68 | for (int i = 0; i < 32; ++i)
69 | setLocalConfigActiveState (i, false, false);
70 | }
71 |
72 | ///////////////////////////
73 | // Utilities
74 |
75 | float getRandom01()
76 | {
77 | while(true)
78 | {
79 | randomSeed = 214013 * randomSeed + 2531011;
80 | int rndInt = (randomSeed >> 16) & 0x7fff;
81 | float f01 = float(rndInt) / 32768.0;
82 | if (f01 >= 0.0 && f01 < 1.0)
83 | return f01;
84 | }
85 | return 0.0;
86 | }
87 |
88 | float getRandomInRange(float start, float rangeExclusive)
89 | {
90 | float rnd = getRandom01();
91 | return start + (rangeExclusive - 0.0001) * rnd;
92 | }
93 |
94 | ///////////////////////////
95 | // Game Logic
96 |
97 | void startGame()
98 | {
99 | randomSeed = getMillisecondCounter();
100 |
101 | gameState = gameState_Play;
102 |
103 | playerX = 8.0;
104 | playerY = 12.0;
105 | targetPlayerX = 8.0;
106 | playerSpeedX = 0.3;
107 |
108 | enemySpeedY = 0.1;
109 |
110 | bulletX = -99.0;
111 | score = 0;
112 |
113 | explosionX = -1.0;
114 | explosionY = -1.0;
115 | explosionWidth = 0.0;
116 |
117 | spawnEnemy();
118 | }
119 |
120 | void setPlayerTarget02(float x02)
121 | {
122 | targetPlayerX = float(x02) / 2.0 * 15.0;
123 | }
124 |
125 | void spawnEnemy()
126 | {
127 | enemyY = 0.0;
128 | enemyX = getRandomInRange(1.0, 13.0);
129 | }
130 |
131 | void spawnBullet()
132 | {
133 | bulletX = playerX;
134 | bulletY = playerY - 1.0;
135 | }
136 |
137 | void updatePlayer()
138 | {
139 | playerX = playerX + (targetPlayerX - playerX) * playerSpeedX;
140 | }
141 |
142 | void updateEnemy()
143 | {
144 | enemyY += enemySpeedY;
145 | }
146 |
147 | void updateBullet()
148 | {
149 | bulletY -= bulletSpeedY;
150 | if (bulletY < 0)
151 | bulletX = -1;
152 | }
153 |
154 | void updateExplosion()
155 | {
156 | if (explosionX >= 0.0)
157 | {
158 | explosionWidth += explosionGrowPerFrame;
159 | if (explosionWidth > explosionMax)
160 | {
161 | explosionX = -1.0;
162 | }
163 | }
164 | }
165 |
166 | void destroyEnemy()
167 | {
168 | bulletX = -99.0;
169 | bulletY = -1;
170 | explosionX = enemyX;
171 | explosionY = enemyY;
172 | explosionWidth = 1.0;
173 |
174 | enemySpeedY += enemySpeedIncreasePerKill;
175 | score++;
176 | }
177 |
178 | void detectCollisions()
179 | {
180 | if (bulletX >= 0)
181 | {
182 | int ydist = abs(int(bulletY)- int(enemyY));
183 | if (ydist < 3)
184 | {
185 | int dist = abs(int(bulletX) - int(enemyX));
186 | if (dist < 3)
187 | {
188 | destroyEnemy();
189 | spawnEnemy();
190 | }
191 | }
192 | }
193 | }
194 |
195 | void detectGameOver()
196 | {
197 | if (enemyY > 13)
198 | {
199 | gameState = gameState_Over;
200 | if (score > highScore)
201 | {
202 | highScore = score;
203 | gameOverMsec = getMillisecondCounter();
204 | }
205 | }
206 | }
207 |
208 | void updatePrepare()
209 | {
210 | int msecSinceStart = getMillisecondCounter() - gameStartMsec;
211 | if (msecSinceStart > numCountdownTicks * msecPerCountdownTick)
212 | {
213 | startGame();
214 | }
215 | }
216 |
217 | void updateGame()
218 | {
219 | updatePlayer();
220 | updateEnemy();
221 | updateBullet();
222 | updateExplosion();
223 |
224 | detectCollisions();
225 | detectGameOver();
226 | }
227 |
228 | ///////////////////////////
229 | // Input detection
230 |
231 | void touchStart(int index, float touchX02, float touchY, float touchZ, float touchScale)
232 | {
233 | if (gameState == gameState_Over)
234 | {
235 | if (getMillisecondCounter() - gameOverMsec > 1000)
236 | {
237 | gameStartMsec = getMillisecondCounter();
238 | gameState = gameState_Prepare;
239 | }
240 | }
241 | else if (gameState == gameState_Play)
242 | {
243 | setPlayerTarget02(touchX02);
244 | }
245 | }
246 |
247 | void touchMove(int index, float touchX02, float touchY, float touchZ, float touchScale)
248 | {
249 | setPlayerTarget02(touchX02);
250 | }
251 |
252 | void touchEnd(int index, float touchX02, float touchY, float touchZ, float touchScale)
253 | {
254 | if (gameState == gameState_Play)
255 | {
256 | spawnBullet();
257 | }
258 | }
259 |
260 | ///////////////////////////
261 | // Drawing
262 |
263 | void drawBullet()
264 | {
265 | if (bulletX >= 0.0)
266 | fillRect(0xffffffff, int(bulletX) - 1, int(bulletY), 3, 3);
267 | }
268 |
269 | void drawPlayer()
270 | {
271 | int col = 0xff0000ff;
272 | int px = int(playerX);
273 | int py = int(playerY);
274 | fillPixel (col, px + 0, py + 0);
275 | fillPixel (col, px - 1, py + 1);
276 | fillPixel (col, px + 0, py + 1);
277 | fillPixel (col, px + 1, py + 1);
278 | fillPixel (col, px - 1, py + 2);
279 | fillPixel (col, px + 1, py + 2);
280 | }
281 |
282 | void drawEnemy()
283 | {
284 | int col = 0xffff0000;
285 | int px = int(enemyX);
286 | int py = int(enemyY);
287 | fillPixel (col, px + 0, py + 2);
288 | fillPixel (col, px - 1, py + 1);
289 | fillPixel (col, px + 0, py + 1);
290 | fillPixel (col, px + 1, py + 1);
291 | fillPixel (col, px - 1, py + 0);
292 | fillPixel (col, px + 1, py + 0);
293 | }
294 |
295 | void drawExplosion()
296 | {
297 | if (explosionX >= 0.0)
298 | {
299 | blendRect(0x80ffffff, int(explosionX + explosionWidth) + 1, int(explosionY), 2, 1);
300 | blendRect(0x80ffffff, int(explosionX - explosionWidth) - 1, int(explosionY), 2, 1);
301 | }
302 | }
303 |
304 | void repaintPlay()
305 | {
306 | blendRect(0x30000000, 0, 0, 15, 15);
307 | drawPlayer();
308 | drawEnemy();
309 | drawBullet();
310 | drawExplosion();
311 | }
312 |
313 | void repaintGameOver()
314 | {
315 | fillRect(0xff00ff00, 0, 0, 15, 15);
316 | fillRect(0xff000000, 1, 1, 13, 13);
317 | drawNumber(score, 0xffffffff, 2, 2);
318 | drawNumber(highScore, 0xffffffff, 2, 8);
319 | }
320 |
321 | void repaintPrepare()
322 | {
323 | fillRect(0xff000000, 0, 0, 15, 15);
324 | int msecSinceStart = getMillisecondCounter() - gameStartMsec;
325 | int counterDigit = (numCountdownTicks * msecPerCountdownTick - msecSinceStart) / msecPerCountdownTick + 1;
326 | drawNumber(counterDigit, 0xffffffff, 5, 5);
327 | }
328 |
329 | void repaint()
330 | {
331 | if (gameState == gameState_Play)
332 | {
333 | updateGame();
334 | repaintPlay();
335 | }
336 | else if (gameState == gameState_Prepare)
337 | {
338 | repaintPrepare();
339 | updatePrepare();
340 | }
341 | else
342 | {
343 | repaintGameOver();
344 | }
345 | }
346 |
347 | /*
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 | */
--------------------------------------------------------------------------------
/Factory Scripts/BreakBLOCKS.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | */
11 |
12 | int paddlePos;
13 | int paddleWidth;
14 | bool down;
15 | int seed;
16 | int ballXVec;
17 | int ballYVec;
18 | int ballX;
19 | int ballY;
20 | int advanceCount;
21 |
22 | bool gameIsOver;
23 | bool gameIsPaused;
24 | int gameOverCoverIndex;
25 | int gameOverCoverCount;
26 | int gameStartMsec;
27 |
28 | #heapsize: 1
29 |
30 | void resetState()
31 | {
32 | gameIsPaused = true;
33 | gameIsOver = false;
34 |
35 | paddleWidth = 4;
36 | paddlePos = 7;
37 | seed = 5;
38 |
39 | ballX = 7;
40 | ballY = 10;
41 | ballYVec = -1;
42 | if (getRandomInt (255) > 127)
43 | {
44 | ballXVec = 1;
45 | }
46 | else
47 | {
48 | ballXVec = -1;
49 | }
50 |
51 | int seedColour = makeARGB (255, getRandomInt (255), getRandomInt (255), getRandomInt (255));
52 | for (int i = 0; i < 20; ++i)
53 | {
54 | int r = (((seedColour >> 16) & 0xFF) + getRandomInt (255)) % 255;
55 | int g = (((seedColour >> 8) & 0xFF) + getRandomInt (255)) % 255;
56 | int b = (((seedColour) & 0xFF) + getRandomInt (255)) % 255;
57 |
58 | seedColour = makeARGB (255, b, r, g); // Yep, lets really mess things up
59 | setBrickCol (i, seedColour);
60 | setBrick (i, true);
61 | }
62 | }
63 |
64 | void initialise()
65 | {
66 | resetState();
67 | startNewGame();
68 | for (int i = 0; i < 32; ++i)
69 | setLocalConfigActiveState (i, false, false);
70 | }
71 |
72 | void handleTouch (int index, float x, float y, float z, float vz)
73 | {
74 | if (! gameIsOver)
75 | {
76 | paddlePos = int ((x * 0.5) * 15.0);
77 | paddlePos = clamp (paddleWidth / 2, 15 - (paddleWidth / 2), paddlePos);
78 | }
79 | }
80 |
81 | void touchStart (int index, float x, float y, float z, float vz)
82 | {
83 | handleTouch (index, x, y, z, vz);
84 | }
85 |
86 | void touchMove (int index, float x, float y, float z, float vz)
87 | {
88 | handleTouch (index, x, y, z, vz);
89 | }
90 |
91 | void touchEnd (int index, float x, float y, float z, float vz)
92 | {
93 | handleTouch (index, x, y, z, vz);
94 | }
95 |
96 | int getBrickX (int brickIndex)
97 | {
98 | return (brickIndex / 4) * 3;
99 | }
100 |
101 | int getBrickRight (int brickIndex)
102 | {
103 | return getBrickX (brickIndex) + 3;
104 | }
105 |
106 | int getBrickY (int brickIndex)
107 | {
108 | return (brickIndex % 4) * 2;
109 | }
110 |
111 | int getBrickBottom (int brickIndex)
112 | {
113 | return getBrickY (brickIndex) + 2;
114 | }
115 |
116 | void handleButtonDown (int index)
117 | {
118 | initialise();
119 | }
120 |
121 | void paintComponents()
122 | {
123 | if (! gameIsPaused)
124 | {
125 | clearDisplay();
126 | for (int i = 0; i < 20; ++i)
127 | {
128 | if (getBrick (i))
129 | {
130 | fillRect (getBrickCol (i), getBrickX (i), getBrickY (i), 3, 2);
131 | }
132 | }
133 | fillRect (0xFF0000, paddlePos - (paddleWidth / 2), 14, paddleWidth, 1);
134 | fillRect (0x00FF00, ballX, ballY, 1, 1);
135 | }
136 |
137 | if (! gameIsOver && gameIsPaused)
138 | {
139 | clearDisplay();
140 | int msecSinceStart = getMillisecondCounter() - gameStartMsec;
141 | int counterDigit = max (0, (3 * 500 - msecSinceStart) / 500 + 1);
142 | if (counterDigit == 0)
143 | {
144 | resetState();
145 | gameIsPaused = false;
146 | gameIsOver = false;
147 | }
148 | else
149 | {
150 | drawNumber(counterDigit, 0xffffffff, 5, 8);
151 | }
152 | }
153 | }
154 |
155 | void advance()
156 | {
157 | if (gameIsPaused)
158 | {
159 | return;
160 | }
161 |
162 | if (++advanceCount % 2 != 0)
163 | {
164 | return;
165 | }
166 |
167 | ballY += ballYVec;
168 | ballX += ballXVec;
169 |
170 | if (ballX < 0)
171 | {
172 | ballX = 0;
173 | ballXVec = -ballXVec;
174 | }
175 | else if (ballX > 14)
176 | {
177 | ballX = 14;
178 | ballXVec = -ballXVec;
179 | }
180 |
181 | if (ballY < 0)
182 | {
183 | ballY = 0;
184 | ballYVec = -ballYVec;
185 | }
186 | else if (ballY >= 14)
187 | {
188 | if (ballX >= paddlePos - (paddleWidth / 2) && ballX < paddlePos + (paddleWidth / 2))
189 | {
190 | ballYVec = -ballYVec;
191 | }
192 | else
193 | {
194 | triggerGameOver();
195 | return;
196 | }
197 | }
198 |
199 | bool hitOne = false;
200 | for (int i = 19; i >= 0; --i)
201 | {
202 | if (! hitOne &&
203 | getBrick (i) &&
204 | ballY <= getBrickBottom (i) &&
205 | ballX >= getBrickX (i) &&
206 | ballX < getBrickRight (i))
207 | {
208 | ballYVec = 1;
209 | setBrick (i, false);
210 | paintComponents();
211 | hitOne = true;
212 | }
213 | }
214 |
215 | bool foundABrick = false;
216 | for (int i = 0; i < 20; ++i)
217 | {
218 | if (getBrick (i))
219 | {
220 | foundABrick = true;
221 | break;
222 | }
223 | }
224 |
225 | if (! foundABrick)
226 | {
227 | triggerGameOver();
228 | }
229 | }
230 |
231 | void triggerGameOver()
232 | {
233 | gameIsOver = true;
234 | gameOverCoverIndex = 0;
235 | gameOverCoverCount = 2;
236 | gameIsPaused = true;
237 | }
238 |
239 | void startNewGame()
240 | {
241 | gameStartMsec = getMillisecondCounter();
242 | gameIsOver = false;
243 | }
244 |
245 | void showGameOver()
246 | {
247 | fillRect (0x000000, 0, 0, 15, gameOverCoverIndex);
248 | if (--gameOverCoverCount < 0)
249 | {
250 | gameOverCoverCount = 2;
251 | if (++gameOverCoverIndex == 15)
252 | {
253 | gameOverCoverIndex = 15;
254 | startNewGame();
255 | }
256 | }
257 | }
258 |
259 | void repaint()
260 | {
261 | paintComponents();
262 | if (! gameIsOver)
263 | advance();
264 | else
265 | showGameOver();
266 | }
267 |
268 | /*
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 | */
345 |
--------------------------------------------------------------------------------
/Factory Scripts/RISE Controller.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | */
28 |
29 | int view;
30 | const int faderView = 0;
31 | const int xyPadView = 1;
32 |
33 | int slider0;
34 | int slider1;
35 | int slider2;
36 |
37 | void initialise()
38 | {
39 | view = faderView;
40 |
41 | slider0 = slider1 = slider2 = 64;
42 |
43 | for (int i = 0; i < 32; ++i)
44 | setLocalConfigActiveState (i, false, false);
45 | }
46 |
47 | int mapTouchToRange (float v, float max)
48 | {
49 | return int (map (v, 7.0 / 100.0, 193.0 / 100.0, 0.0, max));
50 | }
51 |
52 | void handleTouchFader (int index, float x, float y, float z, float vz)
53 | {
54 | int xPixel = mapTouchToRange (x, 14.0);
55 | int yValue = 127 - mapTouchToRange (y, 127.0);
56 |
57 | if (xPixel < 5)
58 | {
59 | slider0 = yValue;
60 | sendCC ((channel - 1), s0CC, slider0);
61 | }
62 | if (xPixel >= 5 && xPixel < 10)
63 | {
64 | slider1 = yValue;
65 | sendCC ((channel - 1), s1CC, slider1);
66 | }
67 | if (xPixel >= 10)
68 | {
69 | slider2 = yValue;
70 | sendCC ((channel - 1), s2CC, slider2);
71 | }
72 | }
73 |
74 | int mapTouchToRange (float v, float inMin, float inMax, float outMax)
75 | {
76 | return int (map (v, inMin / 100.0, inMax / 100.0, 0.0, outMax));
77 | }
78 |
79 | void outputCC (float v, int cc, float inMin, float inMax, bool invert)
80 | {
81 | int value = mapTouchToRange (v, inMin, inMax, 127.0);
82 | if (invert)
83 | value = 127 - value;
84 |
85 | sendCC ((channel - 1), cc, value);
86 | }
87 |
88 | void handleTouchXYPad (int index, float x, float y, float z, float vz)
89 | {
90 |
91 | addPressurePoint (xyzColour, x, y, z * 20.0);
92 |
93 | if (send == 0 || send == 1) outputCC (x, xCC, 7.0, 193.0, false);
94 | if (send == 0 || send == 2) outputCC (y, yCC, 7.0, 193.0, true);
95 | }
96 |
97 | void handleTouch (int index, float x, float y, float z, float vz)
98 | {
99 | if (view == faderView)
100 | handleTouchFader (index, x, y, z, vz);
101 |
102 | if (view == xyPadView)
103 | handleTouchXYPad (index, x, y, z, vz);
104 | }
105 |
106 | void touchStart (int index, float x, float y, float z, float vz)
107 | {
108 | handleTouch (index, x, y, z, vz);
109 | }
110 |
111 | void touchMove (int index, float x, float y, float z, float vz)
112 | {
113 | handleTouch (index, x, y, z, vz);
114 | }
115 |
116 | void touchEnd (int index, float x, float y, float z, float vz)
117 | {
118 | handleTouch (index, x, y, z, vz);
119 | }
120 |
121 | void handleButtonDown (int index)
122 | {
123 | if (view == faderView)
124 | view = xyPadView;
125 | else
126 | view = faderView;
127 | }
128 |
129 | void repaint()
130 | {
131 | clearDisplay();
132 |
133 | if (view == faderView)
134 | paintFaderView();
135 |
136 | if (view == xyPadView)
137 | paintXYPadView();
138 | }
139 |
140 | void paintFaderView()
141 | {
142 | int slider0DrawableHeight = int (map (float (slider0), 0.0, 127.0, 1.0, 15.0));
143 | int slider1DrawableHeight = int (map (float (slider1), 0.0, 127.0, 1.0, 15.0));
144 | int slider2DrawableHeight = int (map (float (slider2), 0.0, 127.0, 1.0, 15.0));
145 |
146 | fillRect (s0Colour, 0, 15 - slider0DrawableHeight, 4, slider0DrawableHeight);
147 | fillRect (s1Colour, 5, 15 - slider1DrawableHeight, 4, slider1DrawableHeight);
148 | fillRect (s2Colour, 10, 15 - slider2DrawableHeight, 4, slider2DrawableHeight);
149 | }
150 |
151 | void paintXYPadView()
152 | {
153 | fillRect (xyzBackColour, 0, 0, 15, 15);
154 | drawPressureMap();
155 | fadePressureMap();
156 | }
157 |
158 | /*
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 | */
--------------------------------------------------------------------------------
/Factory Scripts/Fader Block.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | */
22 |
23 | int bank;
24 | int clusterSize;
25 | bool bankButtonEnabled;
26 | int clusterUpdateStage;
27 | int sliderChangeMessage;
28 |
29 | int getFirstSliderIndexForBank ()
30 | {
31 | return bank * 4;
32 | }
33 |
34 | int sliderIndexForX (float x)
35 | {
36 | float x01 = x * 0.5;
37 |
38 | // Each slider has an area of 3px + 1px gap. We want the gaps to be dead zones..
39 | int ledZone = int (x01 * 15);
40 |
41 | if (ledZone <= 3) return 0;
42 | if (ledZone >= 4 && ledZone <= 7) return 1;
43 | if (ledZone >= 8 && ledZone <= 11) return 2;
44 | if (ledZone >= 12 && ledZone <= 15) return 3;
45 |
46 | return -1;
47 | }
48 |
49 | bool sliderIsInBank (int sliderIndex)
50 | {
51 | int bankStart = getFirstSliderIndexForBank();
52 | int bankEnd = bankStart + 4;
53 | return (sliderIndex >= bankStart && sliderIndex < bankEnd);
54 | }
55 |
56 | int getSliderMaxValueForClusterSize (int theClusterSize)
57 | {
58 | if (theClusterSize == 1)
59 | return 13;
60 |
61 | return 15;
62 | }
63 |
64 | int getSliderMaxValue()
65 | {
66 | return getSliderMaxValueForClusterSize (clusterSize);
67 | }
68 |
69 | float getSliderMinValue()
70 | {
71 | if (clusterSize == 1)
72 | {
73 | return 2.0;
74 | }
75 |
76 | return 0.0;
77 | }
78 |
79 | float getSliderValue01ForTouchAtY (float y)
80 | {
81 | float sliderMax = 14.0;
82 | float sliderMin = getSliderMinValue();
83 | float sliderRange = sliderMax - sliderMin;
84 |
85 | float closestLED = clamp (sliderMin, sliderMax, float (y * 14));
86 | float value01 = ((closestLED - sliderMin) / sliderRange);
87 | return 1.0 - value01;
88 | }
89 |
90 | int convertSliderValue01ToRange (float slider01, int sliderMin, int sliderMax, int hardMax)
91 | {
92 | return clamp (0x00, hardMax, sliderMin + int (slider01 * float (sliderMax - sliderMin)));
93 | }
94 |
95 | int convertSliderValue01ToOutputRange (int sliderIndex, float slider01)
96 | {
97 | return convertSliderValue01ToRange (slider01, getSliderMin (sliderIndex), getSliderMax (sliderIndex), 0x7F);
98 | }
99 |
100 | void doTouch (int index, float x, float y, float z, float vz)
101 | {
102 | int sliderIndex = sliderIndexForX(x) + getFirstSliderIndexForBank();
103 | if (sliderIndex >= 0)
104 | {
105 | int currentValue = getSlider (sliderIndex);
106 | float slider01 = getSliderValue01ForTouchAtY (y * 0.5);
107 | int midiValue = convertSliderValue01ToOutputRange (sliderIndex, slider01);
108 | int newValue = convertSliderValue01ToRange (slider01, 1, getSliderMaxValue(), getSliderMaxValue());
109 |
110 | setSlider (sliderIndex, newValue);
111 |
112 | if (clusterSize != 1 && currentValue != newValue)
113 | {
114 | sendSliderValueMessage (sliderIndex, newValue);
115 | }
116 |
117 | sendMIDI (0xB0 | (midiChannel - 1), getCc (sliderIndex), midiValue);
118 | }
119 | }
120 |
121 | void touchStart (int index, float x, float y, float z, float vz)
122 | {
123 | doTouch (index, x, y, z, vz);
124 | }
125 |
126 | void touchMove (int index, float x, float y, float z, float vz)
127 | {
128 | doTouch (index, x, y, z, vz);
129 | }
130 |
131 | void handleButtonDown (int index)
132 | {
133 | if (bankButtonEnabled)
134 | {
135 | bank = (bank + 1) % 4;
136 | }
137 | }
138 |
139 | void paintBankIndicator()
140 | {
141 | if (clusterSize == 1)
142 | {
143 | fillRect (makeARGB (255, 255, 0, 0), getFirstSliderIndexForBank(), 0, 3, 1);
144 | }
145 | }
146 |
147 | void paintSliders()
148 | {
149 | int bankStart = getFirstSliderIndexForBank();
150 | for (int slider = 0; slider < 4; ++slider)
151 | {
152 | int sliderIndex = slider + bankStart;
153 | int sliderValue = getSlider (sliderIndex);
154 | int sliderColour = getColour (sliderIndex);
155 | fillRect (sliderColour, slider * 4, 15 - sliderValue, 3, sliderValue);
156 | }
157 | }
158 |
159 | void repaint()
160 | {
161 | clearDisplay();
162 | paintBankIndicator();
163 | paintSliders();
164 | updateClustering();
165 | }
166 |
167 |
168 | void zeroSliders()
169 | {
170 | for (int i = 0; i < 16; ++i)
171 | setSlider (i, 1);
172 | }
173 |
174 | void initialise()
175 | {
176 | sliderChangeMessage = 0x7F2E;
177 |
178 | clusterUpdateStage = -1;
179 | zeroSliders();
180 | updateClusterPosition();
181 | notifyOtherBlocksInClusterOfSliderValues();
182 |
183 | for (int i = 0; i < 32; ++i)
184 | setLocalConfigActiveState (i, false, false);
185 | }
186 |
187 | void updateClusterPosition()
188 | {
189 | clusterSize = getClusterWidth();
190 |
191 | if (clusterSize == 1)
192 | {
193 | bank = 0;
194 | bankButtonEnabled = true;
195 | }
196 | else
197 | {
198 | bank = getClusterXpos();
199 | bankButtonEnabled = false;
200 | }
201 | }
202 |
203 | void updateClustering()
204 | {
205 | int newClusterSize = getClusterWidth();
206 | if (clusterSize != newClusterSize)
207 | {
208 | if (newClusterSize == 1)
209 | rescaleSliders (false);
210 | else if (newClusterSize > 1 && clusterSize == 1)
211 | rescaleSliders (true);
212 |
213 | updateClusterPosition();
214 | notifyOtherBlocksInClusterOfSliderValues();
215 | }
216 | }
217 |
218 | void notifyOtherBlocksInClusterOfSliderValues()
219 | {
220 | if (isMasterInCurrentCluster() && clusterSize != 1)
221 | {
222 | int ourID = getBlockIDForIndex (0);
223 | for (int clusterIndex = 0; clusterIndex < getNumBlocksInCurrentCluster(); ++clusterIndex)
224 | {
225 | int id = getBlockIdForBlockInCluster (clusterIndex);
226 |
227 | if (id == ourID)
228 | continue;
229 |
230 | for (int slider = 0; slider < 16; ++slider)
231 | sendMessageToBlock (id, sliderChangeMessage, slider, getSlider (slider));
232 | }
233 | }
234 | }
235 |
236 | void handleMessage (int data0, int data1, int data2)
237 | {
238 | if (data0 == sliderChangeMessage)
239 | setSlider (data1, data2);
240 | }
241 |
242 | void sendSliderValueMessage (int slider, int value)
243 | {
244 | int ourID = getBlockIDForIndex (0);
245 | for (int clusterIndex = 0; clusterIndex < getNumBlocksInCurrentCluster(); ++clusterIndex)
246 | {
247 | int id = getBlockIdForBlockInCluster (clusterIndex);
248 |
249 | if (id == ourID)
250 | continue;
251 |
252 | sendMessageToBlock (id, sliderChangeMessage, slider, value);
253 | }
254 | }
255 |
256 | void rescaleSliders (bool isNowClustering)
257 | {
258 | float nonClusterMax = float (getSliderMaxValueForClusterSize (1));
259 | float clusterMax = float (getSliderMaxValueForClusterSize (4));
260 |
261 | if (isNowClustering)
262 | {
263 | for (int slider = 0; slider < 16; ++slider)
264 | setSlider (slider, int ((float (getSlider (slider)) / nonClusterMax) * clusterMax));
265 | }
266 | else
267 | {
268 | for (int slider = 0; slider < 16; ++slider)
269 | setSlider (slider, int ((float (getSlider (slider)) / clusterMax) * nonClusterMax));
270 | }
271 | }
272 |
273 |
274 | /*
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 | */
--------------------------------------------------------------------------------
/Factory Scripts/XYZ Pad.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | */
16 |
17 | void initialise()
18 | {
19 | for (int i = 0; i < 32; ++i)
20 | setLocalConfigActiveState (i, false, false);
21 | }
22 |
23 | int mapTouchToRange (float v, float inMin, float inMax, float outMax)
24 | {
25 | return int (map (v, inMin / 100.0, inMax / 100.0, 0.0, outMax));
26 | }
27 |
28 | void outputCC (float v, int cc, float inMin, float inMax, bool invert)
29 | {
30 | int value = mapTouchToRange (v, inMin, inMax, 127.0);
31 | if (invert)
32 | value = 127 - value;
33 |
34 | sendCC ((channel - 1), cc, value);
35 | }
36 |
37 | void handleTouch (int index, float x, float y, float z, float scale)
38 | {
39 | if (index == 1)
40 | {
41 | addPressurePoint (colour, x, y, z * scale);
42 |
43 | if (send == 0 || send == 1) outputCC (x, xCC, 7.0, 193.0, false);
44 | if (send == 0 || send == 2) outputCC (y, yCC, 7.0, 193.0, true);
45 | if (send == 0 || send == 3) outputCC (z, zCC, 0.0, 100.0, false);
46 | }
47 | }
48 |
49 | void touchStart (int index, float x, float y, float z, float vz)
50 | {
51 | handleTouch (index, x, y, z, 75.0);
52 | }
53 |
54 | void touchMove (int index, float x, float y, float z, float vz)
55 | {
56 | handleTouch (index, x, y, z, 20.0);
57 | }
58 |
59 | void repaint()
60 | {
61 | fillRect (backgroundColour, 0, 0, 15, 15);
62 | drawPressureMap();
63 | fadePressureMap();
64 | }
65 |
66 | /*
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 | */
297 |
--------------------------------------------------------------------------------
/Example Scripts/MusicGen.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | */
10 |
11 | int green;
12 | int red;
13 | int blue;
14 | int yellow;
15 | int count;
16 |
17 | float bullet1x;
18 | float bullet1y;
19 | float bullet2x;
20 | float bullet2y;
21 | float bullet3x;
22 | float bullet3y;
23 | float bullet4x;
24 | float bullet4y;
25 | float bullet5x;
26 | float bullet5y;
27 |
28 | int bullet1d;
29 | int bullet2d;
30 | int bullet3d;
31 | int bullet4d;
32 | int bullet5d;
33 |
34 | int blob1x;
35 | int blob1y;
36 | int blob2x;
37 | int blob2y;
38 | int blob3x;
39 | int blob3y;
40 | int blob4x;
41 | int blob4y;
42 | int blob5x;
43 | int blob5y;
44 |
45 | int blob1d;
46 | int blob2d;
47 | int blob3d;
48 | int blob4d;
49 | int blob5d;
50 |
51 | int lastNote1;
52 | int lastNote2;
53 | int lastNote3;
54 | int lastNote4;
55 | int lastNote5;
56 |
57 | void initialise()
58 | {
59 | clearDisplay();
60 |
61 | sendCC (0, 120, 127);
62 |
63 | blob1x = -99;
64 | blob2x = -99;
65 | blob3x = -99;
66 | blob4x = -99;
67 | blob5x = -99;
68 |
69 | blob1y = -99;
70 | blob2y = -99;
71 | blob3y = -99;
72 | blob4y = -99;
73 | blob5y = -99;
74 |
75 | blob1d = 3;
76 | blob2d = 3;
77 | blob3d = 3;
78 | blob4d = 3;
79 | blob5d = 3;
80 |
81 | bullet1x = -99;
82 | bullet2x = -99;
83 | bullet3x = -99;
84 | bullet4x = -99;
85 | bullet5x = -99;
86 |
87 | bullet1y = -99;
88 | bullet2y = -99;
89 | bullet3y = -99;
90 | bullet4y = -99;
91 | bullet5y = -99;
92 |
93 | green = 0x2200FF00;
94 | red = 0x22FF0000;
95 | blue = 0x220000FF;
96 | yellow = 0x22FFFF00;
97 |
98 | count = 0;
99 | }
100 |
101 | // Detect touches
102 | void touchStart (int touchIndex, float x, float y, float z, float vz)
103 | {
104 | int intX = int (x * 7);
105 | int intY = int (y * 7);
106 |
107 | int touch = touchBlob (intX, intY);
108 |
109 | if (touch >= 1)
110 | {
111 | changeBlob (touch);
112 | }
113 | else if (count < 5)
114 | {
115 | if (z < 0.05)
116 | {
117 | assignBlob (intX, intY, count, 0);
118 | }
119 | else if (z < 0.2)
120 | {
121 | assignBlob (intX, intY, count, 1);
122 | }
123 | else if (z < 0.5)
124 | {
125 | assignBlob (intX, intY, count, 2);
126 | }
127 | else
128 | {
129 | assignBlob (intX, intY, count, 3);
130 | }
131 |
132 | ++count;
133 | }
134 | }
135 |
136 | //Detect if touch is on a Blob
137 | int touchBlob (int x, int y)
138 | {
139 | int touch = 0;
140 |
141 | if (x >= (blob1x - 1) && x <= (blob1x + 1) && y >= (blob1y - 1) && y <= (blob1y + 1))
142 | {
143 | touch = 1;
144 | }
145 | else if (x >= (blob2x - 1) && x <= (blob2x + 1) && y >= (blob2y - 1) && y <= (blob2y + 1))
146 | {
147 | touch = 2;
148 | }
149 | else if (x >= (blob3x - 1) && x <= (blob3x + 1) && y >= (blob3y - 1) && y <= (blob3y + 1))
150 | {
151 | touch = 3;
152 | }
153 | else if (x >= (blob4x - 1) && x <= (blob4x + 1) && y >= (blob4y - 1) && y <= (blob4y + 1))
154 | {
155 | touch = 4;
156 | }
157 | else if (x >= (blob5x - 1) && x <= (blob5x + 1) && y >= (blob5y - 1) && y <= (blob5y + 1))
158 | {
159 | touch = 5;
160 | }
161 |
162 | return touch;
163 | }
164 |
165 | void changeBlob (int blob)
166 | {
167 | if (blob == 1)
168 | {
169 | if (blob1d < 3)
170 | {
171 | ++blob1d;
172 | }
173 | else
174 | {
175 | blob1d = 0;
176 | }
177 | }
178 | else if (blob == 2)
179 | {
180 | if (blob2d < 3)
181 | {
182 | ++blob2d;
183 | }
184 | else
185 | {
186 | blob2d = 0;
187 | }
188 | }
189 | else if (blob == 3)
190 | {
191 | if (blob3d < 3)
192 | {
193 | ++blob3d;
194 | }
195 | else
196 | {
197 | blob3d = 0;
198 | }
199 | }
200 | else if (blob == 4)
201 | {
202 | if (blob4d < 3)
203 | {
204 | ++blob4d;
205 | }
206 | else
207 | {
208 | blob4d = 0;
209 | }
210 | }
211 | else if (blob == 5)
212 | {
213 | if (blob5d < 3)
214 | {
215 | ++blob5d;
216 | }
217 | else
218 | {
219 | blob5d = 0;
220 | }
221 | }
222 | }
223 |
224 | // Blob Creation and Assignment!
225 | void paintBlob (int x, int y, int type)
226 | {
227 | if (type == 0)
228 | {
229 | fillRect (green, x, y - 1, 1, 2);
230 | blendRect (green, x - 1, y, 3, 1);
231 | }
232 | else if (type == 1)
233 | {
234 | fillRect (red, x, y, 2, 1);
235 | blendRect (red, x, y - 1, 1, 3);
236 | }
237 | else if (type == 2)
238 | {
239 | fillRect (blue, x, y, 1, 2);
240 | blendRect (blue, x - 1, y, 3, 1);
241 | }
242 | else if (type == 3)
243 | {
244 | fillRect (yellow, x - 1, y, 2, 1);
245 | blendRect (yellow, x, y - 1, 1, 3);
246 | }
247 | }
248 |
249 | void assignBlob (int x, int y, int index, int type)
250 | {
251 | if (index == 0)
252 | {
253 | blob1x = x;
254 | blob1y = y;
255 | blob1d = type;
256 | spawnBullet1();
257 | }
258 | else if (index == 1)
259 | {
260 | blob2x = x;
261 | blob2y = y;
262 | blob2d = type;
263 | spawnBullet2();
264 | }
265 | else if (index == 2)
266 | {
267 | blob3x = x;
268 | blob3y = y;
269 | blob3d = type;
270 | spawnBullet3();
271 | }
272 | else if (index == 3)
273 | {
274 | blob4x = x;
275 | blob4y = y;
276 | blob4d = type;
277 | spawnBullet4();
278 | }
279 | else if (index == 4)
280 | {
281 | blob5x = x;
282 | blob5y = y;
283 | blob5d = type;
284 | spawnBullet5();
285 | }
286 | }
287 |
288 | // Make Bullets!
289 | void spawnBullet1()
290 | {
291 | bullet1x = blob1x;
292 | bullet1y = blob1y;
293 | bullet1d = blob1d;
294 | }
295 |
296 | void spawnBullet2()
297 | {
298 | bullet2x = blob2x;
299 | bullet2y = blob2y;
300 | bullet2d = blob2d;
301 | }
302 |
303 | void spawnBullet3()
304 | {
305 | bullet3x = blob3x;
306 | bullet3y = blob3y;
307 | bullet3d = blob3d;
308 | }
309 |
310 | void spawnBullet4()
311 | {
312 | bullet4x = blob4x;
313 | bullet4y = blob4y;
314 | bullet4d = blob4d;
315 | }
316 |
317 | void spawnBullet5()
318 | {
319 | bullet5x = blob5x;
320 | bullet5y = blob5y;
321 | bullet5d = blob5d;
322 | }
323 |
324 | void drawBullet (float x, float y, int d)
325 | {
326 | fillPixel (0xFF222222, int (x), int (y));
327 |
328 | if (d == 0)
329 | {
330 | fillPixel (0xFFFFFF, int (x), int (y - 1));
331 | }
332 | else if (d == 1)
333 | {
334 | fillPixel (0xFFFFFF, int (x + 1), int (y));
335 | }
336 | else if (d == 2)
337 | {
338 | fillPixel (0xFFFFFF, int (x), int (y + 1));
339 | }
340 | else
341 | {
342 | fillPixel (0xFFFFFF, int (x - 1), int (y));
343 | }
344 | }
345 |
346 | void updateBullet1()
347 | {
348 | if (blob1d == 0)
349 | {
350 | bullet1y -= speed;
351 | }
352 | else if (blob1d == 1)
353 | {
354 | bullet1x += speed;
355 | }
356 | else if (blob1d == 2)
357 | {
358 | bullet1y += speed;
359 | }
360 | else if (blob1d == 3)
361 | {
362 | bullet1x -= speed;
363 | }
364 | }
365 |
366 | void updateBullet2()
367 | {
368 | if (blob2d == 0)
369 | {
370 | bullet2y -= speed;
371 | }
372 | else if (blob2d == 1)
373 | {
374 | bullet2x += speed;
375 | }
376 | else if (blob2d == 2)
377 | {
378 | bullet2y += speed;
379 | }
380 | else if (blob2d == 3)
381 | {
382 | bullet2x -= speed;
383 | }
384 | }
385 |
386 | void updateBullet3()
387 | {
388 | if (blob3d == 0)
389 | {
390 | bullet3y -= speed;
391 | }
392 | else if (blob3d == 1)
393 | {
394 | bullet3x += speed;
395 | }
396 | else if (blob3d == 2)
397 | {
398 | bullet3y += speed;
399 | }
400 | else if (blob3d == 3)
401 | {
402 | bullet3x -= speed;
403 | }
404 | }
405 |
406 | void updateBullet4()
407 | {
408 | if (blob4d == 0)
409 | {
410 | bullet4y -= speed;
411 | }
412 | else if (blob4d == 1)
413 | {
414 | bullet4x += speed;
415 | }
416 | else if (blob4d == 2)
417 | {
418 | bullet4y += speed;
419 | }
420 | else if (blob4d == 3)
421 | {
422 | bullet4x -= speed;
423 | }
424 | }
425 |
426 | void updateBullet5()
427 | {
428 | if (blob5d == 0)
429 | {
430 | bullet5y -= speed;
431 | }
432 | else if (blob5d == 1)
433 | {
434 | bullet5x += speed;
435 | }
436 | else if (blob5d == 2)
437 | {
438 | bullet5y += speed;
439 | }
440 | else if (blob5d == 3)
441 | {
442 | bullet5x -= speed;
443 | }
444 | }
445 |
446 | void detectBullet()
447 | {
448 | //Bullet1
449 | if (bullet1x > 15)
450 | {
451 | spawnBullet1();
452 | midiNote (0, 0);
453 | }
454 | else if (bullet1x < 0 && bullet1x > -90)
455 | {
456 | spawnBullet1();
457 | midiNote (0, 1);
458 | }
459 | else if (bullet1y > 15)
460 | {
461 | spawnBullet1();
462 | midiNote (0, 2);
463 | }
464 | else if (bullet1y < 0 && bullet1y > -90)
465 | {
466 | spawnBullet1();
467 | midiNote (0, 3);
468 | }
469 |
470 | //Bullet2
471 | if (bullet2x > 15)
472 | {
473 | spawnBullet2();
474 | midiNote (1, 0);
475 | }
476 | else if (bullet2x < 0 && bullet2x > -90)
477 | {
478 | spawnBullet2();
479 | midiNote (1, 1);
480 | }
481 | else if (bullet2y > 15)
482 | {
483 | spawnBullet2();
484 | midiNote (1, 2);
485 | }
486 | else if (bullet2y < 0 && bullet2y > -90)
487 | {
488 | spawnBullet2();
489 | midiNote (1, 3);
490 | }
491 |
492 | //Bullet3
493 | if (bullet3x > 15)
494 | {
495 | spawnBullet3();
496 | midiNote (2, 0);
497 | }
498 | else if (bullet3x < 0 && bullet3x > -90)
499 | {
500 | spawnBullet3();
501 | midiNote (2, 1);
502 | }
503 | else if (bullet3y > 15)
504 | {
505 | spawnBullet3();
506 | midiNote (2, 2);
507 | }
508 | else if (bullet3y < 0 && bullet3y > -90)
509 | {
510 | spawnBullet3();
511 | midiNote (2, 3);
512 | }
513 |
514 | //Bullet4
515 | if (bullet4x > 15)
516 | {
517 | spawnBullet4();
518 | midiNote (3, 0);
519 | }
520 | else if (bullet4x < 0 && bullet4x > -90)
521 | {
522 | spawnBullet4();
523 | midiNote (3, 1);
524 | }
525 | else if (bullet4y > 15)
526 | {
527 | spawnBullet4();
528 | midiNote (3, 2);
529 | }
530 | else if (bullet4y < 0 && bullet4y > -90)
531 | {
532 | spawnBullet4();
533 | midiNote (3, 3);
534 | }
535 |
536 | //Bullet5
537 | if (bullet5x > 15)
538 | {
539 | spawnBullet5();
540 | midiNote (4, 0);
541 | }
542 | else if (bullet5x < 0 && bullet5x > -90)
543 | {
544 | spawnBullet5();
545 | midiNote (4, 1);
546 | }
547 | else if (bullet5y > 15)
548 | {
549 | spawnBullet5();
550 | midiNote (4, 2);
551 | }
552 | else if (bullet5y < 0 && bullet5y > -90)
553 | {
554 | spawnBullet5();
555 | midiNote (4, 3);
556 | }
557 | }
558 |
559 | //MIDI FUN!
560 | void midiNote(int note1, int note2)
561 | {
562 | note2 *= 12;
563 | int note = rootNote;
564 |
565 | if (note1 == 0)
566 | {
567 | note += note2;
568 | note1 (note);
569 | }
570 | else if (note1 == 1)
571 | {
572 | if (chord == 0)
573 | {
574 | note += 4;
575 | }
576 | else
577 | {
578 | note += 3;
579 | }
580 | note += note2;
581 | note2 (note);
582 | }
583 | else if (note1 == 2)
584 | {
585 | note += 7;
586 | note += note2;
587 | note3 (note);
588 | }
589 | else if (note1 == 3)
590 | {
591 | if (chord == 0)
592 | {
593 | note += 11;
594 | }
595 | else
596 | {
597 | note += 10;
598 | }
599 | note += note2;
600 | note4 (note);
601 | }
602 | else if (note1 == 4)
603 | {
604 | note += 14;
605 | note += note2;
606 | note5 (note);
607 | }
608 | }
609 |
610 | void note1 (int note)
611 | {
612 | sendNoteOff (0, lastNote1, 80);
613 | sendNoteOn (0, note, 80);
614 | lastNote1 = note;
615 | }
616 | void note2 (int note)
617 | {
618 | sendNoteOff (0, lastNote2, 80);
619 | sendNoteOn (0, note, 80);
620 | lastNote2 = note;
621 | }
622 | void note3 (int note)
623 | {
624 | sendNoteOff (0, lastNote3, 80);
625 | sendNoteOn (0, note, 80);
626 | lastNote3 = note;
627 | }
628 | void note4 (int note)
629 | {
630 | sendNoteOff (0, lastNote4, 80);
631 | sendNoteOn (0, note, 80);
632 | lastNote4 = note;
633 | }
634 | void note5 (int note)
635 | {
636 | sendNoteOff (0, lastNote5, 80);
637 | sendNoteOn (0, note, 80);
638 | lastNote5 = note;
639 | }
640 |
641 | void handleButtonDown (int index)
642 | {
643 | initialise();
644 | }
645 |
646 | void repaint()
647 | {
648 | clearDisplay();
649 |
650 | //Draw 5 Blobs
651 | paintBlob (blob1x, blob1y, blob1d);
652 | paintBlob (blob2x, blob2y, blob2d);
653 | paintBlob (blob3x, blob3y, blob3d);
654 | paintBlob (blob4x, blob4y, blob4d);
655 | paintBlob (blob5x, blob5y, blob5d);
656 |
657 | //Draw 5 Bullets
658 | drawBullet (bullet1x, bullet1y, blob1d);
659 | drawBullet (bullet2x, bullet2y, blob2d);
660 | drawBullet (bullet3x, bullet3y, blob3d);
661 | drawBullet (bullet4x, bullet4y, blob4d);
662 | drawBullet (bullet5x, bullet5y, blob5d);
663 |
664 | //Update Bullet
665 | updateBullet1();
666 | updateBullet2();
667 | updateBullet3();
668 | updateBullet4();
669 | updateBullet5();
670 |
671 | //Detect Collision
672 | detectBullet();
673 | }
674 |
--------------------------------------------------------------------------------
/Factory Scripts/Mixer Block.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | */
27 |
28 | // PC Note - We arent using the heap. Without this statement we end up using too much of the heap...
29 | #heapsize: 1
30 |
31 | const int touchTypeNone = 0;
32 | const int touchTypeSlider = 1;
33 | const int touchTypeButton = 2;
34 |
35 | //==============================================================================
36 | void initialise()
37 | {
38 | for (int i = 0; i < 4; ++i)
39 | setSlider (i, 1);
40 |
41 | for (int i = 0; i < 32; ++i)
42 | setLocalConfigActiveState (i, false, false);
43 | }
44 |
45 | //==============================================================================
46 | int channelIndexForX (float x)
47 | {
48 | float x01 = x * 0.5;
49 |
50 | // Each slider has an area of 3px + 1px gap. We want the gaps to be dead zones..
51 | int ledZone = int (x01 * 15);
52 |
53 | if (ledZone <= 3) return 0;
54 | if (ledZone >= 4 && ledZone <= 7) return 1;
55 | if (ledZone >= 8 && ledZone <= 11) return 2;
56 | return 3;
57 | }
58 |
59 | //==============================================================================
60 | float getSliderValue01ForTouchAtY (float y)
61 | {
62 | float sliderMax = 14.0;
63 | float sliderMin = 4.0;
64 | float sliderRange = sliderMax - sliderMin;
65 |
66 | float closestLED = clamp (sliderMin, sliderMax, float (y * 14));
67 | float value01 = ((closestLED - sliderMin) / sliderRange);
68 | return 1.0 - value01;
69 | }
70 |
71 | //==============================================================================
72 | int convertSliderValue01ToRange (float slider01, int sliderMin, int sliderMax, int hardMax)
73 | {
74 | return clamp (0x00, hardMax, sliderMin + int (slider01 * float (sliderMax - sliderMin)));
75 | }
76 |
77 | //==============================================================================
78 | int convertSliderValue01ToOutputRange (int sliderIndex, float slider01)
79 | {
80 | return convertSliderValue01ToRange (slider01, getSliderMin (sliderIndex), getSliderMax (sliderIndex), 0x7F);
81 | }
82 |
83 | //==============================================================================
84 | void doTouchSlider (int index, float x, float y, float z, float vz)
85 | {
86 | int sliderIndex = channelIndexForX (x);
87 | int currentValue = getSlider (sliderIndex);
88 | float slider01 = getSliderValue01ForTouchAtY (y * 0.5);
89 | int midiValue = convertSliderValue01ToOutputRange (sliderIndex, slider01);
90 | int newValue = convertSliderValue01ToRange (slider01, 1, 11, 11);
91 |
92 | setSlider (sliderIndex, newValue);
93 | sendMIDI (0xB0 | (midiChannel - 1), getSliderCC (sliderIndex), midiValue);
94 | }
95 |
96 | //==============================================================================
97 | void doTouchButtonDown (int in, float x, float y, float z, float vz)
98 | {
99 | int buttonIndex = channelIndexForX (x);
100 | int buttonCC = getButtonCC (buttonIndex);
101 | int behaviour = getBehaviour (buttonIndex);
102 |
103 | if (behaviour == 0) // Toggle
104 | {
105 | setButton (buttonIndex, 255 - getButton (buttonIndex));
106 | sendCC (midiChannel - 1, buttonCC, getButton (buttonIndex) / 2);
107 | }
108 | else if (behaviour == 1) // Gate
109 | {
110 | setButton (buttonIndex, 255);
111 | sendCC (midiChannel - 1, buttonCC, 0x7F);
112 | }
113 | else if (behaviour == 2) // trigger
114 | {
115 | setButton (buttonIndex, 255);
116 | sendCC (midiChannel - 1, buttonCC, 0x7F);
117 | }
118 | }
119 |
120 | //==============================================================================
121 | void doTouchButtonUp (int index, float x, float y, float z, float vz)
122 | {
123 | int buttonIndex = channelIndexForX (x);
124 | if (getBehaviour (buttonIndex) == 1)
125 | {
126 | setButton (buttonIndex, 0);
127 | sendCC (midiChannel - 1, getButtonCC (buttonIndex), 0x00);
128 | }
129 | }
130 |
131 | //==============================================================================
132 | bool isTouchingButton (float y)
133 | {
134 | return (int (y * 0.5 * 15.0) <= 2);
135 | }
136 |
137 | //==============================================================================
138 | bool isValidTouchIndex (int index)
139 | {
140 | return ((index - 1) < 16);
141 | }
142 |
143 | //==============================================================================
144 | void touchStart (int index, float x, float y, float z, float vz)
145 | {
146 | if (! isValidTouchIndex (index))
147 | {
148 | return;
149 | }
150 |
151 | if (isTouchingButton (y))
152 | {
153 | doTouchButtonDown (index, x, y, z, vz);
154 | setTouchType ((index - 1), touchTypeButton);
155 | }
156 | else
157 | {
158 | doTouchSlider (index, x, y, z, vz);
159 | setTouchType ((index - 1), touchTypeSlider);
160 | }
161 | }
162 |
163 | //==============================================================================
164 | void touchMove (int index, float x, float y, float z, float vz)
165 | {
166 | if (! isValidTouchIndex (index))
167 | {
168 | return;
169 | }
170 |
171 | if (! isTouchingButton (y))
172 | {
173 | doTouchSlider (index, x, y, z, vz);
174 | }
175 | }
176 |
177 | //==============================================================================
178 | void touchEnd (int index, float x, float y, float z, float vz)
179 | {
180 | if (! isValidTouchIndex (index))
181 | {
182 | return;
183 | }
184 |
185 | int touchType = getTouchType ((index - 1));
186 | if (touchType == touchTypeButton)
187 | {
188 | doTouchButtonUp (index, x, y, z, vz);
189 | }
190 | else
191 | {
192 | doTouchSlider (index, x, y, z, vz);
193 | }
194 |
195 | setTouchType ((index - 1), touchTypeNone);
196 | }
197 |
198 | //==============================================================================
199 | void repaint()
200 | {
201 | fillRect (0x000000, 0, 0, 15, 15);
202 |
203 | for (int channel = 0; channel < 4; ++channel)
204 | {
205 | int buttonValue = getButton (channel);
206 | int behaviour = getBehaviour (channel);
207 |
208 | if (buttonValue > 0)
209 | {
210 | if (behaviour == 2)
211 | {
212 | buttonValue -= 31;
213 | if (buttonValue < 0)
214 | {
215 | buttonValue = 0;
216 | }
217 | setButton (channel, buttonValue);
218 | sendCC (midiChannel - 1, getButtonCC (channel), buttonValue / 2);
219 | blendRect (makeARGB (buttonValue, (buttonColour >> 16) & 0xFF, (buttonColour >> 8) & 0xFF, (buttonColour) & 0xFF), channel * 4, 0, 3, 3);
220 | }
221 | else
222 | {
223 | fillRect (buttonColour, channel * 4, 0, 3, 3);
224 | }
225 | }
226 |
227 | int sliderValue = getSlider (channel);
228 | fillRect (sliderColour, channel * 4, 15 - sliderValue, 3, sliderValue);
229 | }
230 | }
231 |
232 | /*
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 | */
--------------------------------------------------------------------------------
/Factory Scripts/MusicGen.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | */
12 |
13 |
14 | //==============================================================================
15 | int green;
16 | int red;
17 | int blue;
18 | int yellow;
19 | int count;
20 |
21 | int clock;
22 |
23 | float bullet1x;
24 | float bullet1y;
25 | float bullet2x;
26 | float bullet2y;
27 | float bullet3x;
28 | float bullet3y;
29 | float bullet4x;
30 | float bullet4y;
31 | float bullet5x;
32 | float bullet5y;
33 |
34 | int bullet1d;
35 | int bullet2d;
36 | int bullet3d;
37 | int bullet4d;
38 | int bullet5d;
39 |
40 | int blob1x;
41 | int blob1y;
42 | int blob2x;
43 | int blob2y;
44 | int blob3x;
45 | int blob3y;
46 | int blob4x;
47 | int blob4y;
48 | int blob5x;
49 | int blob5y;
50 |
51 | int blob1d;
52 | int blob2d;
53 | int blob3d;
54 | int blob4d;
55 | int blob5d;
56 |
57 | int lastNote1;
58 | int lastNote2;
59 | int lastNote3;
60 | int lastNote4;
61 | int lastNote5;
62 |
63 | void initialise()
64 | {
65 | clearDisplay();
66 |
67 | sendCC (0, 120, 127);
68 |
69 | blob1x = -99;
70 | blob2x = -99;
71 | blob3x = -99;
72 | blob4x = -99;
73 | blob5x = -99;
74 |
75 | blob1d = 3;
76 | blob2d = 3;
77 | blob3d = 3;
78 | blob4d = 3;
79 | blob5d = 3;
80 |
81 | bullet1x = -99;
82 | bullet2x = -99;
83 | bullet3x = -99;
84 | bullet4x = -99;
85 | bullet5x = -99;
86 |
87 | bullet1x = -99;
88 | bullet2x = -99;
89 | bullet3x = -99;
90 | bullet4x = -99;
91 | bullet5x = -99;
92 |
93 | bullet1y = -99;
94 | bullet2y = -99;
95 | bullet3y = -99;
96 | bullet4y = -99;
97 | bullet5y = -99;
98 |
99 | green = 0x2200FF00;
100 | red = 0x22FF0000;
101 | blue = 0x220000FF;
102 | yellow = 0x22FFFF00;
103 | count = 0;
104 | for (int i = 0; i < 32; ++i)
105 | setLocalConfigActiveState (i, false, false);
106 | }
107 |
108 | // Detect touches
109 |
110 | void touchStart (int touchIndex, float x, float y, float z, float vz)
111 | {
112 | int intX = int (x*7);
113 | int intY = int (y*7);
114 |
115 | int touch = touchBlob (intX, intY);
116 |
117 | log(touch);
118 |
119 | if (touch >= 1)
120 | {
121 | changeBlob(touch);
122 | log(123);
123 | }
124 | else if (count < 5)
125 | {
126 | if (z < 0.05)
127 | {
128 | assignBlob (intX, intY, count, 0);
129 | }
130 | else if (z < 0.2)
131 | {
132 | assignBlob (intX, intY, count, 1);
133 | }
134 | else if (z < 0.5)
135 | {
136 | assignBlob (intX, intY, count, 2);
137 | }
138 | else
139 | {
140 | assignBlob (intX, intY, count, 3);
141 | }
142 | count ++;
143 | }
144 | }
145 |
146 | //Detect if touch is on a Blob
147 | int touchBlob (int x, int y)
148 | {
149 | int touch;
150 |
151 | if (x >= (blob1x-1) && x <= (blob1x+1) && y >= (blob1y-1) && y <= (blob1y+1))
152 | {
153 | touch = 1;
154 | }
155 | else if (x >= (blob2x-1) && x <= (blob2x+1) && y >= (blob2y-1) && y <= (blob2y+1))
156 | {
157 | touch = 2;
158 | }
159 | else if (x >= (blob3x-1) && x <= (blob3x+1) && y >= (blob3y-1) && y <= (blob3y+1))
160 | {
161 | touch = 3;
162 | }
163 | else if (x >= (blob4x-1) && x <= (blob4x+1) && y >= (blob4y-1) && y <= (blob4y+1))
164 | {
165 | touch = 4;
166 | }
167 | else if (x >= (blob5x-1) && x <= (blob5x+1) && y >= (blob5y-1) && y <= (blob5y+1))
168 | {
169 | touch = 5;
170 | }
171 | else
172 | {
173 | touch = 0;
174 | }
175 | return touch;
176 | }
177 |
178 | void changeBlob(int blob){
179 | if (blob == 1)
180 | {
181 | if (blob1d < 3){
182 | blob1d++;
183 | }
184 | else{
185 | blob1d = 0;
186 | }
187 | }
188 | else if (blob == 2)
189 | {
190 | if (blob2d < 3){
191 | blob2d++;
192 | }
193 | else{
194 | blob2d = 0;
195 | }
196 | }
197 | else if (blob == 3)
198 | {
199 | if (blob3d < 3){
200 | blob3d++;
201 | }
202 | else{
203 | blob3d = 0;
204 | }
205 | }
206 | else if (blob == 4)
207 | {
208 | if (blob4d < 3){
209 | blob4d++;
210 | }
211 | else{
212 | blob4d = 0;
213 | }
214 | }
215 | else if (blob == 5)
216 | {
217 | if (blob5d < 3){
218 | blob5d++;
219 | }
220 | else{
221 | blob5d = 0;
222 | }
223 | }
224 | }
225 |
226 | // Blob Creation and Assignment!
227 |
228 | void paintBlob (int x, int y, int type)
229 | {
230 | if (type == 0)
231 | {
232 | fillRect(green, x, y-1, 1, 2);
233 | blendRect(green, x-1, y, 3, 1);
234 | }
235 | else if (type == 1)
236 | {
237 | fillRect(red, x, y, 2, 1);
238 | blendRect(red, x, y-1, 1, 3);
239 | }
240 | else if (type == 2)
241 | {
242 | fillRect(blue, x, y, 1, 2);
243 | blendRect(blue, x-1, y, 3, 1);
244 | }
245 | else if (type == 3)
246 | {
247 | fillRect(yellow, x-1, y, 2, 1);
248 | blendRect(yellow, x, y-1, 1, 3);
249 | }
250 | }
251 |
252 |
253 | void assignBlob (int x, int y, int index, int type)
254 | {
255 | if (index == 0)
256 | {
257 | blob1x = x;
258 | blob1y = y;
259 | blob1d = type;
260 | spawnBullet1();
261 | }
262 | else if (index == 1)
263 | {
264 | blob2x = x;
265 | blob2y = y;
266 | blob2d = type;
267 | spawnBullet2();
268 | }
269 | else if (index == 2)
270 | {
271 | blob3x = x;
272 | blob3y = y;
273 | blob3d = type;
274 | spawnBullet3();
275 | }
276 | else if (index == 3)
277 | {
278 | blob4x = x;
279 | blob4y = y;
280 | blob4d = type;
281 | spawnBullet4();
282 | }
283 | else if (index == 4)
284 | {
285 | blob5x = x;
286 | blob5y = y;
287 | blob5d = type;
288 | spawnBullet5();
289 | }
290 | }
291 |
292 | // Make Bullets!
293 |
294 | void spawnBullet1()
295 | {
296 | bullet1x = blob1x;
297 | bullet1y = blob1y;
298 | bullet1d = blob1d;
299 | }
300 |
301 | void spawnBullet2()
302 | {
303 | bullet2x = blob2x;
304 | bullet2y = blob2y;
305 | bullet2d = blob2d;
306 | }
307 |
308 | void spawnBullet3()
309 | {
310 | bullet3x = blob3x;
311 | bullet3y = blob3y;
312 | bullet3d = blob3d;
313 | }
314 |
315 | void spawnBullet4()
316 | {
317 | bullet4x = blob4x;
318 | bullet4y = blob4y;
319 | bullet4d = blob4d;
320 | }
321 |
322 | void spawnBullet5()
323 | {
324 | bullet5x = blob5x;
325 | bullet5y = blob5y;
326 | bullet5d = blob5d;
327 | }
328 |
329 |
330 | void drawBullet (float x, float y, int d)
331 | {
332 | fillPixel(0xFF222222, int(x), int(y));
333 |
334 | if (d == 0)
335 | {
336 | fillPixel(0xFFFFFF, int(x), int(y-1));
337 | }
338 | else if (d == 1)
339 | {
340 | fillPixel(0xFFFFFF, int(x+1), int(y));
341 | }
342 | else if (d == 2)
343 | {
344 | fillPixel(0xFFFFFF, int(x), int(y+1));
345 | }
346 | else
347 | {
348 | fillPixel(0xFFFFFF, int(x-1), int(y));
349 | }
350 | }
351 |
352 | void updateBullet1()
353 | {
354 | if (blob1d == 0)
355 | {
356 | bullet1y = bullet1y - speed;
357 | }
358 | else if (blob1d == 1)
359 | {
360 | bullet1x = bullet1x + speed;
361 | }
362 | else if (blob1d == 2)
363 | {
364 | bullet1y = bullet1y + speed;
365 | }
366 | else if (blob1d == 3)
367 | {
368 | bullet1x = bullet1x - speed;
369 | }
370 | }
371 |
372 | void updateBullet2()
373 | {
374 | if (blob2d == 0)
375 | {
376 | bullet2y = bullet2y - speed;
377 | }
378 | else if (blob2d == 1)
379 | {
380 | bullet2x = bullet2x + speed;
381 | }
382 | else if (blob2d == 2)
383 | {
384 | bullet2y = bullet2y + speed;
385 | }
386 | else if (blob2d == 3)
387 | {
388 | bullet2x = bullet2x - speed;
389 | }
390 | }
391 |
392 | void updateBullet3()
393 | {
394 | if (blob3d == 0)
395 | {
396 | bullet3y = bullet3y - speed;
397 | }
398 | else if (blob3d == 1)
399 | {
400 | bullet3x = bullet3x + speed;
401 | }
402 | else if (blob3d == 2)
403 | {
404 | bullet3y = bullet3y + speed;
405 | }
406 | else if (blob3d == 3)
407 | {
408 | bullet3x = bullet3x - speed;
409 | }
410 | }
411 |
412 | void updateBullet4()
413 | {
414 | if (blob4d == 0)
415 | {
416 | bullet4y = bullet4y - speed;
417 | }
418 | else if (blob4d == 1)
419 | {
420 | bullet4x = bullet4x + speed;
421 | }
422 | else if (blob4d == 2)
423 | {
424 | bullet4y = bullet4y + speed;
425 | }
426 | else if (blob4d == 3)
427 | {
428 | bullet4x = bullet4x - speed;
429 | }
430 | }
431 |
432 | void updateBullet5()
433 | {
434 | if (blob5d == 0)
435 | {
436 | bullet5y = bullet5y - speed;
437 | }
438 | else if (blob5d == 1)
439 | {
440 | bullet5x = bullet5x + speed;
441 | }
442 | else if (blob5d == 2)
443 | {
444 | bullet5y = bullet5y + speed;
445 | }
446 | else if (blob5d == 3)
447 | {
448 | bullet5x = bullet5x - speed;
449 | }
450 | }
451 |
452 | void detectBullet()
453 | {
454 | //Bullet1
455 | if (bullet1x > 15)
456 | {
457 | spawnBullet1();
458 | midiNote(0, 0);
459 | }
460 | else if (bullet1x < 0 && bullet1x > -90)
461 | {
462 | spawnBullet1();
463 | midiNote(0, 1);
464 | }
465 | else if (bullet1y > 15)
466 | {
467 | spawnBullet1();
468 | midiNote(0, 2);
469 | }
470 | else if (bullet1y < 0 && bullet1y > -90)
471 | {
472 | spawnBullet1();
473 | midiNote(0, 3);
474 | }
475 |
476 | //Bullet2
477 | if (bullet2x > 15)
478 | {
479 | spawnBullet2();
480 | midiNote(1, 0);
481 | }
482 | else if (bullet2x < 0 && bullet2x > -90)
483 | {
484 | spawnBullet2();
485 | midiNote(1, 1);
486 | }
487 | else if (bullet2y > 15)
488 | {
489 | spawnBullet2();
490 | midiNote(1, 2);
491 | }
492 | else if (bullet2y < 0 && bullet2y > -90)
493 | {
494 | spawnBullet2();
495 | midiNote(1, 3);
496 | }
497 |
498 | //Bullet3
499 | if (bullet3x > 15)
500 | {
501 | spawnBullet3();
502 | midiNote(2, 0);
503 | }
504 | else if (bullet3x < 0 && bullet3x > -90)
505 | {
506 | spawnBullet3();
507 | midiNote(2, 1);
508 | }
509 | else if (bullet3y > 15)
510 | {
511 | spawnBullet3();
512 | midiNote(2, 2);
513 | }
514 | else if (bullet3y < 0 && bullet3y > -90)
515 | {
516 | spawnBullet3();
517 | midiNote(2, 3);
518 | }
519 |
520 | //Bullet4
521 | if (bullet4x > 15)
522 | {
523 | spawnBullet4();
524 | midiNote(3, 0);
525 | }
526 | else if (bullet4x < 0 && bullet4x > -90)
527 | {
528 | spawnBullet4();
529 | midiNote(3, 1);
530 | }
531 | else if (bullet4y > 15)
532 | {
533 | spawnBullet4();
534 | midiNote(3, 2);
535 | }
536 | else if (bullet4y < 0 && bullet4y > -90)
537 | {
538 | spawnBullet4();
539 | midiNote(3, 3);
540 | }
541 |
542 | //Bullet5
543 | if (bullet5x > 15)
544 | {
545 | spawnBullet5();
546 | midiNote(4, 0);
547 | }
548 | else if (bullet5x < 0 && bullet5x > -90)
549 | {
550 | spawnBullet5();
551 | midiNote(4, 1);
552 | }
553 | else if (bullet5y > 15)
554 | {
555 | spawnBullet5();
556 | midiNote(4, 2);
557 | }
558 | else if (bullet5y < 0 && bullet5y > -90)
559 | {
560 | spawnBullet5();
561 | midiNote(4, 3);
562 | }
563 | }
564 |
565 | //MIDI FUN!
566 |
567 | void midiNote(int note1, int note2)
568 | {
569 | note2 = note2 * 12;
570 | int note = rootNote;
571 |
572 | if (note1 == 0)
573 | {
574 | note = note + note2;
575 | note1(note);
576 | }
577 | else if (note1 == 1)
578 | {
579 | if (chord == 0)
580 | {
581 | note = note + 4;
582 | }
583 | else
584 | {
585 | note = note + 3;
586 | }
587 | note = note + note2;
588 | note2(note);
589 | }
590 | else if (note1 == 2)
591 | {
592 | note = note + 7;
593 | note = note + note2;
594 | note3(note);
595 | }
596 | else if (note1 == 3)
597 | {
598 | if (chord == 0)
599 | {
600 | note = note + 11;
601 | }
602 | else
603 | {
604 | note = note + 10;
605 | }
606 | note = note + note2;
607 | note4(note);
608 | }
609 | else if (note1 == 4)
610 | {
611 | note = note + 14;
612 | note = note + note2;
613 | note5(note);
614 | }
615 | }
616 |
617 | void note1(int note)
618 | {
619 | sendNoteOff (0, lastNote1, 80);
620 | sendNoteOn (0, note, 80);
621 | lastNote1 = note;
622 | }
623 | void note2(int note)
624 | {
625 | sendNoteOff (0, lastNote2, 80);
626 | sendNoteOn (0, note, 80);
627 | lastNote2 = note;
628 | }
629 | void note3(int note)
630 | {
631 | sendNoteOff (0, lastNote3, 80);
632 | sendNoteOn (0, note, 80);
633 | lastNote3 = note;
634 | }
635 | void note4(int note)
636 | {
637 | sendNoteOff (0, lastNote4, 80);
638 | sendNoteOn (0, note, 80);
639 | lastNote4 = note;
640 | }
641 | void note5(int note)
642 | {
643 | sendNoteOff (0, lastNote5, 80);
644 | sendNoteOn (0, note, 80);
645 | lastNote5 = note;
646 | }
647 |
648 | void handleButtonDown (int index)
649 | {
650 | initialise();
651 | }
652 |
653 | void repaint()
654 | {
655 | clearDisplay();
656 |
657 | //Draw 5 Blobs
658 | paintBlob(blob1x, blob1y, blob1d);
659 | paintBlob(blob2x, blob2y, blob2d);
660 | paintBlob(blob3x, blob3y, blob3d);
661 | paintBlob(blob4x, blob4y, blob4d);
662 | paintBlob(blob5x, blob5y, blob5d);
663 |
664 | //Draw 5 Bullets
665 | drawBullet(bullet1x, bullet1y, blob1d);
666 | drawBullet(bullet2x, bullet2y, blob2d);
667 | drawBullet(bullet3x, bullet3y, blob3d);
668 | drawBullet(bullet4x, bullet4y, blob4d);
669 | drawBullet(bullet5x, bullet5y, blob5d);
670 |
671 | //Update Bullet
672 | updateBullet1();
673 | updateBullet2();
674 | updateBullet3();
675 | updateBullet4();
676 | updateBullet5();
677 |
678 | //Detect Collision
679 | detectBullet();
680 | }
681 |
682 | /*
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 | */
709 |
--------------------------------------------------------------------------------
/Factory Scripts/Control Grid.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | */
28 |
29 | #heapsize: 381
30 |
31 | /*
32 | * Heap layout is as follows:
33 | * bytes 0 - 16 touch to touch pads
34 | * byte 32+
35 | * Index 0 4 bytes note off delta
36 | * Index 1 4 bytes start time
37 | * Index 2 4 bytes velocity
38 | *
39 | */
40 |
41 | int padWidth;
42 | int padSpacing;
43 | int gridSize;
44 | int numPads; // Num pads in the grid, so a gridSize=4 would set this to 16
45 | int activePads;
46 | int dimFactor;
47 | int dimDelay;
48 | int dimDelta;
49 |
50 | const int behaviourNoteOnOff = 0;
51 | const int behaviourCC = 1;
52 | const int actionToggle = 0;
53 | const int actionGate = 1;
54 | const int actionTrigger = 2;
55 |
56 | void setPadActive (int padIndex, bool shouldBeActive)
57 | {
58 | activePads = shouldBeActive ? (activePads | (1 << padIndex)) : (activePads & ~(1 << padIndex));
59 | }
60 |
61 | bool isPadActive (int padIndex)
62 | {
63 | return activePads & (1 << padIndex);
64 | }
65 |
66 | bool isAnyPadActive()
67 | {
68 | return activePads;
69 | }
70 |
71 | void setPadForTouch (int touchIndex, int padIndex)
72 | {
73 | setHeapByte (touchIndex, padIndex);
74 | }
75 |
76 | int getPadForTouch (int touchIndex)
77 | {
78 | return getHeapByte (touchIndex);
79 | }
80 |
81 | int getTrailColour (int padColour)
82 | {
83 | if (gridSize == 1)
84 | {
85 | // Note - With a grid size of 1, we dont see the pad dim at note on (and hence its next to impossible to see the touch)
86 | // With this, we draw a white heat trail over the top of the pad, giving a clear touch indication
87 | // There is the potential that the heat trail being white might clash with the chosen colour,
88 | // But given that its white, i figure we will normally still be able to see it, and it avoids having
89 | return 0xFFFFFF;
90 | }
91 |
92 | if (padColour == 0xff000000)
93 | {
94 | return 0xffaaaaaa;
95 | }
96 |
97 | return blendARGB (0x88ffffff, padColour);
98 | }
99 |
100 | void onStateChanged()
101 | {
102 | gridSize = gridOption + 1;
103 | numPads = gridSize * gridSize;
104 | padWidth = 15 / gridSize;
105 | padSpacing = gridSize > 1 ? (15 - gridSize * padWidth) / (gridSize - 1) : 0;
106 | padWidth += padSpacing;
107 | }
108 |
109 | void initialise()
110 | {
111 | onStateChanged();
112 | activePads = 0;
113 | dimFactor = 0;
114 | dimDelta = 0;
115 | dimDelay = 12;
116 |
117 | for (int i = 0; i < 32; ++i)
118 | setLocalConfigActiveState (i, false, false);
119 | }
120 |
121 | void updateDimFactor()
122 | {
123 | if (isAnyPadActive() || dimDelta)
124 | {
125 | if (dimFactor < 180)
126 | {
127 | dimDelta = 60;
128 | }
129 | else
130 | {
131 | dimDelta = 0;
132 | }
133 |
134 | dimFactor += dimDelta;
135 | dimDelay = 8;
136 | }
137 | else
138 | {
139 | if (--dimDelay <= 0)
140 | {
141 | dimFactor -= 24;
142 |
143 | if (dimFactor < 0)
144 | {
145 | dimFactor = 0;
146 | }
147 | }
148 | }
149 | }
150 |
151 | void drawPads()
152 | {
153 | int padIndex = 0;
154 | for (int padY = 0; padY < gridSize; ++padY)
155 | {
156 | for (int padX = 0; padX < gridSize; ++padX)
157 | {
158 | int padColour = getPadColour (padIndex);
159 | int overlayColour = isPadActive (padIndex) ? 0x33ffffff : (dimFactor << 24);
160 |
161 | fillRect (blendARGB (padColour, overlayColour),
162 | padX * padWidth, (gridSize - padY - 1) * padWidth,
163 | padWidth - padSpacing, padWidth - padSpacing);
164 |
165 |
166 | ++padIndex;
167 | }
168 | }
169 | }
170 |
171 | void sendNoteOffForPad (int padIndex, int velocity)
172 | {
173 | sendNoteOff ((channel - 1), getNote (padIndex), velocity);
174 | setPadActive (padIndex, false);
175 | }
176 |
177 | void sendNoteOnForPad (int padIndex, int velocity)
178 | {
179 | sendNoteOn ((channel - 1), getNote (padIndex), velocity);
180 | setPadActive (padIndex, true);
181 | }
182 |
183 | void sendCCForPad (int padIndex, int ccValue, bool changePadActiveStatus)
184 | {
185 | sendCC ((channel - 1), getCC (padIndex), ccValue);
186 | if (changePadActiveStatus)
187 | {
188 | setPadActive (padIndex, ccValue == 127);
189 | }
190 | }
191 |
192 | int getVelocityForVz (float vz)
193 | {
194 | return clamp (1, 127, int (vz * 127.0));
195 | }
196 |
197 | int getPressureForZ (float z)
198 | {
199 | return int ((z * z) * 127.0);
200 | }
201 |
202 | void handleNoteOnOffTouchStart (int padIndex, int action, int velocity, bool pressure)
203 | {
204 | if (action == actionToggle)
205 | {
206 | if (isPadActive (padIndex))
207 | {
208 | sendNoteOffForPad (padIndex, velocity);
209 | }
210 | else
211 | {
212 | sendNoteOnForPad (padIndex, velocity);
213 | }
214 | }
215 | else if (action == actionGate)
216 | {
217 | sendNoteOnForPad (padIndex, velocity);
218 | }
219 | else if (action == actionTrigger)
220 | {
221 | sendNoteOnForPad (padIndex, velocity);
222 | setPadOffDeltaTime (padIndex, noteOffTime, velocity);
223 | }
224 | }
225 |
226 | void sendPressure (int padIndex, int pressure)
227 | {
228 | if (getBehaviour (padIndex) == behaviourNoteOnOff)
229 | {
230 | if (wantsPolyPressure)
231 | {
232 | sendMIDI (0xa0 | (channel - 1), getNote (padIndex), pressure);
233 | }
234 | else
235 | {
236 | sendMIDI (0xd0 | (channel - 1), pressure);
237 | }
238 | }
239 | else
240 | {
241 | sendCCForPad (padIndex, pressure, false);
242 | }
243 | }
244 |
245 | void handleCCTouchStart (int padIndex, int action, int velocity, bool pressure)
246 | {
247 | if (! pressure)
248 | {
249 | if (action == actionToggle)
250 | {
251 | if (isPadActive (padIndex))
252 | {
253 | sendCCForPad (padIndex, 0, true);
254 | }
255 | else
256 | {
257 | sendCCForPad (padIndex, 127, true);
258 | }
259 | }
260 | else if (action == actionGate)
261 | {
262 | sendCCForPad (padIndex, 127, true);
263 | }
264 | else if (action == actionTrigger)
265 | {
266 | sendCCForPad (padIndex, 127, true);
267 | setPadOffDeltaTime (padIndex, noteOffTime, 0);
268 | }
269 | }
270 | }
271 |
272 | void touchStart (int touchIndex, float x, float y, float z, float vz)
273 | {
274 | int row = gridSize - (int (y * (0.95 / 2.0) * float (gridSize))) - 1;
275 | int col = int (x * (0.95 / 2.0) * float (gridSize));
276 | int padIndex = (gridSize * row) + col;
277 |
278 | int action = getAction (padIndex);
279 | int velocity = getVelocityForVz (vz);
280 | bool pressure = getPressure (padIndex);
281 |
282 | if (getBehaviour (padIndex) == behaviourNoteOnOff)
283 | {
284 | handleNoteOnOffTouchStart (padIndex, action, velocity, pressure);
285 | }
286 | else
287 | {
288 | handleCCTouchStart (padIndex, action, velocity, pressure);
289 | }
290 |
291 | if (pressure)
292 | {
293 | sendPressure (padIndex, getPressureForZ (z));
294 | }
295 |
296 | addPressurePoint (getTrailColour (getPadColour (padIndex)), x, y, z * 10.0);
297 | setPadForTouch (touchIndex, padIndex);
298 | }
299 |
300 | void touchMove (int touchIndex, float x, float y, float z, float vz)
301 | {
302 | int padIndex = getPadForTouch (touchIndex);
303 | if (padIndex == 0xff)
304 | {
305 | return; // touch was not started.
306 | }
307 |
308 | if (getPressure (padIndex))
309 | {
310 | sendPressure (padIndex, getPressureForZ (z));
311 | }
312 |
313 | addPressurePoint (getTrailColour (getPadColour (padIndex)), x, y, z * 10.0);
314 | }
315 |
316 | void touchEnd (int touchIndex, float x, float y, float z, float vz)
317 | {
318 | int padIndex = getPadForTouch (touchIndex);
319 |
320 | if (padIndex == 0xff)
321 | {
322 | return; // touch was not started.
323 | }
324 |
325 | if (getPressure (padIndex))
326 | {
327 | sendPressure (padIndex, getPressureForZ (z));
328 | }
329 |
330 | int behaviour = getBehaviour (padIndex);
331 | int action = getAction (padIndex);
332 | if (behaviour == behaviourNoteOnOff)
333 | {
334 | if (action == actionGate)
335 | {
336 | sendNoteOffForPad (padIndex, getVelocityForVz (vz));
337 | }
338 | }
339 | else
340 | {
341 | if (action == actionGate && ! getPressure (padIndex))
342 | {
343 | sendCCForPad (padIndex, 0, true);
344 | }
345 | }
346 |
347 | setPadForTouch (touchIndex, 0xff);
348 | }
349 |
350 | void setPadOffDeltaTime (int padIndex, int delta, int velocity)
351 | {
352 | int basePadAddress = 32 + (padIndex * 12);
353 |
354 | setHeapInt (basePadAddress, delta);
355 | setHeapInt (basePadAddress + 4, getMillisecondCounter());
356 | setHeapInt (basePadAddress + 8, velocity);
357 | }
358 |
359 | void updateNoteOffTime()
360 | {
361 | int currentTime = getMillisecondCounter();
362 | for (int padIndex = 0; padIndex < numPads; ++padIndex)
363 | {
364 | int padAddress = 32 + (padIndex * 12);
365 | int padTime = getHeapInt (padAddress);
366 | if (padTime > 0)
367 | {
368 | int padStartTime = getHeapInt (padAddress + 4);
369 | if (currentTime - padStartTime >= padTime)
370 | {
371 | int velocity = getHeapInt (padAddress + 8);
372 | if (getBehaviour (padIndex) == 0)
373 | {
374 | sendNoteOffForPad (padIndex, velocity);
375 | }
376 | else
377 | {
378 | sendCCForPad (padIndex, velocity, false);
379 | }
380 | setPadOffDeltaTime (padIndex, 0, 0);
381 | }
382 | }
383 | }
384 | }
385 |
386 | void repaint()
387 | {
388 | clearDisplay();
389 | updateDimFactor();
390 | drawPads();
391 | updateNoteOffTime();
392 | drawPressureMap();
393 | fadePressureMap();
394 | }
395 |
396 |
397 | /*
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 | */
--------------------------------------------------------------------------------
/Factory Scripts/Drum Block.littlefoot:
--------------------------------------------------------------------------------
1 | /*
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
73 |
74 |
89 |
90 | */
91 |
92 | #heapsize: 381
93 |
94 | //==============================================================================
95 | /*
96 | Heap layout:
97 |
98 | === 25 x Pad ===
99 |
100 | 0 4 byte x 25 colours
101 | 100 1 byte x 25 note numbers
102 |
103 | === 24 x Touch ===
104 |
105 | 125 1 byte x 24 corresponding pad index (0xff if none)
106 | 149 4 byte x 24 initial x positions (for relative pitchbend)
107 | 245 4 byte x 24 initial y positions (for relative y axis)
108 | 341 1 byte x 24 MIDI channel assigned
109 |
110 | === 16 x Channel ===
111 |
112 | 365 1 byte x 16 touch to track for this channel (depends on tracking mode)
113 | */
114 | //==============================================================================
115 |
116 | int padWidth, padSpacing;
117 | int dimFactor, dimDelay, dimDelta;
118 | int channelLastAssigned;
119 | int activePads;
120 | int clusterWidth;
121 | int clusterHeight;
122 |
123 | //==============================================================================
124 | void checkAndUpdateCluster()
125 | {
126 | int w = getClusterWidth();
127 | int h = getClusterHeight();
128 |
129 | if (clusterWidth != w || clusterHeight != h)
130 | {
131 | updateCluster();
132 | }
133 | }
134 |
135 | //==============================================================================
136 | void updateCluster()
137 | {
138 | clusterWidth = getClusterWidth();
139 | clusterHeight = getClusterHeight();
140 |
141 | if (clusterWidth == 1 && clusterHeight == 1)
142 | return;
143 |
144 | int x = getClusterXpos() % 4;
145 | int y = getClusterYpos() % 4;
146 |
147 | int numPadsInGrid = (gridSize * gridSize);
148 |
149 | if (clusterWidth == 2 && clusterHeight == 1)
150 | baseNote += (x * numPadsInGrid);
151 | else if (clusterWidth == 1 && clusterHeight == 2)
152 | baseNote += (y * numPadsInGrid);
153 | else
154 | baseNote += ((x * clusterWidth) + y) * numPadsInGrid;
155 |
156 | baseNote = min (baseNote, 127 - numPadsInGrid);
157 | }
158 |
159 | //==============================================================================
160 | int Pad_getColour (int padIndex)
161 | {
162 | if (padIndex == 0) return padColour1;
163 | if (padIndex == 1) return padColour2;
164 | if (padIndex == 2) return padColour3;
165 | if (padIndex == 3) return padColour4;
166 | if (padIndex == 4) return padColour5;
167 | if (padIndex == 5) return padColour6;
168 | if (padIndex == 6) return padColour7;
169 | if (padIndex == 7) return padColour8;
170 | if (padIndex == 8) return padColour9;
171 | if (padIndex == 9) return padColour10;
172 | if (padIndex == 10) return padColour11;
173 | if (padIndex == 11) return padColour12;
174 | if (padIndex == 12) return padColour13;
175 | if (padIndex == 13) return padColour14;
176 | if (padIndex == 14) return padColour15;
177 | if (padIndex == 15) return padColour16;
178 |
179 | return 0xffffffff;
180 | }
181 |
182 | void Pad_setNote (int padIndex, int note)
183 | {
184 | setHeapByte (padIndex + 100, note);
185 | }
186 |
187 | int Pad_getNote (int padIndex)
188 | {
189 | return baseNote + padIndex;
190 | }
191 |
192 | void Pad_setActive (int padIndex, bool shouldBeActive)
193 | {
194 | activePads = shouldBeActive ? (activePads | (1 << padIndex))
195 | : (activePads & ~(1 << padIndex));
196 | }
197 |
198 | bool Pad_isActive (int padIndex)
199 | {
200 | return activePads & (1 << padIndex);
201 | }
202 |
203 | bool isAnyPadActive()
204 | {
205 | return activePads;
206 | }
207 |
208 | //==============================================================================
209 | void Touch_setPad (int touchIndex, int padIndex)
210 | {
211 | setHeapByte (touchIndex + 125, padIndex);
212 | }
213 |
214 | int Touch_getPad (int touchIndex)
215 | {
216 | return getHeapByte (touchIndex + 125);
217 | }
218 |
219 | // Note: littlefoot doesn't have set/getHeapFloat yet, so we store initial x/y
220 | // positions as ints, scaled up by a factor of 1e6.
221 | void Touch_setInitialX (int touchIndex, float initialX)
222 | {
223 | setHeapInt ((touchIndex * 4) + 149, int (initialX * 1e6));
224 | }
225 |
226 | float Touch_getInitialX (int touchIndex)
227 | {
228 | return float (getHeapInt ((touchIndex * 4) + 149)) / 1e6;
229 | }
230 |
231 | void Touch_setInitialY (int touchIndex, float initialY)
232 | {
233 | setHeapInt ((touchIndex * 4) + 245, int (initialY * 1e6));
234 | }
235 |
236 | float Touch_getInitialY (int touchIndex)
237 | {
238 | return float (getHeapInt ((touchIndex * 4) + 245)) / 1e6;
239 | }
240 |
241 | void Touch_setChannel (int touchIndex, int channel)
242 | {
243 | setHeapByte (touchIndex + 341, channel);
244 | }
245 |
246 | int Touch_getChannel (int touchIndex)
247 | {
248 | return getHeapByte (touchIndex + 341);
249 | }
250 |
251 | //==============================================================================
252 | void Channel_setTrackedTouch (int channel, int touchIndex)
253 | {
254 | setHeapByte (channel + 365, touchIndex);
255 | }
256 |
257 | int Channel_getTrackedTouch (int channel)
258 | {
259 | return getHeapByte (channel + 365);
260 | }
261 |
262 | //==============================================================================
263 | int getTouchedPad (float x, float y)
264 | {
265 | // Pad positions are inverted in y - i.e. 0 is bottom left, not top left.
266 | int row = gridSize - (int (y * (0.95 / 2.0) * float (gridSize))) - 1;
267 | int col = int (x * (0.95 / 2.0) * float (gridSize));
268 |
269 | return (gridSize * row) + col;
270 | }
271 |
272 | //==============================================================================
273 | int getTrailColour (int padColour)
274 | {
275 | if (gridSize == 1)
276 | {
277 | // Note - With a grid size of 1, we dont see the pad dim at note on (and hence its next to impossible to see the touch)
278 | // With this, we draw a white heat trail over the top of the pad, giving a clear touch indication
279 | // There is the potential that the heat trail being white might clash with the chosen colour,
280 | // But given that its white, i figure we will normally still be able to see it, and it avoids having
281 | return 0xFFFFFF;
282 | }
283 |
284 | if (padColour == 0xff000000)
285 | return 0xffaaaaaa;
286 |
287 | return blendARGB (0x88ffffff, padColour);
288 | }
289 |
290 | //==============================================================================
291 | void updateDimFactor()
292 | {
293 | if (isAnyPadActive() || dimDelta)
294 | {
295 | if (dimFactor < 180)
296 | dimDelta = 60;
297 | else
298 | dimDelta = 0;
299 |
300 | dimFactor += dimDelta;
301 | dimDelay = 8;
302 | }
303 | else
304 | {
305 | if (--dimDelay <= 0)
306 | {
307 | dimFactor -= 24;
308 |
309 | if (dimFactor < 0)
310 | dimFactor = 0;
311 | }
312 | }
313 | }
314 |
315 | //==============================================================================
316 | void drawPad (int x, int y, int colour, int bottomRightCornerDarkeningAmount)
317 | {
318 | int dark = blendARGB (colour, bottomRightCornerDarkeningAmount << 24);
319 | int mid = blendARGB (colour, (bottomRightCornerDarkeningAmount / 2) << 24);
320 |
321 | int w = padWidth - padSpacing;
322 | blendGradientRect (colour, mid, dark, mid, x * padWidth, y * padWidth, w, w);
323 | }
324 |
325 | void drawPads()
326 | {
327 | int padIndex = 0;
328 |
329 | for (int padY = 0; padY < gridSize; ++padY)
330 | {
331 | for (int padX = 0; padX < gridSize; ++padX)
332 | {
333 | int overlayColour = Pad_isActive (padIndex) ? 0x33ffffff : (dimFactor << 24);
334 |
335 | drawPad (padX, gridSize - padY - 1, blendARGB (Pad_getColour (padIndex), overlayColour), 0xcc);
336 |
337 | ++padIndex;
338 | }
339 | }
340 | }
341 |
342 | //==============================================================================
343 | void initialisePads()
344 | {
345 | for (int padIndex = 0; padIndex < 25; ++padIndex)
346 | {
347 | // note numbers:
348 | Pad_setNote (padIndex, baseNote + padIndex);
349 | }
350 |
351 | activePads = 0;
352 | }
353 |
354 | void initialiseTouches()
355 | {
356 | for (int touchIndex = 0; touchIndex < 24; ++touchIndex)
357 | {
358 | Touch_setPad (touchIndex, 0xff);
359 | Touch_setChannel (touchIndex, 0xff);
360 | }
361 | }
362 |
363 | void initialiseChannels()
364 | {
365 | for (int channel = 0; channel < 16; ++channel)
366 | {
367 | Channel_setTrackedTouch (channel, 0xff);
368 |
369 | // Send note-offs for all channels & notes to avoid stuck notes
370 | // when modifying dynamic variables from the sidepanel.
371 | sendMIDI (0xb0 | channel, 120, 0); // All sound off msg
372 | sendMIDI (0xb0 | channel, 123, 0); // All notes off msg
373 | }
374 | }
375 |
376 | void initialise()
377 | {
378 | updateCluster();
379 |
380 | padWidth = 15 / gridSize;
381 | padSpacing = gridSize > 1 ? (15 - gridSize * padWidth) / (gridSize - 1) : 0;
382 | padWidth += padSpacing;
383 |
384 | dimFactor = 0;
385 | dimDelta = 0;
386 | dimDelay = 12;
387 |
388 | initialisePads();
389 | initialiseTouches();
390 | initialiseChannels();
391 |
392 | useMPEDuplicateFilter (true);
393 | setChannelRange (midiMode == 0, channelFirst, channelLast);
394 | for (int i = 0; i < 32; ++i)
395 | setLocalConfigActiveState (i, false, false);
396 | }
397 |
398 | //==============================================================================
399 | void repaint()
400 | {
401 | clearDisplay();
402 | updateDimFactor();
403 |
404 | if (isConnectedToHost())
405 | drawPads();
406 |
407 | // Overlay heatmap
408 | drawPressureMap();
409 | fadePressureMap();
410 |
411 | checkAndUpdateCluster();
412 | }
413 |
414 | //==============================================================================
415 | int getPitchwheelValue (int touchIndex, float x)
416 | {
417 | if (! shouldSendPitchBend)
418 | return 8192;
419 |
420 | float blockWidthUnits = 2.0;
421 | float initialX = Touch_getInitialX (touchIndex);
422 | float deltaX = (x - initialX) * (blockWidthUnits + 0.1); // Adjust width by 0.1 as edges are hard to reach
423 |
424 | if (abs (deltaX) > 1.0)
425 | {
426 | // Initially the note centre is at centre of the finger strike,
427 | // but after a significant slide is performed, we want to use the
428 | // actual pad centres to avoid confusion about pad boundaries.
429 | float divisor = 1.0 / float (gridSize);
430 |
431 | initialX = ((mod (Touch_getPad (touchIndex), gridSize) * divisor) + (divisor * 0.5)) * blockWidthUnits;
432 | deltaX = (x - initialX) * (blockWidthUnits + 0.1); // recompute with new initialX
433 | }
434 | int pitchWheel = getPitchWheelFromDeltaX (deltaX);
435 | return pitchWheel;
436 | }
437 |
438 | //==============================================================================
439 | int getPitchWheelFromDeltaX (float deltaX)
440 | {
441 | // Wheel range is front 0 - 1, where 0.5 is linear. We dont want it to go fully to zero tho, because that disabled the curve
442 | float wheelRange = ((pitchBendCurve * 0.85) + 0.15);
443 | float center = 8192.0;
444 | float range = 8192.0 * wheelRange;
445 | float minRange = center - range;
446 | float maxRange = center + range;
447 | float pitchwheel = map (deltaX, -2.0, 2.0, minRange, maxRange);
448 | return clamp (0, 16383, int (pitchwheel));
449 | }
450 |
451 | //==============================================================================
452 | int getYAxisValue (int touchIndex, float y)
453 | {
454 | float initialY = Touch_getInitialY (touchIndex);
455 |
456 | if (y >= initialY)
457 | y = map (y, initialY, 2.0, 0.0, -1.0);
458 | else
459 | y = map (y, 0.0, initialY, 1.0, 0.0);
460 |
461 | y = 0.5 + (0.5 * applyCurve (y));
462 |
463 | return clamp (0, 127, int (y * 127));
464 | }
465 |
466 | float applyCurve (float y)
467 | {
468 | float absY = slideCoef < 0 ? 1.0 - abs (y) : abs(y);
469 | float absCoef = abs (slideCoef);
470 |
471 | if (absCoef < 0.01)
472 | return y;
473 |
474 | float ky = (16.0 * absCoef / (1.0 + absCoef)) * absY;
475 | float curved = (absY + ky) / (1 + ky);
476 |
477 | if (slideCoef < 0)
478 | curved = 1 - curved;
479 |
480 | if (y < 0)
481 | curved = -curved;
482 |
483 | return curved;
484 | }
485 |
486 | //==============================================================================
487 | bool shouldTrackNewTouch (int channel, int touchIndex, int note)
488 | {
489 | if (trackingMode == 0)
490 | return true; // track last note on channel: new note always overrides old one!
491 |
492 | int previouslyTrackedTouch = Channel_getTrackedTouch (channel);
493 |
494 | if (previouslyTrackedTouch == 0xff)
495 | return true; // channel is free and can track this touch
496 |
497 | int previouslyTrackedNote = Pad_getNote (Touch_getPad (previouslyTrackedTouch));
498 |
499 | if ((trackingMode == 1 && note > previouslyTrackedNote) || (trackingMode == 2 && note < previouslyTrackedNote))
500 | return true; // new note is higher/lower than previous note, and we should track highest/lowest note
501 |
502 | return false;
503 | }
504 |
505 | //==============================================================================
506 | void touchStart (int touchIndex, float x, float y, float z, float vz)
507 | {
508 | int padIndex = getTouchedPad (x, y);
509 | int note = Pad_getNote (padIndex);
510 | int colour = Pad_getColour (padIndex);
511 | int channel = assignChannel (note);
512 | int velocity = fixedStrikeOn ? fixedStrikeValue : clamp (1, 127, int (vz * 127.0));
513 | int pressure = clamp (0, 127, int (z * 127.0));
514 |
515 | if (pressType == 0) // channel pressure
516 | sendMIDI (0xd0 | channel, pressure);
517 |
518 | else // poly aftertouch
519 | sendMIDI (0xa0 | channel, note, pressure);
520 |
521 | sendPitchBend (channel, 8192);
522 | sendMIDI (0xb0 | channel, slideCc, 64); // initial Y in relative mode
523 | sendNoteOn (channel, note, velocity);
524 |
525 | addPressurePoint (getTrailColour (colour), x, y, z * 10.0);
526 |
527 | Pad_setActive (padIndex, true);
528 |
529 | Touch_setPad (touchIndex, padIndex);
530 | Touch_setInitialX (touchIndex, x);
531 | Touch_setInitialY (touchIndex, y);
532 | Touch_setChannel (touchIndex, channel);
533 |
534 | if (shouldTrackNewTouch (channel, touchIndex, note))
535 | Channel_setTrackedTouch (channel, touchIndex);
536 | }
537 |
538 | void touchMove (int touchIndex, float x, float y, float z, float vz)
539 | {
540 | int padIndex = Touch_getPad (touchIndex);
541 | int channel = Touch_getChannel (touchIndex);
542 |
543 | if (padIndex == 0xff)
544 | return; // touch was not started.
545 |
546 | if (Channel_getTrackedTouch (channel) != touchIndex)
547 | return; // these are not the touch messages you're looking for...
548 |
549 | int pressure = clamp (0, 127, int (z * 127.0));
550 |
551 | if (pressType == 0) // channel pressure
552 | sendMIDI (0xd0 | channel, pressure);
553 |
554 | else // poly aftertouch
555 | sendMIDI (0xa0 | channel, Pad_getNote (padIndex), pressure);
556 |
557 | sendMIDI (0xb0 | channel, slideCc, getYAxisValue (touchIndex, y));
558 |
559 | sendPitchBend (channel, getPitchwheelValue (touchIndex, x));
560 |
561 | int colour = Pad_getColour (padIndex);
562 | addPressurePoint (getTrailColour (colour), x, y, z * 10.0);
563 | }
564 |
565 | void touchEnd (int touchIndex, float x, float y, float z, float vz)
566 | {
567 | int padIndex = Touch_getPad (touchIndex);
568 | int channel = Touch_getChannel (touchIndex);
569 |
570 | if (padIndex == 0xff)
571 | return; // touch was not started.
572 |
573 | int note = Pad_getNote (padIndex);
574 | int velocity = clamp (0, 127, int (vz * 127.0));
575 |
576 | sendNoteOff (channel, note, velocity);
577 |
578 | Pad_setActive (padIndex, false);
579 |
580 | Touch_setPad (touchIndex, 0xff);
581 | Touch_setChannel (touchIndex, 0xff);
582 |
583 | Channel_setTrackedTouch (channel, 0xff);
584 |
585 | deassignChannel (note, channel);
586 | }
587 |
588 |
589 | /*
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 | */
--------------------------------------------------------------------------------