Play multiple timelines in order one at a time

you should not use HypeDocumentLoad but HypeTimelineComplete as event. should be ok to load it in the head or sceneload.

add some logging to the callback: console.log(event), console.log(element) and you’ll see what comes along …

I’m sorry I’m so confused. I’m a new user of Hype and coding really in general.

The main timeline pauses at say frame 40 and calls a function playFinalScene. Previous to 40, the user has determined the order they want played of 4 subtimelines (let’s say “dog”, “frog”, “clouds”, “sun”). The function that’s called is:

function playFinalScene(hypeDocument, element, event) {}

I’m confused as to where I would add the following block of code. Can I add it inside this function called on frame 40 in the main timeline?

function HypeDocumentLoadCallback(hypeDocument, element, event) {
	alert("hello");
}

if("HYPE_eventListeners" in window === false) { window.HYPE_eventListeners = Array(); }
window.HYPE_eventListeners.push({"type":"HypeTImelineComplete", "callback":HypeDocumentLoadCallback});

a sample hypedoc containing all necessary along with a description would be a good starting point …

1 Like

So if you go to scene 2 on the live site and click on the dog, or frog. It will make the number disappear or put it back in order. Each animal has an alternate timeline on the mainTimeline, but I want them to play in order. That is if the dog says 1, frog 2 and plants 3, I want the dog to play first, and right when that ends, the frog will play and then the plant and then stop. The animations that I want are not symbols although maybe that would help, they’re just alternate timelines from the main. I hope that makes sense! Thanks in advance for any help.

Jayz copy.hype.zip (119.4 KB)

There is a lot going on in that project for people to get their heads around. Always helps if the posted example is simplyfied and just contains whats needed to explain further.

So any way I am not sure whats supposed to happen in all that but this may help you

Sorry I'm new here, and I was also afraid if I modified too much that it would stop working altogether. The example from that thread you sent though is almost what I'm looking for:

In my example the user clicks on A B C or B C A or A C B, and the blocks would animate in that order, not initiating their respective timeline until the last block's was complete. In my case though I have 5 objects the user would choose to put in order and animate in that order.

Here's the relevant code:

Verb 1 is a dog that wags it's tail, verb2 is a frog that jumps and verb3 is a plant that blows in the wind. The global variables (e.g. dog will play first) that the user later modifies are:

    hypeDocument.verb1 = {
 		pret: true, 
 		place: 1, 
};

 hypeDocument.verb2 = {
 		pret: true, 
 		place: 2, 
};

 hypeDocument.verb3 = {
 		pret: true, 
 		place: 3, 
};

Each time the user clicks on the dog or the frog or the plant, it either takes them out of the "rotation" or adds them back to the order. So if the user clicked on dog, frog would then be in "place" 1 and the plant in "place" 2. If you click on dog again, it will be added again a "place" 3. This code is added as onClick events:

// find out how many verbs are in "rotation"
var i;
hypeDocument.greatest=0;

var dummy=0;

for (i = 1; i < 6; i++) {
	eval('var dummy2=' + 'hypeDocument.verb' + i + '.pret' + ';');
	
	if (dummy2 == true) {
		eval('dummy=' + 'hypeDocument.verb' + i + '.place' + ';');
	
		// example if hypeDocument.verb1.place > hypeDocument.greatest
		if  (dummy > hypeDocument.greatest) {
		
		hypeDocument.greatest=dummy;
		
		}
	}

}

//// when verb is preterite, remove from verb list and move all other verbs up in place position
///////////////////////////////////////////

if (hypeDocument.verb1.pret == true) {
	
	hypeDocument.verb1.pret = false;
	hypeDocument.verb1.place = 0;
	
	var y;
	for (y = 1; y < hypeDocument.greatest; y++) {
	//move other verbs up a place
		var empty_spot = true;
	
		// on 1st iteration find out if there's a verb in first place 
		var i;
		for (i = 1; i < 6; i++) {
	
			//// if any of the verb.place's equal to 1, set empty_spot to false
			eval('var dummy4=' + 'hypeDocument.verb' + i + '.place' + ';');
			
			if (dummy4 == y) {
				empty_spot = false; // there is no need to move verbs up
			}
		}
		
		if (empty_spot == true) { 
		//find out which verb has a place of y + 1, make that verb y
			for (i = 1; i < 6; i++) {
			
				eval('var dummy5=' + 'hypeDocument.verb' + i + '.place' + ';');
				if (dummy5 == y + 1) {
					eval('hypeDocument.verb' + i + '.place=' + y + ';');
				}
			}
		}
	}
}

