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

PowerUI - Powerful HTML/CSS UI Framework

Discussion in 'Assets and Asset Store' started by KulestarUK, Aug 16, 2013.

  1. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269

    Please note: 1.9 is not available on the Asset Store - to get it, grab the version on the store then enter your Invoice number on the My PowerUI page.

    PowerUI - Unity's most powerful UI framework
    PowerUI is a framework for Unity which lets you make interfaces or complete 2D games using standard HTML and CSS. After years of development and thousands of hours of developer time, PowerUI is absolutely jam packed with features.


    The King of Performance
    PowerUI is fast, and it's always getting faster. We spent 8 months eliminating Unity's text API because it wasn't meeting our performance targets. We are extremely passionate about performance, plus we target the web, so PowerUI was built from scratch by performance experts. We have strict no bloat rules too - the core of PowerUI compiles to less than 500kb and can be stripped down well beyond that.


    Every Unity Platform [WebGL unofficial currently]
    PowerUI has no external dependencies - it's all managed C# provided as source code. This means it often "just works" on Unity platforms, like WebGL, before we have even actively supported them. PowerUI works for both Unity Indie and Unity Pro users too. Our main target is Unities most restrictive platform, the web, with the mindset that if it can work there, it can work everywhere. We spent time back-porting PowerUI so it's known to work in even the oldest Editor versions too.

    Supreme Support
    We're proud to provide unbeaten support, night and day, every day, all year round. If you ever have any problems, we're always here for you and always will be. With a range of more than 20 example scenes, well documented source and clear getting started guides, you'll find it fun to be learning about what PowerUI can really do, with us as a friendly safety net if you ever get stuck. Plus, PowerUI is based on standard HTML and CSS so you probably even already know how to use it.


    Goldmine of Hidden Gems
    PowerUI is known for it's myriad of features and it's jam packed with epic things you'd never expect in a UI framework too. Go for a stroll through the source tree, or even through the example scenes, and you'll find things that haven't been mentioned at all. We simply don't have the space!

    Examples and a sandbox (Old! This will be updated soon): Click here.

    Asset store: Click here.

    PowerUI website: Click here.

    Features
    - Runs on HTML/CSS. Includes some custom CSS properties (e.g. rotate:, scale: ) to make your UI great in Unity.
    - Nitro included! This is a scripting language that looks like javascript and can be used to bring your UI alive in intuitive ways. Nitro can be used for player written scripts too (but not on iOS due to Apple's TOS).
    - It's completely dynamic. Stream entire UI's if you want. Even let players make them too.
    - Provided as fully documented source code.
    - Almost always one drawcall. PowerUI has been built to perform.
    - Live chat support is available (directly to me, the developer). Ask whatever you want and I'll be more than happy to help!
    - Unity's most powerful localisation. We care a lot about making games accessible to everybody, no matter what language they speak. PowerUI contains lots of features for making this a breeze.
    - In game world UI support too.
    - Style animations, e.g. document.getElementById("elem").animate("color:#00ff00",2f);
    - Graphical animations (GIF like) in a compact custom format built for Unity.


    If you have any questions, please ask here, try out our live chat or contact us - We're always happy to help out!
     
    Last edited: Feb 15, 2015
    twobob likes this.
  2. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    - Post reserved for updates -
     
  3. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    We've decided to slash the price from $75 to $40!

    Stay tuned on the asset store as it might take a few days for this update to take affect. If you'd like it right now at the reduced price, please don't hesitate to contact us over on the PowerUI site :)
     
  4. kaz2057

    kaz2057

    Joined:
    Jan 18, 2011
    Posts:
    326
    On asset store description I read it work just on web player... It works also on mobile platform?

    Then it is possible open external HTML URL like Google?

    Thanks
     
  5. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Hey kaz!

    Yes it does also work on mobile platforms :)

    It can also load simple websites but it's not designed to browse the web though due to javascript. As we target the webplayer we can't simply use a premade javascript engine to run javascript from the web, so have instead built our own. Our engine however runs a custom language called Nitro; that's a language which looks a lot like javascript and has been constructed to be optimal for use in Unity. But as Nitro isn't actually javascript, it can't successfully run javascript code from the web.

    I hope that helps! :)

    All the best,
    Luke Briggs
     
  6. kaz2057

    kaz2057

    Joined:
    Jan 18, 2011
    Posts:
    326
    Very clean explanation :)

    I will buy as soon as possible.

    However javascript would be a good component to add.

    Thanks
     
    Last edited: Sep 2, 2013
  7. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Great, glad I could help! :)

    I'll take a look into potentially porting a full javascript engine or alternatively making Nitro as close as possible to it; we've got plans for a few Nitro features that should make it much closer in the pipeworks at the moment.

    I try to be on live chat as often as possible (most days) over on the powerUI website - if there's anything else I can do please feel free to let me know; I'm more than happy to help with whatever I can. Alternatively drop messages here or send over an email to luke@kulora.com :)

    All the best,
    Luke Briggs
     
    twobob likes this.
  8. eskimojoe

    eskimojoe

    Joined:
    Jun 4, 2012
    Posts:
    1,440
    Does it support HTML table layout?
     
  9. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Hi eskimojoe!

    Yes it does however it currently requires defining the width of every cell; Due to popular demand this is actively being worked on and will be no longer the case in version 1.4 which is getting released to the store sometime within the next 24 hours :)

    All the best,
    Luke Briggs
     
  10. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    I tried this in the sandbox but it doesn't show anything:
    <font color="#ff0000">Hello</font>
    <font size="3" color="red">Hello 2</font>

    Any chance of supporting this?
     
  11. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Hey Elecman!

    It can currently be done with a span, e.g. <span style="color:#ff0000;font-size:3px;">Hello</span>, however adding the font tag too should be pretty straightforward so I'll stick that in there :)
     
  12. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks.

    Also,
    If I have an mp3 file which I link to in the HTML code, can I automatically display a little play/pause button where it shows up?
     
  13. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Yep that would certainly be possible - the html5 <audio> tag itself isn't supported (anti-bloat thing; PowerUI is more designed for visuals), so that could be implemented with any form of html button (a,input, clickable element/image etc) which points at some C#/Nitro/Unity JS to play the audio. The html element could also store the url, like this:

    <div onmousedown="playAudio" src="path/in/Resources/myAudioFile">Click me!</div>

    .. The playAudio function (Nitro):

    <script type='text/nitro'>
    Code (csharp):
    1.  
    2. function playAudio(e:UIEvent){
    3.  
    4.    var audioSrc:string = e.target["src"];
    5.  
    6.    var audioFile:AudioClip = (Resources.Load(audioSrc)) : AudioClip;
    7.  
    8.    //Attach audioFile to an AudioSource. You'll probably want one shared AudioSource
    9.   // so there's only one of these playing at once.
    10. }
    11.  
    </script>

    Alternatively, PowerUI supports custom tags so adding the audio tag to run something like the above code when clicked would be quite simple.

    I hope that helps! I'm currently on live chat if there's anything else too :)
     
    Last edited: Jan 4, 2014
  14. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks! That will do the trick.
     
  15. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Can you improve the text quality? It doesn't look pixel perfect at times.
    $text result.png

    Edit:
    Another thing I noticed is that this code produces different results in my HTML editor and PowerUI:
    Code (csharp):
    1.  
    2. First line.<div><br /></div><div>Another line after one blank line.</div>  
    3.  
    HTML Editor:
    $edit program.jpg

    PowerUI result:
    $PowerUI test.jpg

    How can I fix that?

    Thanks for adding the color tags by the way. Works perfectly.
     
    Last edited: Jan 6, 2014
  16. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Heya!

    The text quality depends on which filter mode its using, which is FilterMode.Pixel by default (which if you've ever used before is a little hit and miss regarding its results). Try out e.g.

    Code (csharp):
    1.  
    2. UI.TextFilterMode=FilterMode.Bilinear;
    3.  
    And see how that goes :)

    As for the <br> thing, PowerUI expects a block element before the br if it is going to generate a gap (br's themselves are block elements too). Placing the <br> after your div should generate the same thing in both the html editor and PowerUI (or alternatively just a double br):

    Either:
    Code (csharp):
    1.  
    2. First line.<div></div><br /><div>Another line after one blank line.</div>
    3.  
    Or:
    Code (csharp):
    1.  
    2. First line.<br /><br /><div>Another line after one blank line.</div>
    3.  
    Should look the same in both your editor and PowerUI :)
     
  17. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    The Bilinear filter looks much better :)

    The line break works great too now. Thanks!

    One other thing. My app is mostly 2D GUI based. How can I stop Unity from rendering when nothing on the screen has changed? I want to save some battery. Lowering the frame rate is not really an option because the user input response suffers from that.
     
  18. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    No problem! :)

    PowerUI internally buffers and caches at multiple levels and will only redraw when either your CSS or html actually changes. If it's idling, it won't be doing anything at all other than Unity just drawing the mesh on the screen (just like any other 3D mesh) :)

    General performance notes

    If you'd like to make it as performant as possible, the UI rate defines the fastest rate that it will redraw when redraws are required, which is often actually quite a rare thing. In web browsers, these redraw events are called reflow, and standard reflow optimizing for browsers applies to PowerUI too. Something like this kind of thing might be useful to you for just that: https://developers.google.com/speed/articles/reflow.

    Following similar lines, pulling properties such as contentHeight from an element will force a reflow to happen if the element is known to require one. Accessing the computed style (element.style.Computed.ContentHeight) does not force reflows, so if you know e.g. the height didn't change then using computed styles directly can be a little quicker, but this only really applies if you're doing e.g. a style change and then grabbing the contentHeight rapidly in a loop.

    Some things such as changing the color, color-overlay, opacity, scale, translate and rotate etc CSS properties are all post processes and cause no reflow at all in PowerUI, so animating those are brilliant for performance.

    As for memory considerations if you're targeting really low memory devices, PowerUI has the ability to turn off image atlasing (happens automatically). This exchanges GPU/rendering time for lower memory and CPU use - check out UI.RenderMode if you're interested in that.

    In general though, we have been pretty brutal with PowerUI and built it from the ground up with speed in mind, so you can chuck most things at it and it will be fine anyway. I hope that makes sense! :)
     
    Last edited: Jan 7, 2014
  19. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    When Play mode is active, my CPU uses about 6% for Unity, and 0% when not in Play mode. This is when everything is static. So presumably the CPU usage is caused by Unity drawing the mesh on screen. Is there no other trick to force Unity not to draw anything when it is not required? I know that Camera.Render only works with RenderTextures... Perhaps there is another way?

    Edit:
    Also, does PowerUI have an inertial scrolling feature (not just by using a CSS scrollbar) similar to this?
    http://mootools.net/demos/?demo=Drag.Scroll

    Edit 2:
    I am trying to get the click-to-play-mp3 feature to work. I tried this:
    Code (csharp):
    1.  
    2. this is an mp3<div onmousedown="playAudio" src="test.mp3"><img src="play.jpg" /></div>
    3.  
    4. <script type='text/nitro'>
    5. function playAudio(e:UIEvent){
    6.  
    7.    var audioSrc:string = e.target["test.mp3"];
    8.    var audioFile:AudioClip = (Resources.Load(audioSrc)) : AudioClip;
    9. }
    10. </script>
    11.  
    But I get this error:

    Maybe adding a custom tag is a better idea because I have many audio file references and modifying them all by hand and adding a separate function for each of them is too much work. My crappy HTML editor (actually, its a flashcard editor and I don't have much choice) gives this tag for an mp3 file:
    So if I can get that to work without adding extra functions, that would be great. If I have to change the format of the tag, that would be fine, as that can be automated.

    I am not sure how to add a custom tag. I must say that I am not a fan of automated API documentation, but that is a personal preference ;-)
     
    Last edited: Jan 7, 2014
  20. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Heya!

    As for the first question, you can restrict the Unity framerate (Application.targetFrameRate) which allows Unity to leave the screen alone for longer periods of time - I believe that doesn't work in the editor though, so you could try just having a play around with it and see how it fairs :)

    The scrolling thing is something quite a few people have actually implemented themselves (someone also sent over a scene containing an implementation and said it could be used in an example scene) - from everything I've seen, it's quite simple to implement directly with element.scrollTo and straight unity input/ PowerUI input - if you'd like some more pointers just let me know :)

    As for the error, I can first see a small problem on line 6 of the code above:

    Code (csharp):
    1.  
    2. var audioSrc:string = e.target["test.mp3"];
    3.  
    Should be:

    Code (csharp):
    1.  
    2. var audioSrc:string = e.target["src"];
    3.  
    The thing in the brackets is the name of the attribute you'd like to pull from the element :) E.g. <span bananas="fruitey!"> can be used as e.target["bananas"] - the value obtained being "fruitey!". The function itself is re-useable because of this.

    Also the src="test.mp3" in your element should have no file type (that's a slightly wierd Unity thing!) - e.g. src="test". Alternatively, strip the file type from within the function (this is what PowerUI does with images).

    As for the error, sorry! I didn't test out the code, but you'll want to use the overload/ alternative:

    Code (csharp):
    1.  
    2. Resources.Load(audioSrc,AudioClip);
    3.  

    Making a custom tag - starting from an existing one

    If you'd still like to add a custom tag, then the best place to start is by grabbing a copy of an existing one and modifying it to suit your needs - for this case I'd imagine the a tag would be a great place to go from as it has attributes and also a custom click method. You can find it at Your/Path/To/PowerUI/Source/Engine/TagHandlers/a.cs

    Copy and paste that to somewhere outside of PowerUI (just incase you update, you won't want to loose your tags!), and rename it to e.g. sound.cs. For now I'll assume <sound src="test.mp3">. Pop it open and change:

    - All cases of "ClickLinkTag" for "SoundTag".
    - The GetTags() function should return "sound" rather than "a". You could actually have e.g. "sound","audio" here if you'd like to cover multiple tags too.

    - At this point, you've got a valid new tag! It's missing style though, so you could either open up Path/To/PowerUI/Resources/style.html, and copy+paste the 'a' selector (search for a{ ), renaming it to sound, or paste it into /Your/Custom/Path/Resources/customStyle.html if you'd like to get it out of the PowerUI folders.

    So at this point you'll have a tag that also has some default styling, but it's now acting like a link, so time to fix that!

    - Change all mentions of Href and "href" to Src and "src" (or just use <sound href="test.mp3">).

    - Look for the "Time to go to our Href" comment (line 56). At this point, you'd load the sound from Src and play it using e.g. Resources.Load(Src). Hopefully, assuming everything went to plan and your computer and/or desk didn't spontaneously leap out of a window, you should be good to go! :)


    As for the automated documentation hehe; PowerUI consists of over a megabyte of code spread out over many hundreds of methods, so grabbing all of that method documentation and running it through manually would have been quite the task! :p
     
  21. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    I've just made the above two bits of information into getting started guides; We've had many questions regarding the performance of PowerUI and a few people wanting to make custom tags, so I thought it would be wise to drop them into guides to help you guys out some more :)

    Guide 10 - Custom tags
    Guide 11 - Performance
     
  22. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks for the additional guides.

    I have modified the nitro script like this:
    Code (csharp):
    1.  
    2. this is an mp3<div onmousedown="playAudio" src="test.mp3"><img src="play.jpg" /></div>
    3.  
    4. <script type='text/nitro'>
    5. function playAudio(e:UIEvent){
    6.  
    7.    var audioSrc:string = e.target["src"];
    8.    var audioFile:AudioClip = Resources.Load(audioSrc,AudioClip);
    9. }
    10. </script>
    11.  
    But it now gives this error:
    Using your custom tags guide, I got the tag to work but playing the audio still doesn't work. Just calling this:
    Code (csharp):
    1. Resources.Load(Src);
    Does not play any audio. Working with AudioClips does not work either because the PowerUI namespace is not compatible with MonoBehaviour stuff so it doesn't know what a gameObject and an AudioSource component is is, which is required to play audio. If you have some more ideas on how to get this to work, that would be great.

    Also, if you can pass me that scroll example, that would be fantastic.
     
    Last edited: Jan 8, 2014
  23. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    You'll still need to cast the Resources.Load into an AudioClip - sorry; I should have made that clearer :)

    Code (csharp):
    1.  
    2. var audioFile:AudioClip = ( Resources.Load(audioSrc,AudioClip) ) : AudioClip;
    3.  
    As for grabbing an AudioSource, you can use GameObject.Find to grab hold of an object with a source on it. For something like this though, I'd reccommend sticking a source on your main camera (so the volume doesn't vary with distance, which I'd imagine is what you'd want). At which point, just this works:

    Code (csharp):
    1.  
    2. Camera.main.audio.Play(audioFile);
    3.  
    So, with that, the full html should look something like this:


    this is an mp3<div onmousedown="playAudio" src="test"><img src="play.jpg" /></div> Note that src doesn't have a filetype - this is required by Resources.Load (as it might actually end up not being an mp3 in the built game; this is a Unity thing)

    <script type='text/nitro'>
    Code (csharp):
    1.  
    2.     function playAudio(e:UIEvent){
    3.      
    4.        var audioSrc:string = e.target["src"];
    5.        var audioFile:AudioClip = ( Resources.Load(audioSrc,AudioClip) ):AudioClip;
    6.        Camera.main.audio.Play(audioFile);
    7.     }
    8.  
    </script>

    Edit: If you're also trying a C# version, you'll need to stick using UnityEngine; right up at the top of the C# tag source file; that will prevent any errors about missing GameObject/ AudioSource etc :)

    As for the example, I'll see what can be done :) I'll be heading off shortly (as it's just gone 6:30am here!) but I've made a note of that and will set it up for you asap. If you'd like I can email it over to you; if you send me some mail first (luke@kulora.com) then I can reply straight to that so you don't have to stick your mail address on here :)
     
    Last edited: Jan 8, 2014
  24. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    With the new playAudio function I get this error when I click on the link. I removed the .mp3 extension as well, and added an AudioSource component to the camera:
    However, I got it to work by using this in OnClick():
    Code (csharp):
    1.  
    2. Camera.main.audio.clip = Resources.Load(Src) as AudioClip;
    3. Camera.main.audio.Play();
    4.  
    You rock! Thanks so much for your help.

    So for reference, if any one else comes across this thread.

    -Add an AudioSource component to the main camera.

    -Make a file called sounds.cs and place it in your own scripts folder:
    Code (csharp):
    1.  
    2. using System;
    3. using PowerUI.Css;
    4. using UnityEngine;
    5. using UnityEngine;
    6.  
    7. namespace PowerUI{
    8.    
    9.     public class SoundTag:HtmlTagHandler{
    10.  
    11.         public string Src;
    12.        
    13.         public override string[] GetTags(){
    14.             return new string[]{"sound"};
    15.         }
    16.        
    17.         public override Wrench.TagHandler GetInstance(){
    18.             return new SoundTag();
    19.         }
    20.        
    21.         public override bool OnAttributeChange(string property){
    22.             if(base.OnAttributeChange(property)){
    23.                 return true;
    24.             }
    25.             if(property=="src"){
    26.                 Src=Element["src"];
    27.                 return true;
    28.             }
    29.             return false;
    30.         }
    31.        
    32.         public override bool OnClick(UIEvent clickEvent){
    33.  
    34.             base.OnClick(clickEvent);
    35.  
    36.             if(!clickEvent.heldDown){
    37.  
    38.                 if(!string.IsNullOrEmpty(Src)){
    39.  
    40.                     Camera.main.audio.clip = Resources.Load(Src) as AudioClip;
    41.                     Camera.main.audio.Play();
    42.                 }
    43.             }
    44.             return true;
    45.         }
    46.     }
    47. }
    48.  
    -Make a file called customStyle.html and place it in the Resources folder:
    -Take an mp3 file called test.mp3 and a jpg file called play.jpg and place them in the Resources folder. Make sure the jpg has read/write enabled.

    -Put this html code in a text file and attach it to the PowerUIManager script (or your own script if you have modified it)
     
    Last edited: Jan 8, 2014
  25. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Great! No problemo, I'm glad you got it working - thanks also for posting your solution as that will certainly be appreciated by others! :)

    As for that InvalidCastException, my best guess as to what was happening there is maybe there was multiple files in resources with the same name but different filetypes (e.g. test.html and test.mp3) - due to how Unities Resources.Load function works, it might have been returning the wrong one. Let us know if there's ever anything else! :)
     
  26. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Can't PowerUI be used as an XML parser as well?
     
  27. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Heya!

    Yep it sure can - you'll want to look in the Wrench framework for that (http://powerui.kulestar.com/powerdocs/namespaceWrench.html) and more specifically at the MLLexer and MLElement classes. Their designed to be very generic so using it requires a little work but it comes at the advantage of it having great performance and flexibility.

    To give you a starting point we've got a minimal simple parser that derives from the same stuff as PowerUI (it works wherever Wrench is which is included with PowerUI) and I've uploaded so you can grab it from here (5.5kb zip) :) Usage is create a new XMLDocument then use Root, ChildNodes, Tag and the tag handlers as needed - there's a small Unity Sample in there too; Attach SampleXML to a gameobject in an empty scene to see some output. Wrench itself and this XML parser aren't limited to Unity; they work in any C# program.

    As an example, if you've got <book> elements, you can setup a book tag handler and deal with them in custom ways directly at the parser level. Just like with PowerUI, it's a great idea to start off from an existing handler for doing that. You don't need a tag handler for every kind of tag you're expecting; this parser assumes the 'node' handler otherwise.

    All the best - let us know if you need any further pointers :)
     
    Last edited: Jan 12, 2014
  28. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks. I will have a play with it :)
     
  29. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Back to normal HTML. Using the Player, if I set some HTML text with this it shows up correctly:
    Code (csharp):
    1. UI.document.body.innerHTML
    But if I then change it again, the style show incorrectly in the Game window. If I then click on the Scene window, then back to the Game window, it does show correctly.
    Any ideas?

    Edit:
    How can I scale and image down automatically so it fits within the frame? I tried modifying the style using
    max-width: 100%;
    or
    width: 100%;
    and things like that, but I couldn't get it to work.
     
    Last edited: Jan 13, 2014
  30. delinx32

    delinx32

    Joined:
    Apr 20, 2012
    Posts:
    417
    What HTML/CSS spec does powerUI use? Do things like border-radius, and box-shadow work?
     
  31. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    We've followed W3C where possible and the browser used for comparison purposes was Firefox :) No border-radius or box-shadow yet unfortunately, however they've been in strong consideration so they're likely to show up in a future update. Border-radius can be simulated with a table as PowerUI can render curves if needed (although it's better to make them in an image editor of your choice for simplicity), and similarly box-shadow can be done with e.g. a div inside another.

    Elecman - sorry for the delay! I didn't receive an update that you'd left a message here; layouts must be running for the html to update - they are also caused when you jump from scene to game view, or when you change the window size, so I'd imagine it may just be that. For automatic scaling, you can use a css background-image and the background-scale attribute, or alternatively, an img tag which sets that for you - they scale by default.
     
  32. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Not sure what you mean with that. I tried calling these functions but that had no effect:

    Code (csharp):
    1.  
    2. UI.RedrawNow();
    3. UI.RequestLayout();
    4. UI.Update();
    5. UI.document.Renderer.Update();
    6. UI.document.Renderer.RequestLayout();
    7. UI.document.Renderer.Layout();
    8.  
    So it is possible to modify an img tag on the fly to dynamically scale an image? the problem with a background image is that the text doesn't wrap around it...
     
    Last edited: Jan 17, 2014
  33. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Sorry hehe, the game must be running and you must be calling UI.Update(); for it to operate correctly, as well as UI.Start(); must have also been called. If you're using the standard "PowerUIManager" component (it's used in just about all of the example scenes) it does this for you. All the above functions are called internally - you don't need to call any explicitly :)

    To dynamically scale an image, for example to fill the whole screen, width and height on an image tag would do the trick. E.g.:

    <img src='path/in/resources/image.png' width='100%' height='100%'>

    Or

    <img src='path/in/resources/image.png' style='width:100%;height:100%;'>

    Both of these will stretch to entirely fill the screen at all times. Placing the image tag inside some other element (e.g. inside a div) would scale it to fit that instead. If you mean setting the width at runtime, you can treat it just like you would with standard Javascript, using the language of your choice (Unity JS, C# or Nitro) to do so. Something like this:

    <img src='..' id='someID' ..>

    Can be accessed with:

    Code (csharp):
    1.  
    2. UI.document.getElementById("someID").style.width="20px";
    3.  
    The above code is valid in Nitro, Unity JS as well as C#, and hopefully is the kind of thing you're after :)
     
  34. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    The style refreshing issue was solved by putting the padding property at the front, so instead of this:
    HTML:
    <div id='scrollingBox' style='background:#fff;border:3px solid #000;width:100%;height:85%;padding:35px;color:#000 000;overflow-y:scroll;overflow-x:hidden;' >
    
    do this:
    HTML:
    <div id='scrollingBox' style='padding:35px;background:#fff;border:3px solid #000;width:100%;height:85%;color:#000000;overflow-y:scroll;overflow-x:hidden;' >
    
    To get an image which shrinks to fit in the form but not stretches larger than its original size, and maintain aspect ratio as well, make a new tag following this guide:
    http://help.kulestar.com/tags-powerui

    Using this as a style:
    HTML:
    img-shrink{
        display:inline-block;
        width:100%;
    }
    
    And this as a custom tag handler:

    Code (csharp):
    1.  
    2.  
    3.  
    4. //--------------------------------------
    5. //               PowerUI
    6. //
    7. //        For documentation or
    8. //    if you have any issues, visit
    9. //        powerUI.kulestar.com
    10. //
    11. //    Copyright © 2013 Kulestar Ltd
    12. //          www.kulestar.com
    13. //--------------------------------------
    14.  
    15. using System;
    16. using PowerUI.Css;
    17. using UnityEngine;
    18.  
    19. namespace PowerUI{
    20.  
    21.     /// <summary>
    22.     /// Handles an image tag. The src attribute is supported.
    23.     /// </summary>
    24.     public class ImgShrinkTag:HtmlTagHandler{
    25.  
    26.         /// <summary>The aspect ratio of this image.</summary>
    27.         public float AspectRatio;
    28.         /// <summary>The image being loaded for this tag.</summary>
    29.         public ImagePackage Image;
    30.  
    31.         public override string[] GetTags(){
    32.             return new string[]{"img-shrink"};
    33.         }
    34.  
    35.         public override Wrench.TagHandler GetInstance(){
    36.             return new ImgShrinkTag();
    37.         }
    38.  
    39.         public override bool SelfClosing(){
    40.             return true;
    41.         }
    42.  
    43.         public override bool OnAttributeChange(string property){
    44.  
    45.             if(base.OnAttributeChange(property)){
    46.                 return true;
    47.             }
    48.  
    49.             if(property=="src"){
    50.  
    51.                 string src=Element["src"];
    52.                 if(src==null){
    53.                     src="";
    54.                 }
    55.  
    56.                 ComputedStyle computed=Element.Style.Computed;
    57.                 computed.ChangeTagProperty("background-image",new Css.Value(src,Css.ValueType.Text));
    58.                 return true;
    59.             }
    60.             return false;
    61.         }
    62.  
    63.         public override void OnLoaded(string type){
    64.  
    65.             ComputedStyle computed=Element.Style.Computed;
    66.  
    67.             if(computed.BGImage==null){
    68.                 return;
    69.             }
    70.  
    71.             Image=computed.BGImage.Image;
    72.  
    73.             if(Image==null){
    74.                 return;
    75.             }
    76.  
    77.             int width=Image.Width();
    78.             int height=Image.Height();
    79.            
    80.             // Get the aspect ratio:
    81.             AspectRatio=(float)Image.Height()/(float)Image.Width();
    82.  
    83.             // Act like we're setting tag properties:
    84.             // This is so that class/ID/Style can override any of them.
    85.             computed.ChangeTagProperty("background-repeat",new Css.Value("no-repeat",Css.ValueType.Text));
    86.             computed.ChangeTagProperty("background-size",new Css.Value(width+"px "+height+"px",Css.ValueType.Point));
    87.             computed.ChangeTagProperty("max-width", new Css.Value(width+"px"));
    88.             computed.ChangeTagProperty("height",new Css.Value(((int)((float)height/ScreenInfo.ResolutionScale))+"px",Css.ValueType.Pixels));
    89.         }
    90.  
    91.        
    92.  
    93.         public override void WidthChanged(){
    94.  
    95.             ComputedStyle computed=Element.Style.Computed;
    96.  
    97.             if(Image==null){
    98.                 return;
    99.             }
    100.  
    101.             // Get the width:
    102.             int width=computed.InnerWidth;
    103.  
    104.             // Figure out the target height:
    105.             int height=(int)(width * AspectRatio);
    106.  
    107.             // Apply the height:
    108.             computed.FixedHeight=true;
    109.             computed.InnerHeight=height;
    110.             computed.SetPixelHeight(true);
    111.  
    112.             // Next up we need to update the Y property of background-size.
    113.             // So, grab it:
    114.             Value value=computed["background-size"];
    115.  
    116.             if(value==null){
    117.                 return;
    118.             }
    119.  
    120.             // Grab the X property (this won't ever be null):
    121.             Value xProperty=value[0];
    122.  
    123.             // And set the PX width:
    124.             xProperty.PX=width;
    125.  
    126.             // Grab the Y property (this won't ever be null):
    127.             Value yProperty=value[1];
    128.  
    129.             // Set the PX height:
    130.             yProperty.PX=height;
    131.         }
    132.     }
    133. }
    134.  
    Then use this in your HTML:
    HTML:
    <div><img-shrink src="myPicture.jpg" /></div>
    
    Credits go to Luke.
     
    Last edited: Jan 31, 2014
  35. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Credits to you for also having a problem worth sharing! Glad you got there in the end; let me know if there's anything else :)
     
  36. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
  37. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Heya!

    The simplest approach would be like a healthbar (and in fact the simple healthbar example might be of use for you). Rather than a red background and a green one, instead use a tiled bunch of empty stars as the background and a tiled bunch of filled stars - essentially all you would need to to is copy and paste the simple healthbar example, and swap out the background's for your filled and empty stars :)

    That of course only covers the graphical side of things, so for the input side it depends what kind of device you're targeting. The simplest approach is click-drag, where the user clicks on the bar and drags the mouse (or their finger across the screen, so this works for both touchscreen and desktops). This would then be really similar to drag-to-scroll, only rather than scrolling, you update the width of the inner texture. The pixel value for that width can be figured out from the UIEvent's mouse coordinates (e.clientX and e.clientY), and also the bars location on the screen (depending on what you scroll, something like e.target.parentNode.style.Computed.OffsetLeft and OffsetTop). Take the OffsetLeft from the clientX, and you'll have the number of pixels that the mouse is away from the start of the bar. At this point you can also figure it out relatively using the length of the bar, so you can then store the value in some input element or something :)

    So in summary you should be able to do a simple mashup of the examples to get what you'd like:
    - Grab a simple healthbar.
    - Update it's graphics and dimensions. Red to empty stars, green to full stars.
    - Make it drag-to-scroll (horizontally).
    - Rather than scrolling, update the width of that inner bar.

    Hopefully that will work out for you!
     
  38. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks. Will play with it :)
     
  39. lmbarns

    lmbarns

    Joined:
    Jul 14, 2011
    Posts:
    1,628
    Love your product. Is there any way to display alpha in the SPA's? Or any progress towards it?

    For the time being I can continue to use the video textures with an alpha matte for my animations and do the rest of the UI with your product.

    Thanks for all the examples, they help a ton. :D
     
  40. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Heya Imbarns!

    Yep it sure is - The SPA format's major aim was to actually hold alpha in there and they can do this in a multitude of ways, with a benefit of them working on mobile as well. If you use images with alpha as your input, then the output SPA will contain alpha too, even if you compress it.

    At their very basics an SPA is a stream of sprites each holding a bunch of your frames, with the structure optimized for the smallest possible file size. Those sprites can be PNG's or JPEGs (+single channel JPEG for alpha) depending on if their compressed or not :)

    I'm glad you like it! :D Please let me know if there's ever anything else - I'm currently on live chat too so please just ask away, even if it's something small.
     
  41. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
  42. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Hi! Instead you'd do element.form.submit(); - let me know how it goes! :)

    Edit: element.form can also be used if you have pretty much any element reference. E.g. if you've got an input element contained within a <form>, you can do thatElement.form.submit() too, like this:


    Code (csharp):
    1.  
    2. <input type='button' onmousedown='submitWithNitro' content='Submit!'>
    3.  
    Code (csharp):
    1.  
    2. function submitWithNitro(e:UIEvent){
    3.    this.form.submit();
    4.   // or e.target.form.submit();
    5. }
    6.  
     
    Last edited: Jan 26, 2014
  43. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Thanks, it works!

    Is it possible to set a radio button via code (not the default checked property, but using a function)?
     
  44. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Great! Yep it sure is - changing the checked property from code is the easiest way of doing it:

    Code (csharp):
    1.  
    2. element["checked"]="1";
    3.  
    4. // Uncheck:
    5.  
    6. element["checked"]=null;
    7.  
    The above works in C#, Nitro and UnityJS. For a radio button, doing so for any of them will auto uncheck any others with the same name. If you'd like an actual function, you can also do:

    Code (csharp):
    1.  
    2.  ((InputTag)(element.Handler)).Select();
    3.  
    4. // Uncheck:
    5.  
    6.  ((InputTag)(element.Handler)).Unselect();
    7.  
     
    Last edited: Jan 26, 2014
  45. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Got it to work!
     
  46. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    Here is the star rating system based on a modified radio button system in case anyone is interested. I call it the Radio Star!

    First modify form.cs like this:

    Code (csharp):
    1.  
    2. //find this line:
    3. if(child.Tag=="input"||child.Tag=="select"||child.Tag=="textarea"){
    4. //change to:
    5. if(child.Tag=="input"||child.Tag=="input-star"||child.Tag=="select"||child.Tag=="textarea"){
    6.  
    7.  
    8. //find this line:
    9. if(element.Tag=="input"){
    10. //Put this below that if statement:
    11. if(element.Tag=="input-star"){
    12.  
    13.     InputStarTag tag=(InputStarTag)(element.Handler);
    14.  
    15.     if(!tag.Checked){
    16.         // Don't overwrite.
    17.         continue;
    18.     }
    19. }
    20.  
    21.  
    22. //find this line:
    23. if(uniqueValues.ContainsKey(name)){
    24. //Change the code below that if statement to this:
    25. if(!(element.Tag=="input-star")){
    26.     string value=element.value;
    27.     if(value==null){
    28.         value="";
    29.     }
    30.     uniqueValues[name]=value;
    31. }
    32. else{
    33.     InputStarTag tag=(InputStarTag)(element.Handler);
    34.     if(!tag.Checked){
    35.         uniqueValues[name]="0";
    36.     }
    37.     else{
    38.         string value=element.value;
    39.         if(value==null){
    40.             value="";
    41.         }
    42.         uniqueValues[name]=value;
    43.     }
    44. }
    45.  
    Use this style:
    HTML:
    text-align:center;
    v-align:middle;
    margin-left:5px;
    margin-right:5px;
    display:inline-block;
    background-image:url(resources://blankstar.png);
    background-size:100%;
    }
    
    Use this custom tag handler:
    Code (csharp):
    1.  
    2. using System;
    3. using PowerUI.Css;
    4. using System.Text;
    5. using UnityEngine;
    6. using System.Collections;
    7. using System.Collections.Generic;
    8.  
    9. namespace PowerUI{
    10.    
    11.     public class InputStarTag:HtmlTagHandler{
    12.  
    13.         public string Value;
    14.         public bool Checked;
    15.        
    16.         public override string[] GetTags(){
    17.  
    18.             return new string[]{"input-star"};
    19.         }
    20.        
    21.         public override Wrench.TagHandler GetInstance(){
    22.  
    23.             return new InputStarTag();
    24.         }
    25.        
    26.         public override bool SelfClosing(){
    27.  
    28.             return true;
    29.         }
    30.  
    31.         public override void OnLoaded(string type){
    32.  
    33.             ComputedStyle computed=Element.Style.Computed;
    34.            
    35.             if(computed.BGImage==null){
    36.                 return;
    37.             }
    38.            
    39.             Image=computed.BGImage.Image;
    40.            
    41.             if(Image==null){
    42.                 return;
    43.             }
    44.            
    45.             float width=(float)Image.Width();
    46.             float height=(float)Image.Height();
    47.            
    48.            
    49.             if(Image.PixelPerfect){
    50.                 width*=ScreenInfo.ResolutionScale;
    51.                 height*=ScreenInfo.ResolutionScale;
    52.             }
    53.            
    54.             // Compute the tag width:
    55.             TagWidth=new Css.Value((int)width+"fpx",Css.ValueType.Pixels);
    56.            
    57.             // Compute the tag height:
    58.             TagHeight=new Css.Value((int)height+"fpx",Css.ValueType.Pixels);
    59.            
    60.             // Act like we're setting tag properties:
    61.             // This is so that class/ID/Style can override any of them.
    62.             computed.ChangeTagProperty("height",TagHeight);
    63.             computed.ChangeTagProperty("width",TagWidth);
    64.         }
    65.        
    66.         public override bool OnAttributeChange(string property){
    67.  
    68.             if(base.OnAttributeChange(property)){
    69.  
    70.                 return true;
    71.             }
    72.            
    73.             if(property=="type"){
    74.  
    75.                 string type=Element["type"];
    76.  
    77.                 if(type==null){
    78.  
    79.                     type="text";
    80.                 }
    81.  
    82.                 // Change the style. This requests a layout internally.
    83.                 Element.Style.Computed.SetSelector(Css.SelectorType.Tag,"input[type=\""+type+"\"]");
    84.  
    85.                 return true;
    86.             }
    87.  
    88.             else if(property=="value"){
    89.  
    90.                 SetValue(Element["value"]);
    91.                 return true;
    92.             }
    93.            
    94.             else if(property=="checked"){
    95.  
    96.                 if(Element["checked"]==null){
    97.  
    98.                     Uncheck();
    99.                 }
    100.                
    101.                 else{
    102.  
    103.                     SelectLogic(false);
    104.                 }
    105.  
    106.                 RequestLayout();
    107.                 return true;
    108.             }
    109.  
    110.             return false;
    111.         }      
    112.  
    113.         public void Uncheck(){
    114.  
    115.             if(!Checked){
    116.                 return;
    117.             }
    118.  
    119.             Checked=false;
    120.             Element.innerHTML="";
    121.         }
    122.  
    123.         public void Check(){
    124.  
    125.             if(Checked){
    126.  
    127.                 return;
    128.             }
    129.  
    130.             Checked=true;
    131.             Element.Run("onchange");
    132.             Element.innerHTML="<img src='star.png' />";
    133.         }
    134.  
    135.         public void SelectLogic(bool mouse){
    136.  
    137.             bool selectedIsLastChecked = false;
    138.             string name=Element["name"];
    139.             Element element;
    140.             bool uncheckAll = false;
    141.  
    142.             if(Element.form!=null){
    143.  
    144.                 //Get all inputs. This includes non radio-star buttons.
    145.                 List<Element> allInputs=Element.form.GetAllInputs();
    146.  
    147.                 //get the id of the selected button
    148.                 int selectedButton = Convert.ToInt32(Element["value"]);
    149.  
    150.                 if((selectedButton == 1)  !mouse){
    151.  
    152.                     if(Element["checked"] != null){
    153.  
    154.                         if(Element["checked"] == "0"){
    155.  
    156.                             uncheckAll = true;
    157.                         }
    158.                     }
    159.                 }
    160.  
    161.                 //Loop through all inputs. This includes non radio-star buttons.
    162.                 for(int i = 0; i < allInputs.Count; i++){
    163.  
    164.                     element = allInputs[i];
    165.                     Element nextElement = null;
    166.  
    167.                     //get the next element, if available
    168.                     if(i+1 < allInputs.Count){
    169.  
    170.                         nextElement = allInputs[i+1];
    171.                     }
    172.  
    173.                     //Is this a radio-star type button? And does this button belong to the same group?
    174.                     if((element["type"]=="radio-star")  (element["name"]==name)){
    175.  
    176.                         //Get another button in the same group. This might be
    177.                         //the same one we clicked on.
    178.                         int otherButton = Convert.ToInt32(element["value"]);
    179.  
    180.                         if(mouse){
    181.  
    182.                             //the selected button is not yet checked
    183.                             if(!Checked){
    184.  
    185.                                 //check all buttons up to the selected one
    186.                                 if(otherButton <= selectedButton){
    187.  
    188.                                     ((InputStarTag)(element.Handler)).Check();
    189.                                 }
    190.                             }
    191.  
    192.                             //the selected button is already checked
    193.                             else{
    194.                                
    195.                                 //uncheck all buttons after the selected one
    196.                                 if(otherButton > selectedButton){
    197.  
    198.                                     ((InputStarTag)(element.Handler)).Uncheck();
    199.                                 }      
    200.  
    201.                                 //uncheck the current selected button
    202.                                 selectedIsLastChecked = IsselectedIsLastChecked(nextElement, name);
    203.                                 if((otherButton == selectedButton)  selectedIsLastChecked){
    204.  
    205.                                     ((InputStarTag)(element.Handler)).Uncheck();
    206.                                 }
    207.                             }
    208.                         }
    209.  
    210.                         else{
    211.  
    212.                             if(uncheckAll){
    213.  
    214.                                 ((InputStarTag)(element.Handler)).Uncheck();
    215.                             }
    216.  
    217.                             else{
    218.  
    219.                                 //check all buttons up to the selected one
    220.                                 if(otherButton <= selectedButton){
    221.  
    222.                                     ((InputStarTag)(element.Handler)).Check();
    223.                                 }
    224.  
    225.                                 else{
    226.  
    227.                                     ((InputStarTag)(element.Handler)).Uncheck();
    228.                                 }
    229.                             }
    230.                         }
    231.                     }
    232.                 }
    233.             }
    234.         }
    235.  
    236.         private bool IsselectedIsLastChecked(Element nextElement, string name){
    237.  
    238.             bool selectedIsLastChecked = false;
    239.             bool nextButtonChecked = false;
    240.  
    241.             //is the next element valid?
    242.             if(nextElement != null){
    243.  
    244.                 if((nextElement["type"]=="radio-star")  (nextElement["name"]==name)){
    245.  
    246.                     nextButtonChecked = ((InputStarTag)(nextElement.Handler)).Checked;
    247.                 }
    248.             }
    249.  
    250.             //is the selected button is the last checked one?
    251.             if(Checked  !nextButtonChecked){
    252.  
    253.                 selectedIsLastChecked = true;
    254.             }
    255.  
    256.             return selectedIsLastChecked;
    257.         }
    258.        
    259.         public override bool OnClick(UIEvent clickEvent){
    260.  
    261.             if(clickEvent.heldDown){
    262.  
    263.                 Element.Focus();               
    264.                 SelectLogic(true);
    265.             }
    266.  
    267.             base.OnClick(clickEvent);
    268.             clickEvent.stopPropagation();
    269.            
    270.             return true;
    271.         }
    272.  
    273.         public void SetValue(string value){
    274.  
    275.             Element["value"]=Value=value;
    276.         }
    277.     }
    278. }
    279.  
    Put these stars in the resources folder:
    $star.png $blankstar.png
    Change the image import settings:
    1. Change the image type to Advanced.
    2. Change "Non Power of 2" to none.
    3. Check the read/write enabled checkbox.
    4. Uncheck generate mipmaps.

    Use this HTML code:
    HTML:
    <form onsubmit='GuiLogic.OnStarSubmit' id='starFormID'>
    <br>
    <input-star type='radio-star' name='groupA' value='1' onmousedown='GuiLogic.OnStarClicked' id='star1' />
    <input-star type='radio-star' name='groupA' value='2' onmousedown='GuiLogic.OnStarClicked' id='star2' />
    <input-star type='radio-star' name='groupA' value='3' onmousedown='GuiLogic.OnStarClicked' id='star3' />
    <input-star type='radio-star' name='groupA' value='4' onmousedown='GuiLogic.OnStarClicked' id='star4' />
    <input-star type='radio-star' name='groupA' value='5' onmousedown='GuiLogic.OnStarClicked' id='star5' />
    </form>
    
    Put these functions into your script:
    Code (csharp):
    1.  
    2. //Select a star from code
    3. private static void SelectStar(int selectedStar){
    4.  
    5.     Element element;
    6.  
    7.     //a star 1-5 is selected
    8.     if(selectedStar != 0){
    9.  
    10.         element = UI.document.getElementById("star" + selectedStar);
    11.  
    12.         if(element != null){
    13.  
    14.             //force attribute change
    15.             element["checked"]="0";
    16.             element["checked"]="1";
    17.         }
    18.     }
    19.  
    20.     //deselect all stars
    21.     else{
    22.  
    23.         element = UI.document.getElementById("star" + 1);
    24.  
    25.         if(element != null){
    26.  
    27.             //force attributeChange
    28.             element["checked"]="1";
    29.             element["checked"]="0";
    30.         }
    31.     }
    32. }
    33.  
    34. //This is a callback when the star form is submitted.
    35. public static void OnStarSubmit(FormData form){
    36.  
    37.     int value = 0;
    38.  
    39.     //get the selected star
    40.     string starString = form["groupA"];
    41.     int selectedStar = Convert.ToInt32(starString);
    42. }
    43.  
    44. //every time a star is selected, the star form is submitted so the star value can be
    45. //read out and saved.
    46. public static void OnStarClicked(UIEvent mouseEvent){
    47.  
    48.     UI.document.getElementById("starFormID").submit();
    49. }
    50.  
    To select star 3 from code, call this:
    Code (csharp):
    1. SelectStar(3);
    To de-select all stars, call:
    Code (csharp):
    1. SelectStar(0);
    Each time a star is selected, the OnStarSubmit() function is called. You can get the currently selected star from the selectedStar variable in that function.
     
    Last edited: Feb 20, 2014
  47. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    Interesting solution - I really like the side effect of how it gets treated like any other input element/ submitted with the form that way; thanks a lot for the share! :D
     
  48. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,369
    I noticed that the camera you create to render the PowerUI stuff is perspective. Shouldn't that be orthographic instead? The text and images seem squashed when scrolled to the bottom. Perhaps that is an effect of the perspective arrangement?
     
  49. KulestarUK

    KulestarUK

    Joined:
    Aug 16, 2013
    Posts:
    269
    It's perspective by default to make things like rotate look correct, and to allow 3D meshes to be easily placed on the UI without looking odd :) The latest version (it's been released to the store but hasn't shown up there yet) has UI.CameraMode which can be set to orthographic if an ortho camera is needed.

    As for the squishing thing, that's an optimisation enabled by default and can be turned off selectively with (css) text-clip:clip (default is text-clip:fast) on e.g. your body tag :)
     
    Last edited: Jan 26, 2014
  50. lmbarns

    lmbarns

    Joined:
    Jul 14, 2011
    Posts:
    1,628

    Hrm...even your sample SPA shows black background and my alpha images show black as well...

    Here's a screenshot:
    $NoAlpha.jpg

    Then looking at the spriteframe.cs the condition of hasAlphaFrame is empty...