Search Unity

Resolved How to use background-image: resource("Images/default-image.png") From Editor

Discussion in 'UI Toolkit' started by Gapa, Jun 24, 2021.

  1. Gapa

    Gapa

    Joined:
    Dec 11, 2012
    Posts:
    27
    So as the Title say how do i make it use my Editors resource?


    So if i use the path from Assets it works
    Code (USS):
    1. .MoveUpBtn{
    2.     margin-left:auto;
    3.     background-image: resource("Assets/Icons/arrowUp.png");
    4. }
    5.  
    6. .MoveDownBtn{
    7.     margin-left:auto;
    8.     background-image: resource("Assets/Icons/arrowDown.png");
    9. }



    So now i try to use the Editor one.
    Code (USS):
    1. .MoveUpBtn{
    2.     margin-left:auto;
    3.     background-image: resource("Icons/default-arrowUp.png");
    4.  
    5. }
    6.  
    7. .MoveDownBtn{
    8.     margin-left:auto;
    9.     background-image: resource("Icons/default-arrowDown.png");
    10. }



    if anyone knows what I'm doing wrong I would highly appreciate some help.
     

    Attached Files:

  2. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
  3. Gapa

    Gapa

    Joined:
    Dec 11, 2012
    Posts:
    27
    Thanks for your time and help!
    That work.

    So now I wanna report an error on your own documentation.
    USS Properties types
    https://docs.unity3d.com/Manual/UIE-USS-PropertyTypes.html

    As I was simply following the documentation or I might have misunderstood it.


    For anyone else here is the working resolve.

    Code (USS):
    1. .MoveUpBtn{
    2.     margin-left:auto;
    3.     background-image: resource("Icons/arrowUp");
    4. }
    5.  
    6. .MoveDownBtn{
    7.     margin-left:auto;
    8.     background-image: resource("Icons/arrowDown");
    9. }

     
  4. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Ah! Yes that can be confusing.

    The "Editor Default Resources" refers to the builtin editor resources that are included with Unity, not resources in an "Editor" folder.
     
  5. Gapa

    Gapa

    Joined:
    Dec 11, 2012
    Posts:
    27
    Arrr i see well i was confusing :)
    Anyway Thanks alot for the help.
     
  6. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    If you load images as resources, don't you become subject to texture rules, including power-of-two rules? I've had some problems with other resources (non UI Elements context), where adding them as a resource changed their dimensions when I loaded them. I had to load them as a bytearray and then make a texture based on a bytearray to get a runtime size like the original.

    Right now, I'm loading a 40x30 graphic as a resource, and the image looks OK in the UI only because I'm setting it as a background on a VisualElement that has the same aspect. But when I inspect the texture settings for the image, it has clearly been conformed to 32x32. So the pixels are being tweaked, which I don't love.

    So the question is whether it's dangerous to use resources for non-power-of-two graphics, or whether UI Elements has special knowledge and resolves the texture in its original size.

    Or, is the only way to use images to make them a background to a VisualElement anyway, meaning that you always have to know the image aspect? Because in that case, it's less important if Unity has conformed the image to power-of-twos, since it'll be scaled right back, just losing some pixel resolution possibly.

    Is there a way to use an image in VisualElements where it retains the aspect of the original image? Or is background-image + manual aspect the only game in town?
     
  7. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    You can use the -unity-background-scale-mode if you want to change how the background image will be resized inside an element:

    Code (CSharp):
    1. -unity-background-scale-mode: stretch-to-fill | scale-and-crop | scale-to-fit
    This should work for resources and regular assets.
     
  8. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    Hi,

    But if that image comes from a resource, isn't the aspect lost due to power-of-two harmonization? Here's a graphic that's that's 40 x 30 at source. But in Unity it's 32 x 32 due to being conformed.

    upload_2021-8-14_15-59-42.png

    upload_2021-8-14_15-59-50.png

    Now, even with Non-Power of 2 disabled, it remains at 32 x 32.

    Isn't the aspect lost if the image is loaded as a resource?
     

    Attached Files:

  9. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    This can happen if your texture is imported with the Default texture type. Using a UI texture or a Sprite should allow you to load Non-Power-of-Two textures.
     
  10. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    Hi,

    I'm a bit trying to convince you that UI Elements is casually mixing two hostile concepts, that are a workflow impediment and will result in significant human error.

    When power of two is good: For textures, the aspect doesn't matter. The aspect comes from the UV coordinates on the geometry. No matter how you scale a texture, you'll get the same aspect in the render. You can and should use power-of-two sizes, for GPU performance. This is default in Unity, and should be.

    When power of two is bad: For UI images, the aspect matters a lot. But since it's by default destroyed by the power of two process, you have to go to every single texture, switch it to None and Apply that. This prevents artists from simply dropping graphics into a directory, because they'll actually be changed by Unity. A human must continue to take special steps after each import, or graphics become warped. Mistakes won't be discovered a percentage of the time, and will make it to release.

    The problem is that you can't simply set a default setting. Power is two is practically always good for 3D, and practically always bad for UI elements. Yet, you have to go back and forth every few minutes and never make a mistake.

    What I'm fishing for is two things:

    1.) That the documentation is much clearer on the consequence that all UI images will have their aspect modified unless manual steps are taken on every single image.

    2.) That a way to partition these two workflows is invented. Just spit-balling, there could be designated "UI" folder under Resources that always imports graphics with original aspect.

    I think this should be addressed.
     
  11. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    Thanks for the feedback. This is something we are aware of, but we don't have a solution yet.

    Using a "UI" folder as you suggested is an interesting idea and is something you can implement yourself using an Asset Preprocessor:
    https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPreprocessTexture.html

    You can implement OnPreprocessTexture, look if the asset is in a "UI" folder, and change the texture type of the importer accordingly.
     
  12. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    Hi,

    Thank you, I wasn't aware of this importer hook. I'll implement one right now for specially named folders.

    I do perhaps think this is a fundamental enough dichotomy that Unity should accommodate it, since it will affect all users of UI Elements, and who may not realize that images are brought in as though they were intended for texture mapping. And perhaps the docs should mention this setting.
     
  13. mcoted3d

    mcoted3d

    Unity Technologies

    Joined:
    Feb 3, 2016
    Posts:
    1,003
    I completely agree, and this is something that has caused confusion already. I'll make sure we at least document this properly.

    I don't think we could implement the "UI" folder solution directly inside Unity, as these magic folders tend to cause even more confusion for those who aren't aware they exist. But we'll try to figure something else.

    Thanks again!
     
  14. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    Hi,

    I'm making a general-purpose sample right now, which I'll post here. Perhaps the docs can simply contain a sample like it, and then people can paste the feature into a script. It saves you from the consequences of putting a potentially misfiring feature into Unity proper.
     
    mcoted3d likes this.
  15. perholmes

    perholmes

    Joined:
    Dec 29, 2017
    Posts:
    296
    Here is the script, which works out of the box. Thanks for the tip, I wasn't aware the AssetImporter could be triggered as a hook.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.IO;
    4.  
    5. // Script to ensure that all images intended for use in UIElements are imported without
    6. // Non-Power-Of-Two scaling, so that dimensions and aspect ratio are preserved. This script disables
    7. // scaling when the immediate parent folder begins with "UI " (UI+Space). Prefix can be changed
    8. // below. To install, place script in any folder called "Editor".
    9.  
    10. class UIImageProcessor : AssetPostprocessor
    11. {
    12.     void OnPreprocessTexture()
    13.     {
    14.         string prefix = "UI "; // UI + Space
    15.         var parentFolder = Path.GetFileName(Path.GetDirectoryName(assetPath));
    16.  
    17.         if (parentFolder.StartsWith(prefix)) {
    18.             TextureImporter textureImporter = (TextureImporter)assetImporter;
    19.             textureImporter.npotScale = TextureImporterNPOTScale.None;
    20.         }
    21.     }
    22. }
    23.  
     
    mcoted3d likes this.