else {
hypeDocument.verb1.pret = true;
hypeDocument.verb1.place = hypeDocument.greatest + 1;
}

If the user has chosen that dog has a place of 2, frog 3 and plant 1. Ideally I want there to be a button the user can then click which will play the dog, frog and plant timelines in that order.

  1. Play plant timeline in entirety and stop
  2. Play dog timeline in entirety and stop
  3. Play frog timeline in entirety and stop. COMPLETE

Just knocked this together.

The code has comment. There is a Timeline Action at the end of each timeline that run selectOrder() function.

Each button has a data attribute with its corrosponding timeline name.


On Each button click we add the data attribute to an key/value object.
We limit double selection this way and the code limits select by counting.
We then run a second function then run the correct timeline in order by using a corrosponding index number to match the run order and key names in the object.

SelectOrder function for each button.

	//-- Lets init some stuff
			if (typeof hypeDocument.customData.selectionOrder == "undefined"){
			
			//-- index to use a object key
			hypeDocument.customData.selectionCounterIndex = 1
			//-- order object
				hypeDocument.customData.selectionOrder = {}
 			}
 			
 			
 	 
 			//-- if the order object does not already have the data attribute value of the button..
 			if(! Object.values(hypeDocument.customData.selectionOrder).includes(element.dataset.timeline)  ){
 			
 			//-- Set the value of the key using the data attribute for the button ( each button has a data attribute with the timeline name)  as the value and index numberas the key.. 
 			hypeDocument.customData.selectionOrder[hypeDocument.customData.selectionCounterIndex] = element.dataset.timeline
 			
 			//-- add 1 to the index number
 			hypeDocument.customData.selectionCounterIndex++
 			}
 			
 			
 			//-- only run if all buttons are pressed
 			if(hypeDocument.customData.selectionCounterIndex > 3){
 			console.log(hypeDocument.customData.selectionOrder)
 			
 			
 			//-- call the runINOrder function
 			hypeDocument.functions().runInOrder(hypeDocument, element, event)
 			
 			
 			}

RunInOrder function

	//-- init a counter index
		if (typeof hypeDocument.customData.runOrder == "undefined"){
			hypeDocument.customData.runOrder = 1
		 
 			}
 			
 			//-- only run # times
	if  ( hypeDocument.customData.runOrder < 4 ){
	
	//-- get the selectionOrder item using the new index number as the key to look for.
	var thisOrderItem = hypeDocument.customData.selectionOrder[hypeDocument.customData.runOrder]
	
	////-- use the value to run the timeline
	 
	  
	  hypeDocument.startTimelineNamed(thisOrderItem, hypeDocument.kDirectionForward)
	  hypeDocument.customData.runOrder++
	
	}  

runInOrder.hype.zip (19.8 KB)

2 Likes

OMG yes this is exactly what I wanted! Now let me go through and see if I can understand it well enough to modify my existing code to match. Thanks so much!

1 Like

Just makes sure download the one there now. I did a small update…

1 Like

Redownloaded thanks! :partying_face:

1 Like

Where its say in the comments of the example project;
//-- if the order object does not already have the id value of the button…

I meant data attribute value.
originally used an id and forgot to change the commen.
Not worth uploading again.

one thing to mention: All of the artwork is done with Hypes pathtool. That’s great! @Jonathan will love it :slight_smile:

put it together too, but more or less the same approach :wink: @MarkHunte’s file is done more careful :slight_smile:
playTimelinesInOrder.hype.zip (17.6 KB)

3 Likes

Great Minds… :brain:

shoutout :wink: funny thing: last saturday (or one saturday before … ) i turned the radio up again, cause it’s been quite nice and he did the shoutout again :wink: refresh :slight_smile:

Yer, There are repeat play lists. Its a 24/7 station

