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

Coherent UI - HTML5-based User Interface middleware

Discussion in 'Assets and Asset Store' started by stoyannk, Oct 30, 2012.

  1. stoyannk

    stoyannk

    Joined:
    Oct 30, 2012
    Posts:
    35
    We are almost ready with the final release of the product and the web site is not up--to-date. A focus of ours is to support the indie community, so we plan to offer 3 or 4 different licensing options. There won't be a per-year subscription.
     
  2. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Ok, thank you for clarification. I'm a professional web developer (over 6 years of experience). So am incredibly interested in this. Basically when it's released point me in the right direction and i'll open the wallet, lol. I've been using NGUI and it's just a pain in the butt for me at least; doesn't give the UI results I am used to creating for websites. Do you have an ETA of when release will be? I assume it's also easy to interact with buttons, etc.. using scripts such as on click events and various things of that nature (updating health bars, etc..).
     
  3. stoyannk

    stoyannk

    Joined:
    Oct 30, 2012
    Posts:
    35
    If you want to try it out now, register on the site or drop me a PM. The current trial version is 99% what will be available on the asset store. ETA is very soon - a week or two I suppose.
    Binding events is extremely easy. JS can trigger Unity messages directly and you can call JS from Unity just as easily.
     
  4. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    We have a new Unity3D tutorial we would like to show you. We've integrated a small HTML5 game inside the engine as a challenge for the player. He needs to complete it in order to open a closed door that is stopping him from proceeding further.

    Read our blog post for more information on how to do it by yourself http://blog.coherent-labs.com/2013/02/html5-game-unity-3d.html

    Check out the video as well.

    http://youtu.be/m-s9mlTn45o
     
  5. zyzyx

    zyzyx

    Joined:
    Jul 9, 2012
    Posts:
    226
    Very cool!
    So there wont be an updated beta version?
     
  6. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    We won't be updating our beta. The reason is because on Monday we are releasing our final version for desktop platforms.
     
  7. kenlem

    kenlem

    Joined:
    Oct 16, 2008
    Posts:
    1,630
    Any update on the mobile version?
     
  8. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    I can't give you specific information about it. I will let you know when we have some news.
     
  9. imtrobin

    imtrobin

    Joined:
    Nov 30, 2009
    Posts:
    1,548
    I want the mobile version too.
     
  10. zyzyx

    zyzyx

    Joined:
    Jul 9, 2012
    Posts:
    226
    Any news on this?
     
  11. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
  12. Yann

    Yann

    Joined:
    Oct 20, 2007
    Posts:
    432
    @MartinZhel : congrats on the Mac release, Coherent UI is becoming more and more attracting. Just would like to add my voice to those expressing their strong interest in a mobile port :)
     
  13. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    @Yann: thank you for your feedback. We are looking forward to bring Coherent UI available on other platforms as well.
     
  14. whorfin

    whorfin

    Joined:
    Mar 23, 2013
    Posts:
    3
    Goofing around with the trial version of this. Nice tool, I like it very much.

    I got the basic jQuery UI page up and running attached to the camera and noticed a bug, though. The mouse cursor Y seemed inverted, but only for movement and hovering, not for clicks.

    As a quick fix I changed InputManager.cs's GenerateMouseEvent(), where it sets the mouseMoveEvent.Y to the mousePosition.y, to instead set it to Screen.height-mousePosition.y. Seemed to fix it for my goofing around, but that's maybe not the right fix.
     
  15. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    Hi whorfin,
    glad to hear that you like our product and thank you for your feedback.

    The behavior you're describing is indeed not intuitive and we'll be fixing that in the next version. Until then, you can try the approach we use in our samples - calling CoherentUIView.SetMousePosition with the inverted Y coordinate each Update cycle. Check out MenuScript.cs in Sample03 or InputForward.cs in Sample04 for reference. You could also use the "Click-to-focus" feature of the view if it's suitable for your needs.

    Thanks again for your comment - we hope that with the help of our fans we can make the product better :).
     
  16. whorfin

    whorfin

    Joined:
    Mar 23, 2013
    Posts:
    3
    Ah, cool, thanks. Hadn't spotted the Update() thing. I'll switch over to doing that.

    New question.

    I'm trying to catch events from JavaScript in C#. I've tried both RegisterForEvent() and the CoherentMethod attribute, with the binding flag set. With RegisterForEvent() I was doing it inside a delegate catching the ReadyForBindings event. And with the automated binding with the attribute, I just made sure to have it on a component on the same GameObject. But I can't get either method work.

    Adding some log statements, it seems like the ReadyForBindings event is never firing. I logged the attribute stuff, and watched it find my component, and my function with the attribute, and add it to the list for binding, but none of the log statements in the CoherentUIView.ReadyForBinding() function are ever getting hit.

    Is there a step I might be missing that would cause this?

    The UI itself (the jQuery test page) seems to be completely functional, and I get the ViewCreated event just fine...
     
  17. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    Hi there again,

    Sounds like you're not including the coherent.js script in your test page (you can find it in the Assets/CoherentUI/JavaScript.zip archive) - it's necessary to setup the JS binding and fire the ReadyForBindings event.

    Please let me know if this was your issue.
     
  18. whorfin

    whorfin

    Joined:
    Mar 23, 2013
    Posts:
    3
    That was it. Thanks, man!
     
  19. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I receive the below after import of 1.5.0 Pro Trial.

    Code (csharp):
    1. There are inconsistent line endings in the 'Assets/CoherentUI/Editor/CoherentUI/CoherentUIInstaller.cs' script. Some are Mac OS X (UNIX) and some are Windows.
    2. This might lead to incorrect line numbers in stacktraces and compiler errors. Many text editors can fix this using Convert Line Endings menu commands.
    3.  
    Am on Windows 7 64bit. I know it's just a line ending warning and nothing major by a long shot, but just letting you know.
     
  20. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Performance different is quite large compared to NGUI and by that I mean for the better. On average with NGUI I have 700fps. On average with CoherentUI I have 900fps. This is very very nice. I'm also previewing my GUI inside of my web browser instead of in game for quick development. This is absolutely brilliant. Will keep exploring the trial, but at this point I think I'm sold.
     
  21. Acenth

    Acenth

    Joined:
    Aug 14, 2012
    Posts:
    42
    I've been using CoherentUI since they announced the Unity beta and I must say it is pretty awesome.

    Their support is just amazing, quick to respond with helpful information and with fixing bugs.
     
  22. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    Thanks for letting us know about this. We're going to fix the line endings in the next update.

     
  23. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I'm using the trial now to develop my UI and once I'm done and sure it'll work as an acceptable replacement I plan to purchase. Is the upgrade from trial to indie pretty smooth sailing?
     
  24. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    The migration of trial to commercial versions is seamless. Trial has the same API and only a few limitations that does not exists in the commercial versions.

     
  25. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, thank you. I'm sold at this point as seams to fit my needs and is very easy to use.
     
    Last edited: Mar 25, 2013
  26. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    There's a lot of documentation to go through. Is there a simple tutorial or can you point me in the right direction to set a value in the local view (it's my HUD) every frame from C#? I'm needing to update a timer and a few other things every frame, but am not seeing how to send this to the view and can only find how to call a function from the view using JS, but isn't what I'm looking for.

    Looks like within my HUD in JS I should have engine.on respond to a event and update the variable using jQuery or JS and in Unity I trigger this using coherentUIView.View.TriggerEvent("MyEvent", args);. Would this be correct? Seams to be what I'm looking for.
     
    Last edited: Mar 26, 2013
  27. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    Hi Krileon,

    The way you figured out is the correct one :). You send the data using View.TriggerEvent and it's handled by the function you registered with engine.on in the HTML/JS side. Make sure you've included coherent.js so the whole machinery works.

    If you need the other direction (JS -> C#) the usage is similar. You invoke engine.call / engine.trigger in JS and register the handlers in C# with View.BindCall and View.RegisterForEvent, respectively. The difference between the two is that a call can have only a single handler, while an event may have many.

    You can check the Binding sample that we have for a complete example. It doesn't send data per frame but it can be easily modified to do so.

    If you have suggestions on improving the documentation so it doesn't look so scary, please let us know :).
     
  28. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, thank you.

    Yup, already done. :)

    Ok, great; believe I'll have uses for both.

    I should be ok doing this with the engine.on and coherentUIView.View.TriggerEvent usage, correct? I'd just call TriggerEvent every frame basically.

    I couldn't find the Unity code associated with the samples to understand the relationship between the engine usages in JS.
     
  29. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    @KriLeon, thank you for your feedback. We will try to improve the documentation about the binding between JavaScript and Unity to make it more clear for devs.
     
  30. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    Yes, that's it.

    There's a small write-up on the JS<->Unity communication in section 3.4 Bindig demo of the pdf, describing the sample. In any case, we'll try to make the documentation on binding clearer - thank you for your feedback.
     
  31. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, thank you for confirmation. Will give it a shot in the coming days (I'll be occupied with Bioshock Infinite for now, lol). Completely awesome asset. Makes UIs extremely easy if you're skilled with HTML/CSS/JS such as my self. I let my UI sit for months due to hating NGUI usage (just not my cup of tea), but with this I already have a nice looking UI put together. Thanks again!
     
  32. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Have I hit a limitation of the trial with the below?

    Code (csharp):
    1.  
    2. No overload for method `TriggerEvent' takes `2' arguments
    3.  
    This happens when using the below code.

    Code (csharp):
    1.  
    2. Hashtable options = new Hashtable();
    3.  
    4. options.Add( "test", true );
    5.  
    6. view.View.TriggerEvent( eventName, options );
    7.  
    I've followed the instructions of the documentation translating JS usage to C#, but doesn't seam to work. Is this just a limitation of the trial or am I doing something wrong? Also is an associative array even needed? In the HTML JS it's using options[INT] and not an associative value so this is rather confusing as to what the proper usage should be (if possible please in the future provide C# examples too).
     
    Last edited: Mar 30, 2013
  33. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    @Krileon

    No, this is not a limitation of the trial version, but rather something we missed in the documentation. You need to add a
    Code (csharp):
    1. using Coherent.UI.Binding;
    directive to use TriggerEvent with arguments. The template extension methods are defined in that namespace and provide means for passing up to 8 arguments.

    As for the associative array, it isn't needed - you can bind anything you like, provided you expose the properties of your custom data structures using the [CoherentType(PropertyBindingFlags.***)] property. Here's a simple example for passing a non-associative container to JS:

    Code (csharp):
    1.  
    2. // C#
    3. m_View.View.TriggerEvent("TestFunc", new object[] { "the answer to life, the universe and everything", 42 });
    4.  
    Code (csharp):
    1.  
    2. // JS
    3. engine.on("TestFunc", function(arr) {
    4.     for (var i = 0; i < arr.length; ++i) {
    5.         console.log(arr[i]);
    6.     }
    7. });
    On a sidenote, I'd like to thank you again for reporting all those issues and we'll make sure that the next update of Coherent UI doesn't have them.
     
  34. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, that fixed it.

    So I can't pass an array or object of as many variables as I want? For example if I wanted to pass an array with 20 variables I can only access the first 8? Also what kind of variables can I pass? Objects, strings, integers, etc.. anywhere I can find a list of those that are acceptable?

    Right, but if you pass an associative array can you do the following for example.

    Code (csharp):
    1.  
    2. // JS
    3. engine.on("TestFunc", function(arr) {
    4.     console.log(arr['test_variable']);
    5. });
    6.  
    Glad I could help! As a side note from my self I'll be purchasing next week; just waiting for paycheck to come through. :) This is absolutely awesome and my HUD looks fantastic (easily 100x better looking then my current NGUI implementation).

    Also I can't seam to get the argument list built properly in C#. Even your example errors out. Please provide a working C# example so I can build my list of arguments to pass. ListArray gives me a large amount of errors complaining about GetProperty, etc.. I'm making this as a PlayMaker action and I'm dynamically populating the ListArray based off the variables passed to the action, which all works fine except I can't get CUI to accept my list. My current usage is as follows.

    Code (csharp):
    1.  
    2.             ArrayList options = new ArrayList();
    3.  
    4.             if ( ! string1.IsNone ) {
    5.                 options.Add( string1.Value );
    6.             }
    7.  
    8.             if ( ! string2.IsNone ) {
    9.                 options.Add( string2.Value );
    10.             }
    11.  
    12.             if ( ! string3.IsNone ) {
    13.                 options.Add( string3.Value );
    14.             }
    15.  
    16.             if ( ! string4.IsNone ) {
    17.                 options.Add( string4.Value );
    18.             }
    19.  
    20.             if ( ! string5.IsNone ) {
    21.                 options.Add( string5.Value );
    22.             }
    23.  
    24.             if ( ! int1.IsNone ) {
    25.                 options.Add( int1.Value );
    26.             }
    27.  
    28.             if ( ! int2.IsNone ) {
    29.                 options.Add( int2.Value );
    30.             }
    31.  
    32.             if ( ! int3.IsNone ) {
    33.                 options.Add( int3.Value );
    34.             }
    35.  
    36.             if ( ! int4.IsNone ) {
    37.                 options.Add( int4.Value );
    38.             }
    39.  
    40.             if ( ! int5.IsNone ) {
    41.                 options.Add( int5.Value );
    42.             }
    43.  
    44.             if ( ! bool1.IsNone ) {
    45.                 options.Add( bool1.Value );
    46.             }
    47.  
    48.             if ( ! bool2.IsNone ) {
    49.                 options.Add( bool2.Value );
    50.             }
    51.  
    52.             if ( ! bool3.IsNone ) {
    53.                 options.Add( bool3.Value );
    54.             }
    55.  
    56.             if ( ! bool4.IsNone ) {
    57.                 options.Add( bool4.Value );
    58.             }
    59.  
    60.             if ( ! bool5.IsNone ) {
    61.                 options.Add( bool5.Value );
    62.             }
    63.  
    64.             view.View.TriggerEvent( eventName.Value, options );
    65.  
    Your example usage with new object[] gives the below.

    Code (csharp):
    1.  
    2. NullReferenceException: Object reference not set to an instance of an object
    3. Coherent.UI.Binding.ViewExtensions.TriggerEvent[Object[]] (Coherent.UI.View view, System.String name, System.Object[] argument1)
    4.  
    My usage above gives the below.

    Code (csharp):
    1.  
    2. NullReferenceException: Object reference not set to an instance of an object
    3. Coherent.UI.Binding.ViewExtensions.TriggerEvent[ArrayList] (Coherent.UI.View view, System.String name, System.Collections.ArrayList argument1)
    4.  
    5. InvalidProgramException: Invalid IL code in (wrapper dynamic-method) System.Collections.ArrayList:GetProperty (System.Collections.ArrayList,Coherent.UI.Binding.Exporter): IL_0003: call      0x00000001
    6.  
    7. Non matching Profiler.EndSample (BeginSample and EndSample count must match)
    8. System.Reflection.Emit.DynamicMethod:CreateDelegate(Type)
    9. Coherent.UI.Binding.DynamicCode:CreateGetter(Type, PropertyInfo, MethodInfo)
    10. Coherent.UI.Binding.UserDefinedTypeExporter`1:CreateGetter(Type, PropertyInfo)
    11. Coherent.UI.Binding.UserDefinedTypeExporter`1:.ctor(Type)
    12. Coherent.UI.Binding.Exporter:CreateUserTypeExporter(ArrayList)
    13. Coherent.UI.Binding.Exporter:Export(ArrayList)
    14. Coherent.UI.Binding.ViewExtensions:TriggerEvent(View, String, ArrayList)
    15.  
    I've also tried the below, which also errors and does not work.

    Code (csharp):
    1.  
    2. view.View.TriggerEvent( eventName.Value, "test" );
    3.  
     
    Last edited: Mar 31, 2013
  35. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    You can pass up to 8 arguments to the TriggerEvent method - e.g. view.TriggerEvent("MyFunc", arg1, arg2, ..., arg8 ); Each of these arguments can be an array of a million elements if you wish and all of them will be accessible (although you should try to avoid passing that many elements :)).

    Primitive types, arrays and generic collections (IList and IDictionary) can be exported automatically. User defined types must be decorated with the CoherentType attribute. You can read about the binding in the Coherent_UI_Documentation.chm file (not the pdf), chapter "Binding for .NET".

    Yes, you can - it seems I didn't understand your question last time.

    The NullReferenceException can be caused if you're trying to bind anything before you receive the ReadyForBindings event. Please make sure you do all your binding after that.

    The other error is because we have only exposed generic collections, and not ones such as ArrayList, Hashtable, Stack, Queue, etc. (thanks for spotting that!). You'll get the same error if you try to pass a user-defined type which is not exposed. Obviously, you can't do that for core framework types yourself, so we'll expand the set of those types in a future version so they can be bound as well. As a temporary workaround you can use List<object> or Dictionary<object, object> instead of ArrayList/Hashtable.

    Finally, here's the example you asked for (the scene is just a new scene with a camera only and CoherentUIView and TestComponent components attached):

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6. using Coherent.UI.Binding;
    7.  
    8. public class TestComponent : MonoBehaviour {
    9.    
    10.     private CoherentUIView m_View;
    11.    
    12.     void Start () {
    13.         m_View = GetComponent<CoherentUIView>();
    14.         m_View.Listener.ReadyForBindings += HandleReadyForBindings;
    15.        
    16.         //SendDataToJS(); // Causes NullReferenceException, any binding must be done after the ReadyForBindings event is fired
    17.     }
    18.  
    19.     void HandleReadyForBindings (int frameId, string path, bool isMainFrame)
    20.     {
    21.         if (isMainFrame)
    22.         {
    23.             SendDataToJS();
    24.         }
    25.     }
    26.    
    27.     void SendDataToJS()
    28.     {
    29.         var arg1 = new object[] { "a string", 42, 3.14 };
    30.        
    31.         var arg2 = new List<string>();
    32.         arg2.Add ("Lorem");
    33.         arg2.Add ("ipsum");
    34.         arg2.Add ("dolor");
    35.         arg2.Add ("sit");
    36.         arg2.Add ("amet");
    37.        
    38.         var arg3 = new Dictionary<object, object>();
    39.         arg3.Add("string key", "string value");
    40.         arg3.Add(1, 2);
    41.        
    42.         m_View.View.TriggerEvent("SendArray", arg1, arg2, arg3); // You can pass up to 8 args
    43.     }
    44. }
    45.  
    Code (csharp):
    1.  
    2. <html>
    3. <body>
    4. <script type="text/javascript" src="javascript/jquery-1.7.2.min.js"></script>
    5. <script type="text/javascript" src="javascript/coherent.js"></script>
    6.  
    7. <script type="text/javascript">
    8.  
    9. engine.on('SendArray', function (array, ilist, idictionary) {
    10.     var text = "Array contents: ";
    11.     for (var i = 0; i < array.length; ++i) {
    12.         text += array[i] + ' ';
    13.     }
    14.     $('#array_contents').text(text);
    15.    
    16.     text = "IList contents: ";
    17.     for (var i = 0; i < ilist.length; ++i) {
    18.         text += ilist[i] + ' ';
    19.     }
    20.     $('#ilist_contents').text(text);
    21.    
    22.     text = "IDictionary contents: ";
    23.     text += idictionary['1'] + ' ';
    24.     text += idictionary['string key'] + ' ';
    25.     $('#idictionary_contents').text(text);
    26. });
    27.    
    28. </script>
    29.  
    30. <div id="array_contents"></div><br/>
    31. <div id="ilist_contents"></div><br/>
    32. <div id="idictionary_contents"></div><br/>
    33.  
    34. </body>
    35. </html>
    36.  
    If you're unsure what type of object is passed to JS, you can always use the Debugger to set a breakpoint in the JS handler and inspect the arguments.
     
  36. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Awesome, thank you very much. Everything is working perfectly fine now!
     
  37. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Is there a variable I can check to see that a view is ready for binding? The below works, but only for the first frame. If I call it again after the first frame it never seams to fire the function.

    Code (csharp):
    1.  
    2. view.Listener.ReadyForBindings += HandleReadyForBindings;
    3.  
    Is there a function or variable I can just access? For example view.isReady(), etc..
     
  38. DimitarT

    DimitarT

    Joined:
    Apr 8, 2013
    Posts:
    99
    Your handler is called only the first frame, because ReadyForBindings is fired only once per loaded view. It signalizes that the view is ready to accept TriggerEvent calls and C# handlers can be registered. The opposite event BindingsReleased is fired when the page is being unloaded and no more events should be triggered to the view.

    There is no function or a property that can be used to query whether the view is accepting events, but you can implement it by wrapping the Coherent.UI.View instance in your own class that has a boolean property or by modifying a static boolean in your handlers for ReadyForBindings and BindingsReleased.
     
  39. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Ok, thank you; I just created a handled it through a public variable and all working fine now and adjust it as needed if the view changes.

    Edit: Could an example be provided for the BindingsReleased usage please? I am not finding anything in regards to its usage in the Unity PDF documentation.

    Edit: Nevermind, looks like it's exactly the same as ReadyForBindings except with BindingsReleased . Same variables and everything.
     
    Last edited: Apr 8, 2013
  40. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    How would you go about having an in-game mini-map for a 2D game. Basically can you project what a Unity camera sees onto a CoherentUI HTML element somehow? Basically I want to see a minimized 2D small view of my entire level or a good bit of it at least as a UI element like a mini-map. Any suggestions?
     
  41. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    We have planned to make a complete feature for easily binding media content such as images from your engine so Coherent UI can use them, but until then you have to use other methods.

    The most straight-forward method would be converting the texture to png/jpg, encoding the bytes in base64 and then constructing a data URL out of this (https://en.wikipedia.org/wiki/Data_URI_scheme). This, of course, would incur a performance penalty if done each frame - you can try using a coroutine for the png encoding if you're comfortable with a few frames delay. Ideally in your case, you can send the image only once and then draw a marker for each player or object in JS. Here's some example code for sending the image:

    C#:
    Code (csharp):
    1. public void ShowTexture(Texture2D tex)
    2. {
    3.     var png = tex.EncodetoPNG();
    4.     var pngInB64 = System.Convert.ToBase64String(png);
    5.     var dataURL = "data:image/png;base64," + pngInB64;
    6.  
    7.     View.TriggerEvent('SetImage', dataURL);
    8. }
    JavaScript:
    Code (csharp):
    1. function SetImage(data) {
    2.     var image = document.getElementById('theMinimap');
    3.     image.src = data;
    4. }
    5.  
    6. engine.on('Ready', function () {
    7.     engine.on('SetImage', SetImage);
    8. });
    Another way would be using a canvas, which would allow you to omit the png/jpg encoding but would require some more code.
     
  42. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I'm wanting more along the lines of having a second camera be shown in a UI element like you can do with NGUI. Any idea how to go about doing that or is it not possible as of yet (hopefully can be in the future)?
     
  43. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    At the moment Coherent UI does not have such access to Unity resources. You have to copy them from the Unity universe to the HTML universe using TriggerEvent. If you want to have picture in picture with dynamic content, you'll have to copy the image data every frame. You can use my previous example to do so, just executing it constantly. Using a canvas element in the HTML should allow you to send the image without encoding it, since it allows direct pixel manipulation, but sending this much data every frame will affect performance.

    You can try to lower the load by sending reasonably low-res images or, if you only need the HTML/JS for something simple such as a transform, stay with Unity (GUI) textures to render the second camera for the time being since that wouldn't require copying the data.
     
  44. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    Ok, will look into trying that. It doesn't need to be high resolution as it's just a mini-map showing a overall view of the 2.5D, thank you!
     
  45. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    When I build my project the UI is completely left exposed as it's outside of the Asset folder (has to be or Unity freaks out from JS files). Any suggestions to hide the UI resources so they can't be tampered with?
     
  46. nikxio

    nikxio

    Joined:
    Oct 30, 2012
    Posts:
    69
    One easy way to do that is to use a custom file handler. You can zip password protect your resources and the custom file handler will read them using the password. Of course, this being C# and all, the dll can be decompiled and the password is likely to be there as clear text, but it requires some effort to be able to mess with the resources. We're currently experimenting with some schemes that would allow you to sign your resources with almost no overhead which will provide the needed security.

    For the moment, we've added a new sample in the development version that reads resources from an archive and changed the API so you can add your own handler easily. We used a tar archive since we needed a very simple third party reader and inherent zip support for .NET was added in 4.0 while we're targeting 3.5. You can, of course, use any archive format you see fit.

    Here's the code for the custom file handler from the dev branch (using tar-cs for reading the tar):
    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.IO;
    4. using System.Runtime.InteropServices;
    5. using tar_cs;
    6.  
    7. public class CustomFileHandlerScript : MonoBehaviour
    8. {
    9.  
    10.     class CustomFileHandler : Coherent.UI.FileHandler
    11.     {
    12.         private string m_ResourcesHost;
    13.         private string m_ArchiveName;
    14.  
    15.         public CustomFileHandler(string resourcesHost, string archiveName)
    16.         {
    17.             m_ResourcesHost = resourcesHost.ToLower();
    18.             m_ArchiveName = archiveName;
    19.         }
    20.  
    21.         private string GetArchiveFolder()
    22.         {
    23. #if UNITY_EDITOR
    24.             // Read resources from the project folder
    25.             var uiResources = PlayerPrefs.GetString("CoherentUIResources");
    26.             if (uiResources == string.Empty)
    27.             {
    28.                 Debug.LogError("Missing path for Coherent UI resources. Please select path to your resources via Edit -> Project Settings -> Coherent UI -> Select UI Folder");
    29.             }
    30.             return uiResources;
    31. #else
    32.             // Read resources from the <executable>_Data folder
    33.             return Path.Combine(Application.dataPath, m_ResourcesHost);
    34. #endif
    35.         }
    36.  
    37.         private bool GetFilepath(string inUrl, out string cleanUrl)
    38.         {
    39.             var asUri = new Uri(inUrl);
    40.             cleanUrl = asUri.GetComponents(UriComponents.Path, UriFormat.Unescaped);
    41.  
    42.             bool isFile = (asUri.Scheme == "file" || asUri.Host.ToLower() != m_ResourcesHost);
    43.             return isFile;
    44.         }
    45.  
    46.         public void ReadFileFromFilesystem(string cleanUrl, Coherent.UI.ResourceResponse response)
    47.         {
    48.             if (!File.Exists(cleanUrl))
    49.             {
    50.                 response.SignalFailure();
    51.                 return;
    52.             }
    53.  
    54.             byte[] bytes = File.ReadAllBytes(cleanUrl);
    55.  
    56.             RespondWithBytes(bytes, response);
    57.         }
    58.  
    59.         public void RespondWithBytes(byte[] bytes, Coherent.UI.ResourceResponse response)
    60.         {
    61.             IntPtr buffer = response.GetBuffer((uint)bytes.Length);
    62.             if (buffer == IntPtr.Zero)
    63.             {
    64.                 response.SignalFailure();
    65.                 return;
    66.             }
    67.  
    68.             Marshal.Copy(bytes, 0, buffer, bytes.Length);
    69.  
    70.             response.SignalSuccess();
    71.         }
    72.  
    73.         public void ReadTarFile(string cleanUrl, Coherent.UI.ResourceResponse response)
    74.         {
    75.             string archivePath = Path.Combine(GetArchiveFolder(), m_ArchiveName);
    76.             using (FileStream unarchFile = File.OpenRead(archivePath))
    77.             {
    78.                 TarReader reader = new TarReader(unarchFile);
    79.                 while (reader.MoveNext(true))
    80.                 {
    81.                     var path = reader.FileInfo.FileName;
    82.  
    83.                     if (path == cleanUrl)
    84.                     {
    85.                         using (MemoryStream ms = new MemoryStream((int)reader.FileInfo.SizeInBytes))
    86.                         {
    87.                             reader.Read(ms);
    88.                             byte[] buffer = ms.GetBuffer();
    89.                             RespondWithBytes(buffer, response);
    90.                         }
    91.  
    92.                         break;
    93.                     }
    94.                 }
    95.             }
    96.         }
    97.  
    98.         public override void ReadFile(string url, Coherent.UI.ResourceResponse response)
    99.         {
    100.             string cleanUrl = string.Empty;
    101.             bool isFile = GetFilepath(url, out cleanUrl);
    102.  
    103.             if (isFile)
    104.             {
    105.                 ReadFileFromFilesystem(cleanUrl, response);
    106.             }
    107.             else
    108.             {
    109.                 ReadTarFile(cleanUrl, response);
    110.             }
    111.         }
    112.  
    113.         public void WriteFileToFilesystem(string cleanUrl, Coherent.UI.ResourceData resource)
    114.         {
    115.             IntPtr buffer = resource.GetBuffer();
    116.             if (buffer == IntPtr.Zero)
    117.             {
    118.                 resource.SignalFailure();
    119.                 return;
    120.             }
    121.  
    122.             byte[] bytes = new byte[resource.GetSize()];
    123.             Marshal.Copy(buffer, bytes, 0, bytes.Length);
    124.  
    125.             try
    126.             {
    127.                 File.WriteAllBytes(cleanUrl, bytes);
    128.             }
    129.             catch (IOException ex)
    130.             {
    131.                 Console.Error.WriteLine(ex.Message);
    132.                 resource.SignalFailure();
    133.                 return;
    134.             }
    135.  
    136.             resource.SignalSuccess();
    137.         }
    138.  
    139.         public override void WriteFile(string url, Coherent.UI.ResourceData resource)
    140.         {
    141.             string cleanUrl = string.Empty;
    142.             bool isFile = GetFilepath(url, out cleanUrl);
    143.             if (!isFile)
    144.             {
    145.                 Debug.LogWarning("In this sample the archive is read only!");
    146.                 resource.SignalFailure();
    147.                 return;
    148.             }
    149.  
    150.             WriteFileToFilesystem(cleanUrl, resource);
    151.         }
    152.     }
    153.  
    154.     //----------------------------------------------------------------------------------
    155.  
    156.     void Awake()
    157.     {
    158.         CoherentUISystem.FileHandlerFactoryFunc = () => { return new CustomFileHandler("UIResources", "ArchiveResource.tar"); };
    159.     }
    160. }
    The call in the Awake() method uses the new API functionality. For the currently released version of Coherent UI (1.1.5) the easiest way to change the file handler is to change the implementation of the UnityFileHandler class, located in Assets / Standard Assets / Scripts / CoherentUI / Detail / FileHandler.cs.
     
  47. DimitarT

    DimitarT

    Joined:
    Apr 8, 2013
    Posts:
    99
    The best way to hide the UI implementation is to provide a custom FileHandler to Coherent UI. This way you can read the files from a package, encrypted zip file.
    There is a sample how to provide and implement custom FileHandler in our new release 1.2.0.0, you can get it on our website http://coherent-labs.com/UIDownloadUnity3D/.
     
  48. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I've just noticed the two different pricing pages. So for Unity really it's $350 for standard? I was under the impression it was just $99. Ouch, much higher then anticipated. This is for 1 seat unlimited titles though right with unlimited updates? Will the $99 indie work with Unity or do you not get the Unity project?
     
    Last edited: Apr 15, 2013
  49. MartinZhel

    MartinZhel

    Joined:
    Nov 25, 2012
    Posts:
    18
    The price for the Unity standard is #350 for 1 seat with unlimited titles and all the newest updates. $99 is the price for the indie version of Coherent UI native which doesn't work with Unity.

     
  50. Krileon

    Krileon

    Joined:
    Oct 30, 2012
    Posts:
    642
    I see, ok, thank you; will just need to hold off on purchasing till later than expected then.