So where we finished last time? Oh I know now we know the coordinates of mouse click and pointer to a FaceShape instance. Why FaceShape, its simple if we only had Shape instances there would be no pointer back to a triangle data which rendered into that particular Shape. Thats why i made a simple class FaceShape which extends Shape class and contains pointer to a RenderFace instance. I’ll rather not go back into other solutions mentioned in previous part but suffice to say that if you use sprite method you will probably create something like FaceSprite or if you go the math method you will access the RenderFace structures directly anyway. But lets concentrate only on FaceShape solution. If you have any general questions about how to implement this with other method used up to this point just ask ;)
Now we have projection space coordinates which is simple mouse coordinates on the screen and projected vertices of the RenderFace, with both of these its a simple math using triangle equation to get the coeficients for position of the mouse coordinates within that triangle. Using these coeficients in the same equation using projected UV coordinates we can get exact UV coordinates where user clicked within the texture. There can be additional math involved if you use stuff like multitexturing or UVs outside 0/1 range or additional texture dependent mapping stuff you implemented, but basically thats it. Tadaa, simple enough now that we have the UV coordinates of the user mouse interactivity we want to propagate it to the interactive texture.
Here we are at the crossroad again, we have 2 options to go.
1. standard method used since Flash8, uses hidden InteractiveObject instance that overlapping the scene where user interacts.
2. using more sophisticated event model of AS3 to propagate events without direct user interaction
I am sure you all are aware of the 1st method, anyone that used some kind of texture interactivity in old Flash8 engines probably encountered it in one way or another. The principle is quite easy we have an InteractiveObject(it was MovieClip in Flash8) instance on the scene at all times interactivity is in progress but its not visible. Moving mouse over the interactive texture just provides information about positioning of the “invisible” InteractiveObject, and since its on the stage it will catch the mouse events directly all we need to do is position it correctly so the mouse over the object is always at the correct point. And we are pretty much done everything else will work automatically.
Downside to this method is that we need to have the InteractiveObject in the scene. It can’t be invisible as in visible=false since such objects don’t catch mouse events so we need to just fade it away using alpha=0 but as you already know there is a glitch, for example non-embedded texts can’t have alpha values. Other issue is if you are catching mouse move events which move in the opposing direction as the offset goes your movement will be jagged. I am not making myself clear here probably but its hard to explain, this problem is due to the double movement going on, first you need to position the IO instance into correct place so you move it but at the same time it catches the mouse move event. This is not major problem since this is visible only in few applications, like a texture painter for example.
Now onto the 2nd solution, one can say this is more complicated one but at the core its basically the same thing. In this scenario we don’t have the IO instance on the stage we just have it in memory but we don’t add it to the display tree (hence it wasn’t possible before AS3). Instead of offseting the IO instance within stage as in previous scenario we will propagate the event directly to the IO instance. So what goes on, we capture a mouse event, change its coordinates to the correct coordinates based on the UV coordinates we clicked, and then propagate it to the InteractiveObject instance. This can be a chain of methods, just for illustration in Agile3D since FaceShape refers to RenderFace instance which refers to material instance which refers to its texture instances where texture refers to its InteractiveObject element.
But there are downsides again, for example this will not work with native functionality within flash such as dynamic text selection. Basically any stuff that can’t be invoked only with mouse events but needs to actually happen will not work.
So there is not a ONE correct solution, it all depends what are you trying to achieve. Agile3D currently supports both methods, which let me tell you is a mess right now due to all the testing and tracing i did, you can picture it.
I hope i was making sense, sometimes its hard to explain something without going into unnecessary detail or math. That way it would be 20 pages long probably. If by any chance something isn’t explained enough or its confusing just ask as always ;)
Next i will post an Agile3D demo example of scene/texture interactivity.