So I’m trying to use your code in my project where I already had existing code but I’m having some difficulty. So to start there’s three verbs which will play in order, as in your coding example, but there’s 5 verbs total. Right now my code is working in that the user can pick which 3 verbs will be in order to eventually play.

	    // figure out how many verbs are on/off to be able to join order
    ///////////////////////////////////////////
    var i;
    hypeDocument.greatest=0;
    var dummy=0;
    for (i = 1; i < 6; i++) {
    	eval('var dummy2=' + 'hypeDocument.verb' + i + '.pret' + ';');
    	
    	if (dummy2 == true) {
    		eval('dummy=' + 'hypeDocument.verb' + i + '.place' + ';');
    	
    		// example if hypeDocument.verb1.place > hypeDocument.greatest
    		if  (dummy > hypeDocument.greatest) {
    		hypeDocument.greatest=dummy;
    		}
    	}
    }

    //// when verb is on (.pret == tue), remove from verb list and move all other verbs up in place position
    ///////////////////////////////////////////

    if (hypeDocument.verb1.pret == true) {

    	hypeDocument.verb1.pret = false;
    	hypeDocument.verb1.place = 0;
    	
    	var y;
    	for (y = 1; y < hypeDocument.greatest; y++) {
    	//move other verbs up a place
    		var empty_spot = true;
    	
    		// on 1st iteration find out if there's a verb in first place 
    		var i;
    		for (i = 1; i < 6; i++) {
    			//// if any of the verb.place's equal to 1, set empty_spot to false
    			eval('var dummy4=' + 'hypeDocument.verb' + i + '.place' + ';');
    			
    			if (dummy4 == y) {
    				empty_spot = false; // there is no need to move verbs up
    			}
    		}
    		
    		if (empty_spot == true) { 
    		//find out which verb has a place of y + 1, make that verb y
    			for (i = 1; i < 6; i++) {
    			
    				eval('var dummy5=' + 'hypeDocument.verb' + i + '.place' + ';');
    				if (dummy5 == y + 1) {
    					eval('hypeDocument.verb' + i + '.place=' + y + ';');
    				}
    			}
    		}
    	}
    }

//if verb is "off" turn it back "on" (.pret==true)
    else {
    hypeDocument.verb1.pret = true;
    hypeDocument.verb1.place = hypeDocument.greatest + 1;
    }

At the very beginning frame I set global variables like so:

 hypeDocument.verb1 = {
 		pret: true, 
 		place: 1, 
};

Would I just add another key such as ‘data-pret’ with a value of true or false and then when the user clicks on one of the buttons it’ll first change the value of ‘data-pret’, and only set the order if ‘data-pret’ also == true?

hypeDocument.customData.selectionOrder[hypeDocument.customData.selectionCounterIndex] = element.dataset.pret

    //-- if the order object does not already have the data attribute value of the button..
		if(! Object.values(hypeDocument.customData.selectionOrder).includes(element.dataset.timeline)  **&&  hypeDocument.customData.selectionOrder[hypeDocument.customData.selectionCounterIndex] == true**){
		
		//-- Set the value of the key using the data attribute for the button ( each button has a data attribute with the timeline name)  as the value and index number as the key.. 
		hypeDocument.customData.selectionOrder[hypeDocument.customData.selectionCounterIndex] = element.dataset.timeline
		
		//-- add 1 to the index number
		hypeDocument.customData.selectionCounterIndex++
		
		}

Below is not answering you question… but…

I assume you are trying to search in these objects:

hypeDocument.verb1 = {
 		pret: true, 
 		place: 1, 
 		pret_sentence: "el perro meneó la cola", 
 		imp_sentence: "el perro meneaba la cola"
};

First place them in a hypeDocument.customData global var. not on the hypeDocument as you are doing.

i.e

hypeDocument.customData.verb1 = {
pret: true,
place: 1,
pret_sentence: “el perro meneó la cola”,
imp_sentence: “el perro meneaba la cola”
};

You seem to be using a for loop to pick up the correct verb and using the loops index to get the number i.e verb1, verb2.

Not sure why you are using eval you should avoid this. ( or what you are doing )

You should be able to do for example:

hypeDocument.customData.greatest=0;
var dummy=0;
    for (i = 1; i < 6; i++) {
    	 var dummy2=  hypeDocument.customData['verb' + i ].pret
   
    	if (dummy2 == true) {
    		 
             dummy=  hypeDocument.customData['verb' + i ].place
    	 
    		if  (dummy > hypeDocument.customData.greatest) {
    		hypeDocument.customData.greatest=dummy;
    		
    		}
    	}

    }

If I get a min I will try and have a look it. But no promises…

1 Like

Thanks no worries if you can’t take a look! I honestly used eval even though I saw it was a bad idea because I could wrap my head around its use given my level of programming understanding. I never really got around to objects or indexes in computer programming in high school or when I was programming with Actionscript back in the day.

So eval.

In this case Evaluates the concatenated string construction into an executable command…

You generally really do not want this in your code.

Read this

And from whaI can see all you really want is to be able to convert a string and a var value into an object name.

We do this as I have shown using the square bracket. []

The JavaScript API will convert the concatenated string/var into an object’s name.

And it can be used as a direct reference to the object with that name.

1 Like