Activity › Forums › Adobe After Effects Expressions › pick random number from given range (if possible: only once)
-
pick random number from given range (if possible: only once)
Posted by Patrick Grossien on July 1, 2022 at 9:35 amHi expression masters,
I have an array of color swatches from which I want to pick a random color to change a fill color every second. Right now I manage to step through all iterations, but I’d like to randomize the order – and if possible never pick the same color twice.
Any ideas?
Thanks a ton!
Patrick
// Color Swatch Picker
seedRandom(index, true);
colSwtCTRL_Layer = comp("Col Swatches SELECTOR").layer("GLOBAL COL CTRL Outlines");
colSwt_Layer = colSwtCTRL_Layer.effect("Layer Control")("Layer");
cFROM = colSwtCTRL_Layer.effect("Color Swatches – Select FROM")("Slider");
cTO = colSwtCTRL_Layer.effect("Color Swatches – Select TO")("Slider");
maxSWATCHES = colSwtCTRL_Layer.effect("max SWATCHES")("Slider");
t = Math.floor(time-inPoint);
if(cTO > maxSWATCHES) {cTO = maxSWATCHES};
c = linear(t, 0, 60, cFROM, cTO);
colSwt_Layer.content(c).content("Fill 1").color;Dan Ebbertsreplied 3 years, 10 months ago 2 Members · 11 Replies
-
11 Replies
-
Patrick Grossien
July 1, 2022 at 9:46 amOk I partially figured it out with help of a different post. But now : is there a way to make sure a number is not used twice or at least not twice right behind each other?
// Color Swatch Picker
var holdTime = 1;
seedRandom(Math.floor(time/holdTime), timeless = true);
// seedRandom(index, true);
colSwtCTRL_Layer = comp("Col Swatches SELECTOR").layer("GLOBAL COL CTRL Outlines");
colSwt_Layer = colSwtCTRL_Layer.effect("Layer Control")("Layer");
cFROM = colSwtCTRL_Layer.effect("Color Swatches – Select FROM")("Slider");
cTO = colSwtCTRL_Layer.effect("Color Swatches – Select TO")("Slider");
maxSWATCHES = colSwtCTRL_Layer.effect("max SWATCHES")("Slider");
t = Math.floor(time-inPoint);
//sec = Math.floor(t%60);
if(cTO > maxSWATCHES) {cTO = maxSWATCHES};
//c = linear(t, 0, 60, cFROM, cTO);
c = Math.floor(random(cTO,cFROM) + cFROM);
colSwt_Layer.content(c).content("Fill 1").color; -
Dan Ebberts
July 1, 2022 at 2:57 pmWhat I would do would be to put all your swatch choices into an array, then shuffle the array, and then read them out sequentially. You’d have to work this into your code, but shuffle part might look like this:
function shuffle(a) {
seedRandom(index,true);
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(random() * (i + 1));
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
cFrom = 1;
cTo = 9;
array = [];
for (i = cFrom; i <= cTo; i++){ // build the array
array.push(i);
}
shuffle(array);
-
Patrick Grossien
July 1, 2022 at 4:25 pmDan, thanks a million!
I am almost getting it to work. I now stumbled across a situation where the swatches are less than the cycles it goes through, thus needing to start the count through the array again.
Will need to fiddle with this. But this is the perfect direction for it! Thank you!
-
Dan Ebberts
July 1, 2022 at 5:01 pmIf you’re ok with repeating what’s in the shuffled array, you could just do some modulo math on whatever you’re using for an array index:
idx%array.length
-
Patrick Grossien
July 1, 2022 at 5:11 pmOh wow… it can be so simple a script, if you know what you’re doing 😅 I was fighting with while / if / for loops but this … oh my. Thank you!!!!
ended up doing the following and it works perfectly!
t = Math.floor(time-inPoint);
c = array[t%array.length]
colSwt_Layer.content(c).content("Fill 1").color; -
Patrick Grossien
July 1, 2022 at 5:16 pm// Color Swatch Picker
// shuffle array function
function shuffle(a) {
seedRandom(index,true);
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(random() * (i + 1));
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
// define variables
colSwtCTRL_Layer = comp("Col Swatches SELECTOR").layer("GLOBAL COL CTRL Outlines");
colSwt_Layer = colSwtCTRL_Layer.effect("Layer Control")("Layer");
cFROM = colSwtCTRL_Layer.effect("Color Swatches – Select FROM")("Slider");
cTO = colSwtCTRL_Layer.effect("Color Swatches – Select TO")("Slider");
maxSWATCHES = colSwtCTRL_Layer.effect("max SWATCHES")("Slider");
if(cTO > maxSWATCHES) {cTO = maxSWATCHES}; // only needed if there's a sub definition smaller than the swatches
// put swatches into array
array = [];
for (i = cFROM; i <= cTO; i++){ // build the array
array.push(i);
}
shuffle(array);
// define new color swatch every second - repeated if time > array length
t = Math.floor(time-inPoint);
c = array[t%array.length] // using odulo to repeat array
colSwt_Layer.content(c).content("Fill 1").color; -
Dan Ebberts
July 1, 2022 at 7:21 pmBTW, how do you post your code here so that you don’t get an extra blank line between lines with text? I’ve never been able to figure that out.
-
Patrick Grossien
July 1, 2022 at 7:58 pmSorry – I’m not sure – for me it just works like that.
I’m on a mac, copying / pasting straight from AE and then marking the text and styling it after having it pasted
It could differ depending on the source / origin app of the copied text maybe? Or if you start the style first and then paste/ type into the code style and not the other way round?
Just guess work though 🙈🙈🙈 sorry.
-
Patrick Grossien
July 2, 2022 at 5:13 pmseedRandom(index, true);
colSwtCTRL_Layer = comp("Col Swatches SELECTOR").layer("GLOBAL COL CTRL Outlines");
colSwt_Layer = colSwtCTRL_Layer.effect("Layer Control")("Layer");
cFROM = colSwtCTRL_Layer.effect("Color Swatches – Select FROM")("Slider");
cTO = colSwtCTRL_Layer.effect("Color Swatches – Select TO")("Slider");
maxSWATCHES = colSwtCTRL_Layer.effect("max SWATCHES")("Slider");
if(cTO > maxSWATCHES) {cTO = maxSWATCHES};
cNUDGE = Math.floor(effect("nudge selected color")("Slider"));
c = clamp(1, maxSWATCHES, Math.floor(random(cFROM, cTO))+cNUDGE);
colSwt_Layer.content(c).content("Fill 1").color;
-
Patrick Grossien
July 2, 2022 at 5:14 pmHi Dan, it seems to do the trick to paste the code, then mark all, then set the Textstile to code. Doing it the other way round creates the double returns for me, too. (see above)
Reply to this Discussion! Login or Sign Up