Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Flash] Simple AS3 Bridge Demo : Loading textures from web.

Discussion in 'Flash' started by RalphH, Mar 16, 2012.

  1. RalphH

    RalphH

    Administrator

    Joined:
    Dec 22, 2011
    Posts:
    592
    Example
    To give a small example of our ActionScript bridging functionality I made a small example to serve two purposes;
    1. Show how you could use the actionscript + C# to integrate flash functionality
    2. Show how to load textures from the web without WWW. (replacing missing functionality with Flash specific implementations).

    As an extra bonus, it implements the same functionality for the actionscript bridge in C#, so it also works in the editor.
    By no means is this an actual or stable replacement for WWW, but it should help making a temporary solution until we have a public flash preview with WWW enabled. (no release date for that just yet, sorry).

    The example uses very little of the inline ActionScript functionality offered by UnityEngine.Flash.ActionScript. That can still be used (and will remain to be supported, although expanded).

    Keep in mind that ActionScript is only supported for the Flash build target; ActionScript will not be compiled or used in on other targets.

    The main "magic" is in the following things;
    You can create a folder in your project named ActionScript; the files in this folder and it's subfolders will be compiled in the final flash build.
    Sidenote; you can also add .swc (Flash ActionScript libraries) to your project and they will be compiled in.

    The usage of [NotRenamed] and [NotConverted] attributes, which allow to switch off name mangling of functions and the actual conversion of scripts, and implement them in ActionScript.

    The only usage of UnityEngine.Flash.ActionScript is for one import statement to actually import the AS3 loader class.

    Still subject to change
    Again, by no means is this a replacement for WWW, we'll have full WWW support at a later point in time, until then, this will show you the ropes to do implementations of AS3 features and exposing them to C#. As we are still in development/preview, API's are still subject to change.

    We are aware there is currently no way to get a reference to the stage and do Flash 2D overlays. We'll find an elegant solution to do so in a future build. For now the only way to do so is using the UnityShared.swc embedding api and communicating with that to get the stage reference.

    Another thing subject to change is Flash "native" texture retrieval. Currently in this example it's a bit of a hack, but it works none the less. A more elegant and documented solution will be in a future build, while this will be deprecated/subject to change.

    Code (csharp):
    1.  
    2. var texture:Texture = Stage3DObjectMap.getInstance().getTexture(UnityNative.nativeTextureIDMap[nativeId]) as Texture;
    3.  
    A nicer way to retrieve textures can be achieved using the UnityShared.swc embedding API, as the loader exposes unitycontent, which in turn exposes getTextureFromNativeID(id:int).
    This example only deals correctly with POT textures with no mipmaps.

    Download and notes
    View attachment $Unity_Flash_Load_Texture_AS3.zip

    Given the same strategy as this implementation, one can implement networking, json, xml etc, using the ActionScript native implementations for that. Value objects can be shared between C# and ActionScript using the same attributes.
     
    Last edited: Mar 16, 2012
  2. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Wouaw, thank you UnityRalph !!!
     
  3. diese440

    diese440

    Joined:
    May 25, 2007
    Posts:
    105
    Great job UnityRalph,

    Thank you for sharing.
     
  4. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    New version for load Picture And/or Data with same constructor, and using delegate for event ;)

    Example
     
  5. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    New version with the error event ;)
     
  6. manuelv

    manuelv

    Joined:
    Feb 24, 2012
    Posts:
    14
    wonderful

    Great
     
  7. ina

    ina

    Joined:
    Nov 15, 2010
    Posts:
    1,080
    Is WWW support available yet for Flash
     
  8. RalphH

    RalphH

    Administrator

    Joined:
    Dec 22, 2011
    Posts:
    592
    Yes, check the thread about the new release on this forum.
     
  9. Breakmachine

    Breakmachine

    Joined:
    Sep 19, 2009
    Posts:
    39
    Hi Ralph

    Thank's for a great example!

    I'm struggling with passing an array of values from Flash to Unity (c#). Got any ideas? For example, let's say I have and Array of Strings in Flash and like to pass it to a string[] in c#. Obviously I want this to work with more advanced classes than String but you get the idea.
     
  10. amdk

    amdk

    Joined:
    Nov 24, 2011
    Posts:
    1
    hello everyone,

    I try implement a brige between flash(Unity build) and php, and take your exemple and work well, when i teste with my url get the same problem i have when i use class WWW and WWWForm a empty string. And i think my problem is on php, i start make change and discovery if i put (require or require_once, because e have other php files) i get a empty string, if i dont put i get the correct value. Any solution for that?

    Thanks
     
  11. tteneder

    tteneder

    Unity Technologies

    Joined:
    Feb 22, 2011
    Posts:
    174
    i found a way to do just that. Instead of using built-in arrays or Lists in C#, use a custom Array class, which is (due to [NotConverted]) just a placeholder later on an AS3 Array:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [NotConverted]
    5. [NotRenamed]
    6. public class Array {
    7.    
    8.     public object this[object key]
    9.     {
    10.         get { throw new System.NotSupportedException(); }
    11.         set { throw new System.NotSupportedException(); }
    12.     }
    13.    
    14.     public int length {
    15.         get { throw new System.NotSupportedException(); }
    16.     }
    17.    
    18.     public void push(object o) {
    19.         throw new System.NotSupportedException();
    20.     }
    21. }
    22.  
    for even more convenience in cross-platform coding, extend it further to support common things from the IList interface:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [NotConverted]
    5. [NotRenamed]
    6. public class FlashArray : Array {
    7.    
    8.     public int Count {
    9.         get {throw new System.NotSupportedException();}
    10.     }
    11.    
    12.     public void Add(object o) {
    13.         throw new System.NotSupportedException();
    14.     }
    15. }
    16.  
    if you have to be cross-platform, create your variable something like this:
    Code (csharp):
    1. #if UNITY_FLASH  !UNITY_EDITOR
    2. private FlashArray myArray = new FlashArray();
    3. #else
    4. private List<WhateverType> myArray = new List<WhateverType>();
    5. #endif
    6.  
    7. ...
    8.  
    9. myArray.Add( new WhateverType );
    10. Debug.Log(myArray.Count);
    11. WhateverType myType = (WhateverType) myArray[0]; // You HAVE to cast here, since AS3 arrays are not type safe.
    12. ...
    On the Actionscript side, you have to implement the derived FlashArray class (put it in some "ActionScript" folder inside the Assets folder):
    Code (csharp):
    1. package  
    2. {
    3.     /**
    4.      * ...
    5.      * @author Andreas Atteneder
    6.      */
    7.     public dynamic class FlashArray extends Array
    8.     {
    9.         public function Add(o:Object) :void {
    10.             this.push(o);
    11.         }
    12.        
    13.         public function get Count () : int {
    14.             return this.length;
    15.         }
    16.     }
    17. }
    and that's about it
     
  12. okokok

    okokok

    Joined:
    Aug 1, 2012
    Posts:
    24
    i use this on unity 4.07f its have bug like this

    Type 'TextureLoaderAS' has an extra field 'isDone' of type 'System.Boolean' in the player and thus can't be serialized
    UnityEditor.HostView:OnGUI()

    Type 'TextureLoaderAS' has an extra field 'width' of type 'System.Int32' in the player and thus can't be serialized
    UnityEditor.HostView:OnGUI()

    Type 'TextureLoaderAS' has an extra field 'height' of type 'System.Int32' in the player and thus can't be serialized
    UnityEditor.HostView:OnGUI()

    Error building player because script class layout is incompatible between the editor and the player.
     
    Last edited: Nov 25, 2012
  13. RalphH

    RalphH

    Administrator

    Joined:
    Dec 22, 2011
    Posts:
    592
    The script isn't compatible with Unity4.0f7; it can be modified, but as said in the other thread; in your case you can just use WWW. You'll need the ability to put a crossdomain.xml on the domain you are trying to load from/
     
  14. okokok

    okokok

    Joined:
    Aug 1, 2012
    Posts:
    24
    WWW can work On Unity 4.0

    use Crossdomain.xml
    Stay On Folder FIle Game ?

    Thank a lot for answer

    i use this but cant download my Crossdomain.xml

    to Load http://images.earthcam.com/ec_metros/ourcams/fridays.jpg

    <?xml version="1.0"?>
    <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
    <cross-domain-policy>
    <allow-access-from domain="http://images.earthcam.com/ec_metros/ourcams/fridays.jpg" />
    </cross-domain-policy>







    this is Code Load Texture
    #pragma strict
    var url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
    function Start () {
    // Start a download of the given URL
    var www : WWW = new WWW (url);

    // Wait for download to complete
    yield www;

    // assign texture
    renderer.material.mainTexture = www.texture;
    }

    IT SHOW " RED ? "

    please
     
    Last edited: Nov 28, 2012
  15. RalphH

    RalphH

    Administrator

    Joined:
    Dec 22, 2011
    Posts:
    592
    The crossdomain.xml needs to be placed on the domain you want to load from; if you can't upload to the domain (I'm pretty sure you can't upload to earthcam.com), that means that you can also not set the crossdomain.xml for that domain, in which the only case is to setup a 'proxy' on a domain you do control and pipe the traffic of the target domain through that.
     
  16. okokok

    okokok

    Joined:
    Aug 1, 2012
    Posts:
    24
    Can Load picture on facebook.com ?
     
  17. mtoivo

    mtoivo

    Joined:
    Jul 30, 2012
    Posts:
    274
    As it is stated numerous times: Flash sandboxing prevents it from loading stuff from other domains, unless crossdomain.xml is in place in the domain where the file is to be loaded. And since you probably cannot place such crossdomain.xml in facebook.com either, then you have to implement some kind of proxy (with simple php-script or similar in a domain you have control over) to bypass that restriction.
     
  18. okokok

    okokok

    Joined:
    Aug 1, 2012
    Posts:
    24
    Last edited: Nov 30, 2012
  19. actuallystarky

    actuallystarky

    Joined:
    Jul 12, 2010
    Posts:
    188
    Hello. I've had a stab at extending the provided demo to include support for streaming video to replace the missing Flash movieTexture support. I believe I've gotten close - I can hear the audio from my video playing but the texture doesn't show anything. I'm posting the sample code. Does anyone have any suggestions? Any help or advice at all would be really appreciated and almost certainly earn the person supplying it free beer.

    The Unity calling class, pretty straightforward.

    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.Flash;
    3. using System.Collections;
    4.  
    5. public class FlashVideoBridgeExample : MonoBehaviour
    6. {
    7.     public GUIText debugText;
    8.     public string dataPath = "http://disparitygames.com/TestProject/";
    9.     public string videoToLoad = "Resources/Akungwa";   
    10.     private VideoLoaderAS _videoLoaderAS;
    11.    
    12.     IEnumerator Start ()
    13.     {
    14.         debugText.text = "Beginning init";
    15.         videoToLoad = dataPath + videoToLoad;
    16.         ActionScript.Import("com.unity.example.VideoLoaderAS");//This won't do anything on NON Flash targets, but for Flash it will import the correct class.
    17.         _videoLoaderAS = new VideoLoaderAS(videoToLoad);
    18.         debugText.text = "video loader instance created";
    19.        
    20.         while (!_videoLoaderAS.isDone)
    21.         {
    22.             yield return null;
    23.         }
    24.         debugText.text = _videoLoaderAS.error;
    25.         var texture = new Texture2D(_videoLoaderAS.width, _videoLoaderAS.height, TextureFormat.ARGB32, false);//No mips, although it would be better to generate them in actionscript.
    26.         renderer.material.mainTexture = texture;
    27.         _videoLoaderAS.setToTexture(gameObject, texture.GetNativeTextureID());
    28.     }  
    29. }
    And the flash code. It seems to be close to the money but I have zero flash experience.

    Code (csharp):
    1.  
    2. package com.unity.example
    3. {
    4.     import com.unity.*;
    5.     import flash.errors.IOError;
    6.     import flash.media.Video;
    7.     import flash.net.NetStream;
    8.     import flash.net.NetConnection;
    9.     import flash.display.*;
    10.     import flash.system.LoaderContext;
    11.     import flash.events.ErrorEvent;
    12.     import flash.events.NetStatusEvent;
    13.     import flash.events.AsyncErrorEvent;
    14.     import flash.events.Event;
    15.     import flash.events.IOErrorEvent;
    16.     import flash.net.URLRequest;
    17.     import flash.display3D.textures.Texture;
    18.     import flash.geom.Matrix;
    19.  
    20.     public class VideoLoaderAS
    21.     {
    22.         private var _error:String;
    23.         private var flipMatrix:Matrix;
    24.         private var loader:Loader;
    25.         private var netStream:NetStream
    26.         private var _isDone:Boolean;
    27.         private var vid:Video;     
    28.        
    29.         public function VideoLoaderAS(url:String)
    30.         {
    31.             init();
    32.             _isDone = false;
    33.             var nc:NetConnection = new NetConnection();
    34.             nc.connect(null);
    35.             vid = new Video();
    36.             netStream = new NetStream(nc);
    37.             netStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
    38.             netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
    39.             vid.attachNetStream(netStream);
    40.             var fullURL:String;
    41.             fullURL = url + ".flv";
    42.             netStream.play(fullURL);
    43.         }
    44.        
    45.         private function netStatusHandler(event:NetStatusEvent):void //this never gets called even though the video's audio plays!
    46.         {
    47.                 switch (event.info.code)
    48.                 {                      
    49.                     case "NetStream.Play.Start":
    50.                         _error = "video ready to play";
    51.                         _isDone = true;
    52.                         break;
    53.                     case "NetStream.Play.Stop":
    54.                         _error = "video finished playing";
    55.                         break;
    56.                     default:
    57.                         _error = "unhandled net status event";
    58.                         _isDone = true;
    59.                         break; 
    60.                 }
    61.         }
    62.        
    63.         private function asyncErrorHandler(event:AsyncErrorEvent):void
    64.         {
    65.             _isDone = true;
    66.             _error = event.toString();
    67.         }
    68.        
    69.         private function init():void
    70.         {
    71.             flipMatrix = new Matrix();
    72.         }
    73.        
    74.         public function get width():int
    75.         {
    76.             return vid.videoWidth;
    77.         }
    78.        
    79.         public function get height():int
    80.         {
    81.             return vid.videoHeight;
    82.         }
    83.        
    84.         public function get isDone():Boolean
    85.         {
    86.             return _isDone;
    87.         }
    88.        
    89.         public function get error():String
    90.         {
    91.             return _error;
    92.         }
    93.        
    94.         public function setToTexture(unusedByFlash:*, nativeId:int):void
    95.         {
    96.             //Be aware that this does not upload mipmaps (as we defined the texture) and that flash only allows power of two texture sizes; to generate these for NPOT images, take the nearest power of two and scale to that in the bitmapdata before uploading.
    97.             var texture:Texture = Stage3DObjectMap.getInstance().getTexture(UnityNative.nativeTextureIDMap[nativeId]) as Texture;//This line is currently a bit of a hack, as it was originally only intended for internal use for the embedding API. In future versions we'll have an API.
    98.             texture.uploadFromBitmapData(getFlippedBitmapForVideo(), 0);
    99.         }
    100.        
    101.         private function getFlippedBitmapForVideo():BitmapData
    102.         {
    103.             var bitmapData:BitmapData = new BitmapData(vid.videoWidth, vid.videoHeight, false, 0); 
    104.             flipMatrix.identity();
    105.             flipMatrix.scale(1,-1);
    106.             flipMatrix.translate(0,bitmapData.height);
    107.             bitmapData.draw(vid, flipMatrix);
    108.             return bitmapData;
    109.         }
    110.     }
    111. }
     
  20. CristianoDuarte

    CristianoDuarte

    Joined:
    Feb 21, 2013
    Posts:
    3
    Hello actuallystarky. I do not quite understand how your code works, also do not know much about flash. It appears that lack a part. So I made some adjustments to the code, but was the maximum I could get pictures, videos did not work. Can you help me?
     
  21. RalphH

    RalphH

    Administrator

    Joined:
    Dec 22, 2011
    Posts:
    592
    Make sure that the texture settings for the texture you are rendering to are set correctly.
     
  22. rezzer123123

    rezzer123123

    Joined:
    Nov 18, 2013
    Posts:
    2
    I want to complete the loading of the video examples, please...
     
  23. frevd

    frevd

    Joined:
    Aug 29, 2013
    Posts:
    8
    This works with unity 4.3+ as well, if you make some changes (add the NotRenamed attribute to the c# class and remove the #if UNITY_EDITOR stuff).

    Also, only square POT texture seem to be supported.

    I happen to have textures that are POT in one dimension, width or height.
    Those can be loaded by adjusting the .as code as follows:

    private static function getFlippedBitmapForLoader(loader:Loader):BitmapData
    {
    var w = loader.width;
    var h = loader.height;
    var s = (w > h) ? w : h;
    var bmp : BitmapData = new BitmapData(s, s, false, 0);
    flipMatrix.identity();
    var xf = 1.0;
    var yf = 1.0;
    if (w < h) // non-square portrait, needs correction
    xf *= h / w;
    else if (h < w) // non-square landscape, needs correction
    yf *= w / h;
    flipMatrix.scale(xf, -yf);
    flipMatrix.translate(0, s);
    bmp.draw(loader, flipMatrix);
    return bmp;
    }

    If you have completely non-POT in width and height, you need to change the code a little further (find the neirest POT and stretch width and height to that).

    Best, frevd