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

TextMesh Pro Inline Graphics require sprite sheets?

Discussion in 'UGUI & TextMesh Pro' started by TSabos, Jun 3, 2017.

  1. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    Is there any easy way to add more sprites to your inline graphic options besides keeping a PSD and adding new graphics every time you need a new icon inside your text?

    If I have gold, food, etc.. then I realize I want to add an Iron bar to my inline options it seems like a huge pain.
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The <sprite> tag allows you to access multiple sprite sheets.

    The format is <sprite="Name of Sprite Asset" name="Name of Sprite">.

    The sprite asset must be located in a Resources folder at the location specified in the TMP Settings file.

    Keep in mind that you get (1) draw call per material used in Unity. Therefore, if your sprites are contained in individual sprite sheets, you will get (1) draw calls for each of them.

    In order to minimize draw calls, it is best to combine sprites into a single sprite atlas. That way, a sprite sheet containing 700 sprites will only result in (1) draw call.

    When I added support for Sprite Assets in TextMesh Pro, it was not possible to leverage the 2D Sprite Atlas packing system due to missing API functionality. Since the required functionality is being added, it will be possible in the future to have individual sprites which Unity packs into a single Sprite Sheet at runtime.
     
  3. TSabos

    TSabos

    Joined:
    Mar 8, 2015
    Posts:
    94
    The last paragraph was what I was looking for, thanks ;)

    In the meantime I guess I'll hunt down an atlas packing tool so that it's not some horrible workflow when needing to add or remove images. It seems best practice to use the name of the sprite instead of the position since this could change at any time if you're in major dev mode.
     
  4. shawnblais

    shawnblais

    Joined:
    Oct 11, 2012
    Posts:
    324
    Would be really nice if this could be updated soon. Having to use TextuePacker to place these in a Atlas seems a bit silly at this point, especially now that we have the nice new Sprite Atlas API's.
     
  5. Arthur-LVGameDev

    Arthur-LVGameDev

    Joined:
    Mar 14, 2016
    Posts:
    228
    +1 for native sprite asset support. =D
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Font files that contains sprites have these sprites encoded as png inside the font file. These are typically represented at different sizes like 16 x 16, 32 x 32, 64 x 64, etc. Unlike Glyphs (characters) sprites are bitmap data using RGBA.

    Typically when creating a font atlas texture which contains bitmap or SDF glyphs, this font atlas texture is using 8 bit alpha. In order to try to combine the sprites from the font file into the same atlas as the glyphs, you would have to switch to using an RGBA texture which would be 4 times the size for no real gain and even performance impact on some mobile devices. Furthermore, you would have data contained in a font atlas texture that is potentially encoded differently.

    I'll certainly be looking at simpler ways to generate sprite atlas textures from source font files but these atlas textures should remain separate from the atlas texture that contains glyphs.
     
    Thoma1207 likes this.
  7. bradbecker

    bradbecker

    Joined:
    Dec 26, 2014
    Posts:
    130
    so what's the recommended workflow when you're using Unity's Sprite Atlases?
     
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The Sprite Atlas system isn't supported at this time. This is something I need to look into when I have a chance.

    Until then, you need to manage your own textures and TMP Sprite Assets.
     
  9. TantzyGames

    TantzyGames

    Joined:
    Jul 27, 2016
    Posts:
    51
    I just had to do this. It's not super easy, but it's possible.

    I have a sprite sheet with specific offsets. I wanted to add a sprite to that without having to copy all the settings. This particular sprite sheet isn't very big, but I'm also preparing to add emoji support which will be huge.

    To add the new sprite:
    1. Slice the updated sprite sheet, adding a the new sprite to it.
    2. Create a new TextMesh Pro Sprite Asset from the updated sprite.
    3. Open the original and new sprite assets in a text editor and copy the entry from the new one to the original one (Note: if you create your sprite sheet in a grid, in order from left to right and up to down this will be easiest as it will be the last entry). A single entry looks like this:
    Code (JavaScript):
    1.   - id: 7
    2.     x: 256
    3.     y: 0
    4.     width: 128
    5.     height: 128
    6.     xOffset: 0
    7.     yOffset: 100
    8.     xAdvance: 128
    9.     scale: 1.4
    10.     name: remove
    11.     hashCode: 211706022
    12.     unicode: 0
    13.     pivot: {x: -64, y: 64}
    14.     sprite: {fileID: 21300014, guid: 59ba87cfe9de37845bc63dc8341640a4, type: 3}
    You could automate this if it's something that you need to do regularly.

    If that doesn't work, copy the original entries to the new asset (instead of copying the new entry to the original asset), and replace the original asset with the new one.
     
    Last edited: Aug 24, 2018
  10. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    247
    Hi to all, had a same problem, so I rewrote TMP_SpriteAssetImporter. I've used TexturePackerPro for generating Json-data, and then updated TMP_Asset with this window:
    Code (CSharp):
    1.  
    2. using UnityEngine.TextCore;
    3. #if UNITY_EDITOR
    4. using UnityEngine;
    5. using UnityEditor;
    6. using System.IO;
    7. using System.Collections.Generic;
    8. using TMPro.EditorUtilities;
    9. using TMPro.SpriteAssetUtilities;
    10.  
    11. namespace TMPro
    12. {
    13.     public class TMP_SpriteAssetImporterCustom : EditorWindow
    14.     {
    15.         // Create Sprite Asset Editor Window
    16.         [MenuItem("Window/TextMeshPro/Sprite Importer Custom", false, 2026)]
    17.         public static void ShowFontAtlasCreatorWindow()
    18.         {
    19.             var window = GetWindow<TMP_SpriteAssetImporterCustom>();
    20.             window.titleContent = new GUIContent("Importer Custom");
    21.             window.Focus();
    22.         }
    23.  
    24.         Texture2D m_SpriteAtlas;
    25.         SpriteAssetImportFormats m_SpriteDataFormat = SpriteAssetImportFormats.TexturePacker;
    26.         TextAsset m_JsonFile;
    27.  
    28.         string m_CreationFeedback;
    29.  
    30.         TMP_SpriteAsset m_SpriteAsset;
    31.         List<TMP_Sprite> m_SpriteInfoList = new List<TMP_Sprite>();
    32.  
    33.  
    34.         void OnEnable()
    35.         {
    36.             // Set Editor Window Size
    37.             SetEditorWindowSize();
    38.         }
    39.  
    40.         protected override void OnGUI()
    41.         {
    42.             base.OnGUI();
    43.             DrawEditorPanel();
    44.         }
    45.  
    46.  
    47.         void DrawEditorPanel()
    48.         {
    49.             // label
    50.             GUILayout.Label("Import Settings", EditorStyles.boldLabel);
    51.  
    52.             EditorGUI.BeginChangeCheck();
    53.  
    54.             // Sprite Texture Selection
    55.             m_JsonFile = EditorGUILayout.ObjectField("Sprite Data Source", m_JsonFile, typeof(TextAsset), false) as TextAsset;
    56.  
    57.             m_SpriteDataFormat = (SpriteAssetImportFormats)EditorGUILayout.EnumPopup("Import Format", m_SpriteDataFormat);
    58.                  
    59.             // Sprite Texture Selection
    60.            m_SpriteAtlas = EditorGUILayout.ObjectField("Sprite Texture Atlas", m_SpriteAtlas, typeof(Texture2D), false) as Texture2D;
    61.  
    62.             if (EditorGUI.EndChangeCheck())
    63.             {
    64.                 m_CreationFeedback = string.Empty;
    65.             }
    66.  
    67.             GUILayout.Space(10);
    68.  
    69.            GUI.enabled = m_JsonFile != null && m_SpriteAtlas != null && m_SpriteDataFormat == SpriteAssetImportFormats.TexturePacker;
    70.  
    71.             // Create Sprite Asset
    72.             if (GUILayout.Button("Create Sprite Asset"))
    73.             {
    74.                 m_CreationFeedback = string.Empty;
    75.  
    76.                 // Read json data file
    77.                 if (m_JsonFile != null && m_SpriteDataFormat == SpriteAssetImportFormats.TexturePacker)
    78.                 {
    79.                    TexturePacker.SpriteDataObject sprites = JsonUtility.FromJson<TexturePacker.SpriteDataObject>(m_JsonFile.text);
    80.  
    81.                  
    82.                  
    83.                     if (sprites != null && sprites.frames != null && sprites.frames.Count > 0)
    84.                     {
    85.                         int spriteCount = sprites.frames.Count;
    86.  
    87.                         // Update import results
    88.                         m_CreationFeedback = "<b>Import Results</b>\n--------------------\n";
    89.                        m_CreationFeedback += "<color=#C0ffff><b>" + spriteCount + "</b></color> Sprites were imported from file.";
    90.  
    91.                         // Create sprite info list
    92.                         m_SpriteInfoList = CreateSpriteInfoList(sprites);
    93.                     }
    94.                 }
    95.  
    96.             }
    97.  
    98.             GUI.enabled = true;
    99.  
    100.             // Creation Feedback
    101.             GUILayout.Space(5);
    102.             GUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Height(60));
    103.             {
    104.                 EditorGUILayout.LabelField(m_CreationFeedback, TMP_UIStyleManager.label);
    105.             }
    106.             GUILayout.EndVertical();
    107.  
    108.             GUILayout.Space(5);
    109.            GUI.enabled = m_JsonFile != null && m_SpriteAtlas && m_SpriteInfoList != null && m_SpriteInfoList.Count > 0;    // Enable Save Button if font_Atlas is not Null.
    110.             if (GUILayout.Button("Save Sprite Asset") && m_JsonFile != null)
    111.             {
    112.                string filePath = EditorUtility.SaveFilePanel("Save Sprite Asset File", new FileInfo(AssetDatabase.GetAssetPath(m_JsonFile)).DirectoryName, m_JsonFile.name, "asset");
    113.  
    114.                 if (filePath.Length == 0)
    115.                     return;
    116.  
    117.                 SaveSpriteAsset(filePath);
    118.  
    119.             }
    120.             GUI.enabled = true;
    121.         }
    122.  
    123.  
    124.         /// <summary>
    125.         ///
    126.         /// </summary>
    127.         List<TMP_Sprite> CreateSpriteInfoList(TexturePacker.SpriteDataObject spriteDataObject)
    128.         {
    129.             List<TexturePacker.SpriteData> importedSprites = spriteDataObject.frames;
    130.  
    131.             List<TMP_Sprite> spriteInfoList = new List<TMP_Sprite>();
    132.  
    133.             string path = AssetDatabase.GetAssetPath(m_SpriteAtlas);
    134.  
    135.             TextureImporter importer = (TextureImporter)AssetImporter.GetAtPath(path);
    136.          
    137.             importer.textureType = TextureImporterType.Sprite;
    138.  
    139.             importer.spriteImportMode = SpriteImportMode.Multiple;
    140.             var newMetaData = new SpriteMetaData[importedSprites.Count];
    141.             importer.isReadable = true;
    142.          
    143.             for (int i = 0; i < importedSprites.Count; i++)
    144.             {
    145.                 TMP_Sprite sprite = new TMP_Sprite();
    146.  
    147.                 sprite.id = i;
    148.                 sprite.name = Path.GetFileNameWithoutExtension(importedSprites[i].filename) ?? "";
    149.                 sprite.hashCode = TMP_TextUtilities.GetSimpleHashCode(sprite.name);
    150.  
    151.                 // Attempt to extract Unicode value from name
    152.                 int unicode;
    153.                 int indexOfSeperator = sprite.name.IndexOf('-');
    154.                 if (indexOfSeperator != -1)
    155.                     unicode = TMP_TextUtilities.StringHexToInt(sprite.name.Substring(indexOfSeperator + 1));
    156.                 else
    157.                     unicode = TMP_TextUtilities.StringHexToInt(sprite.name);
    158.  
    159.                 sprite.unicode = unicode;
    160.  
    161.                 sprite.x = importedSprites[i].frame.x;
    162.                 sprite.y = m_SpriteAtlas.height - (importedSprites[i].frame.y + importedSprites[i].frame.h);
    163.                 sprite.width = importedSprites[i].frame.w;
    164.                 sprite.height = importedSprites[i].frame.h;
    165.  
    166.                 //Calculate sprite pivot position
    167.                 sprite.pivot = importedSprites[i].pivot;
    168.  
    169.              
    170.                 // Properties the can be modified
    171.                 sprite.xAdvance = sprite.width;
    172.                 sprite.scale = 1.0f;
    173.                 sprite.xOffset = 0 - (sprite.width * sprite.pivot.x);
    174.                 sprite.yOffset = sprite.height - (sprite.height * sprite.pivot.y);
    175.              
    176.                 spriteInfoList.Add(sprite);
    177.              
    178.                 var rect = new Rect(sprite.x, sprite.y, sprite.width, sprite.height);
    179.  
    180.              
    181.  
    182.                 newMetaData[i] = new SpriteMetaData();
    183.  
    184.                 newMetaData[i].name = sprite.name;
    185.                 newMetaData[i].pivot = sprite.pivot;
    186.              
    187.                 Debug.Log(newMetaData[i].pivot);
    188.  
    189.              
    190.                 newMetaData[i].rect = rect;
    191.                 newMetaData[i].alignment = (int)SpriteAlignment.Custom;
    192.              
    193.                 //Debug.Log($"{ newMetaData[i].name} { newMetaData[i].rect}");
    194.             }
    195.          
    196.             importer.spritesheet = newMetaData;
    197.          
    198.             EditorUtility.SetDirty(importer);
    199.             importer.SaveAndReimport();
    200.             //AssetDatabase.SaveAssets();
    201.             //AssetDatabase.Refresh();
    202.             //AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
    203.  
    204.             return spriteInfoList;
    205.         }
    206.  
    207.  
    208.         /// <summary>
    209.         ///
    210.         /// </summary>
    211.         /// <param name="filePath"></param>
    212.         void SaveSpriteAsset(string filePath)
    213.         {
    214.             filePath = filePath.Substring(0, filePath.Length - 6); // Trim file extension from filePath.
    215.  
    216.             string dataPath = Application.dataPath;
    217.  
    218.             if (filePath.IndexOf(dataPath, System.StringComparison.InvariantCultureIgnoreCase) == -1)
    219.             {
    220.                Debug.LogError("You're saving the font asset in a directory outside of this project folder. This is not supported. Please select a directory under \"" + dataPath + "\"");
    221.                 return;
    222.             }
    223.  
    224.             string relativeAssetPath = filePath.Substring(dataPath.Length - 6);
    225.             string dirName = Path.GetDirectoryName(relativeAssetPath);
    226.             string fileName = Path.GetFileNameWithoutExtension(relativeAssetPath);
    227.             string pathNoExt = dirName + "/" + fileName;
    228.  
    229.  
    230.             if (AssetDatabase.LoadMainAssetAtPath(pathNoExt + ".asset") as TMP_SpriteAsset)
    231.             {
    232.                 m_SpriteAsset = AssetDatabase.LoadMainAssetAtPath(pathNoExt + ".asset") as TMP_SpriteAsset;
    233.                 Debug.Log("asset already exist");
    234.             }
    235.             else
    236.             {
    237.                 // Create new Sprite Asset using this texture
    238.                 m_SpriteAsset = CreateInstance<TMP_SpriteAsset>();
    239.                 AssetDatabase.CreateAsset(m_SpriteAsset, pathNoExt + ".asset");
    240.                 Debug.Log("create new asset");
    241.             }
    242.             // Compute the hash code for the sprite asset.
    243.             m_SpriteAsset.hashCode = TMP_TextUtilities.GetSimpleHashCode(m_SpriteAsset.name);
    244.  
    245.             // Assign new Sprite Sheet texture to the Sprite Asset.
    246.          
    247.          
    248.             m_SpriteAsset.spriteSheet = m_SpriteAtlas;
    249.             m_SpriteAsset.spriteInfoList = m_SpriteInfoList;
    250.             Debug.Log(m_SpriteAsset.spriteInfoList[0].name);
    251.  
    252.             string path = AssetDatabase.GetAssetPath(m_SpriteAtlas);
    253.  
    254.             var index = 0;
    255.             var sprites = AssetDatabase.LoadAllAssetsAtPath(path);
    256.          
    257.             //importer = (TextureImporter)AssetImporter.GetAtPath(path);
    258.          
    259.             for (var i = 0; i < sprites.Length; i++)
    260.             {
    261.                 if (!(sprites[i] is Sprite)) continue;
    262.              
    263.                 m_SpriteInfoList[index].sprite = (Sprite) sprites[i];
    264.                 //Debug.Log($"{sprites[i].name} {importer.spritesheet[index].pivot}");
    265.                 index++;
    266.             }
    267.  
    268.          
    269.             // Add new default material for sprite asset.
    270.             AddDefaultMaterial(m_SpriteAsset);
    271.          
    272.             UpgradeSpriteAsset(m_SpriteAsset);
    273.          
    274.             EditorUtility.SetDirty(m_SpriteAsset);
    275.             AssetDatabase.SaveAssets();
    276.             AssetDatabase.Refresh();
    277.             AssetDatabase.ImportAsset(pathNoExt + ".asset");
    278.             //AssetDatabase.CreateAsset(m_SpriteAsset, pathNoExt + ".asset");
    279.         }
    280.  
    281.  
    282.         /// <summary>
    283.         /// Create and add new default material to sprite asset.
    284.         /// </summary>
    285.         /// <param name="spriteAsset"></param>
    286.         static void AddDefaultMaterial(TMP_SpriteAsset spriteAsset)
    287.         {
    288.             Shader shader = Shader.Find("TextMeshPro/Sprite");
    289.             Material material = new Material(shader);
    290.             material.SetTexture(ShaderUtilities.ID_MainTex, spriteAsset.spriteSheet);
    291.  
    292.             spriteAsset.material = material;
    293.             material.hideFlags = HideFlags.HideInHierarchy;
    294.             AssetDatabase.AddObjectToAsset(material, spriteAsset);
    295.         }
    296.  
    297.  
    298.         /// <summary>
    299.         /// Limits the minimum size of the editor window.
    300.         /// </summary>
    301.         void SetEditorWindowSize()
    302.         {
    303.             EditorWindow editorWindow = this;
    304.  
    305.             Vector2 currentWindowSize = editorWindow.minSize;
    306.  
    307.             editorWindow.minSize = new Vector2(Mathf.Max(230, currentWindowSize.x), Mathf.Max(300, currentWindowSize.y));
    308.         }
    309.      
    310.         private void UpgradeSpriteAsset(TMP_SpriteAsset asset)
    311.         {
    312.             asset.spriteCharacterTable.Clear();
    313.             asset.spriteGlyphTable.Clear();
    314.  
    315.             for (int i = 0; i < m_SpriteInfoList.Count; i++)
    316.             {
    317.                 TMP_Sprite oldSprite = m_SpriteInfoList[i];
    318.  
    319.                 TMP_SpriteGlyph spriteGlyph = new TMP_SpriteGlyph();
    320.                 spriteGlyph.index = (uint)i;
    321.                 spriteGlyph.sprite = oldSprite.sprite;
    322.                spriteGlyph.metrics = new GlyphMetrics(oldSprite.width, oldSprite.height, - oldSprite.width / 2f + oldSprite.sprite.pivot.x, oldSprite.height / 2f + oldSprite.sprite.pivot.y, oldSprite.xAdvance);
    323.                spriteGlyph.glyphRect = new GlyphRect((int)oldSprite.x , (int)oldSprite.y, (int)oldSprite.width, (int)oldSprite.height);
    324.  
    325.                 spriteGlyph.scale = 1.0f;
    326.                 spriteGlyph.atlasIndex = 0;
    327.  
    328.                 asset.spriteGlyphTable.Add(spriteGlyph);
    329.  
    330.                 TMP_SpriteCharacter spriteCharacter = new TMP_SpriteCharacter((uint)oldSprite.unicode, spriteGlyph);
    331.                 spriteCharacter.name = oldSprite.name;
    332.                 spriteCharacter.scale = oldSprite.scale;
    333.  
    334.                 asset.spriteCharacterTable.Add(spriteCharacter);
    335.             }
    336.  
    337.             // Clear legacy glyph info list.
    338.             //spriteInfoList.Clear();
    339.  
    340.             asset.UpdateLookupTables();
    341.  
    342. #if UNITY_EDITOR
    343.             EditorUtility.SetDirty(this);
    344.             AssetDatabase.SaveAssets();
    345. #endif
    346.         }
    347.      
    348.     }
    349. }
    350. #endif
    351.  
     
  11. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The Sprite Asset Importer was updated in the latest release of TMP which is version 1.5.0-preview.x for Unity 2018.4 and 2.1.0-preview.x for Unity 2019.x or newer.

    The Sprite Asset Importer still only works with JSON Array because that is available in the free version of TexturePacker.

    I would suggest testing the changes in the latest release. Please let me know if you run into any issues and as usual feel free to provide feedback / suggestions.
     
  12. bradbecker

    bradbecker

    Joined:
    Dec 26, 2014
    Posts:
    130
    So does it work with Sprite Atlases now?
     
  13. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    It does not currently support the Unity Sprite Atlas system. I need some functionality to be added by the 2D team for this to work correctly in the Editor and at runtime.
     
    bz_apps likes this.
  14. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    I just paid $150 for a perma license for texture packer so I can add a few inline sprites to my text, when Unity's built in sprite atlas system should definitely be able to support Unity's built in text display system, lol.

    are the texture packer guys giving you some $$ kickback to delay integration? If not, they should be :D
     
  15. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    ohhhh and it doesn't actually work after my $150 ... ouchhhhh

    Is this error fixed in some specific version which is compatible with unity 2018.2.0f2?
     

    Attached Files:

    • tmp.jpg
      tmp.jpg
      File size:
      302.1 KB
      Views:
      424
  16. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    so it's just the sprite asset importer that's broken?

    http://digitalnativestudios.com/textmeshpro/docs/sprites/

    Using my externally created atlas I can still do asset / Create / TextMeshPro - Sprite Asset

    and get something functional in the game, I just have to manually set all the sprites using Unity's sprite editor?

    this workflow is just painful
     
  17. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I would recommend upgrading to Unity 2018.4 given it is the LTS release that is unless you have technical reasons not to uppgrade.

    If you can upgrade to 2018.4 then be sure to grab the latest release of the TMP package which is version 1.5.0-preview.7 as I believe the sprite creation issues should have been addressed. Let me know if that is not the case.
     
  18. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    That's great news, thanks. We are code locked to 2018.2 right now, but I'll install 2018.4 separately so I can try the sprite creation in there. I'm assuming once I have the sprites set up I can throw them back in 2018.2 for use. I'll report if there are any issues there as well.
     
  19. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    unfortunately getting the same error after installing 2018.4 & updating TMP to 1.50.7. This is also using the latest version of texture packer, and with some very friendly settings (basic spacing, no rotation, etc)

    In case it's helpful, I've also attached a zip of the json file & sprite sheet from TMP
     

    Attached Files:

  20. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Thank you for providing the above resources.

    In TexturePacker, please use JSON (Array) as the Framework instead of Unity JSON Data (.txt) and everything should work as expected.
     
    Last edited: Mar 12, 2020
  21. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,589
    Any idea when this is going to happen? SpriteAtlas support would make that a lot easier on the user side.
     
    Arthur-LVGameDev likes this.
  22. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    Thanks. This sort of works. The importer does accept the .json file & texture, but the resulting sprite coords are wrong, no matter what export settings I used. I tried about 10 different permutations and they all came out with incorrect coords, but at least the files were accepted. I've attached the most recent variation I tried.

    The only version I didn't try was setting up a grid of icons which would all be the same size for easy multiples across the sprite sheet. I couldn't figure out a way to get TexturePacker to do that, and doing it in photoshop wouldn't get me the atlas .json file I'd need.
     

    Attached Files:

  23. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Unfortunately, I don't have an ETA on this yet. So much to do and so little time to do it all...
     
  24. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The following changes should resolve the issue. You will need to make those changes in the Global Package Cache otherwise these will reset when you close / reopen Unity.

    These changes will be included in the next package release which should be over the weekend.

    upload_2020-3-13_14-54-23.png

    upload_2020-3-13_14-54-30.png

    Please test the above and let me know if you have any additional issues.
     
  25. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I also tested using different pivot points and this is working as expected as well as per the image below.

    upload_2020-3-13_17-44-27.png

    The first sprite has pivot in the bottom left corner, the next 3 in the middle and the last one in the top right.

    The pivot determines the positioning of the sprite relative to the Origin which for the first character is typically (0, 0) which is on the Baseline.
     
  26. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    Thanks, I finally got around to trying this. I'm not a programmer so I had some fun digging into the CS files to transcribe this stuff (don't tell our tech director)

    The good news: I got a working version using the sprite importer!

    The other news: rotated sprites and non power of 2 textures did not work for me. The recipe for success for me was exporting using power of 2 with no rotation. Everything else was set as default from TexturePacker for the json array.

    The other native unity exporters from TexturePacker did not result in usable files, I had to keep the generic json array export type.

    So, just update your tutorial bits to make sure ppl know to use the correct exporter type (TP nags about generic json array so that's worth noting), must use power of 2 texture sizes, and not allow sprite rotation.

    tmp_working.jpg

    This one shows the problem with rotated sprites on the atlas:
     

    Attached Files:

  27. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Rotation is not supported. Tight fitted would not work either as it would require more complex geometry (ie. not quads).

    Non Power of Two should work but that doesn't work on all platforms so I would stick to power of two.

    The only supported mode is JSON (Array) which is available in the free version of TexturePacker.

    I would love to update all those videos but given I am the only developer working on text / TMP, my hands are full ;)

    Any volunteers to create updated videos for other user? <wink wink>
     
  28. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    In regards to the tutorial, I just meant your walkthrough page. But sure, we'd be happy to make some tutorial vids for a reasonable fee. ;)

    I did notice setting pivot point in TexturePacker didn't result in any noticeable pivot point change in the newly created asset. It seems like the offsets will need to be adjusted individually with the current setup if you have differently sized sprites.

    My use case is specifically sprites in-line with text as you see here. This tutorial type text stuff is what this is all about for us:
    tmp_inline_sprite.jpg


    How were you setting the pivot point on the individual sprites? Is that something I can do with inline sprites? I tried setting the pivot in TexturePacker directly only but it didn't seem to work
    tp_pivot.jpg
     
  29. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The pivot defined in TexturePacker should affects the position of the sprite relative to the Origin / Baseline when inserted in the text.

    For example if the pivot is in the bottom left corner as depicted in the image below

    upload_2020-3-16_18-40-39.png

    When the Sprite Asset is created, this sprite will have its metrics such that the pivot will be placed at the Origin as seen below

    upload_2020-3-16_18-45-59.png

    The Origin of the glyph of character "A" as located at (0, 0). The Origin of the subsequent glyph is A Origin + A Advance. Given the pivot for this Leaf sprite was defined as the bottom left corner, this is where the sprite is inserted.

    If the pivot has been defined as the Top Right corner then we would have the image below.

    upload_2020-3-16_18-53-44.png

    If the pivot had been defined at the stem, we would get the following.

    upload_2020-3-16_18-55-6.png

    and so forth for the other positions.

    The Origin of the glyph following the Leaf would be Leaf Origin + Leaf Advance (which is the width of the sprite).
     
  30. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    is it possible to adjust pivots like that using text inline sprites, or only canvas objects?
     
  31. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The Pivot position defines the Bearing X (BX) and Bearing Y (BY) which defines the positioning of the Sprite Glyph relative to the Origin. This is identical to how character and their glyphs are positioned in terms of text layout.

    Sprites contained in a Sprite Asset are now comprised of Sprite Characters and Sprite Glyphs which are essentially the same as Characters and Glyphs in Font Assets.

    Characters and Sprite Characters are Text Elements which are roughly handled the same way in regards to text layout regardless of the target renderer whether it be a MeshRenderer which the <TextMeshPro> component uses or the CanvasRenderer which the <TextMeshProUGUI> component uses.
     
  32. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    Ok, I guess I was asking how to adjust the pivot point of inline sprites, which would definitely be of interest.

    The issue I have now is the pivot point / offset setup with inline sprites seems to behave in sort of funky ways. It's forcing me to hand edit every single OY offset to get the right layout even though the sprites were exported with the same pivot point.

    You can see this happen in the first 2 mins of this vid:



    in the middle of the vid I was monkeying around with the canvas to try to get some positive change which didn't work so I just undid that and then went through and started manually adjusting OYs but there has to be a better way.

    Possibly I'm doing something wrong or have an incorrect setting that you can see.
     
  33. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    What version of TextMesh Pro are you using in that video? Looks like a release prior to version 1.3.0 just looking at the UI.

    Please be sure to test with version 1.5.0-preview.7 and to make the changes I provided in a previous post above.

    Preview 8 should be available later tonight which will incorporate those changes.
     
    Last edited: Mar 18, 2020
  34. dark_tonic

    dark_tonic

    Joined:
    Mar 23, 2011
    Posts:
    138
    looks like 1.3.0 is the newest available with 2018.2 (which we're locked to atm). Is there any way to install 1.5.8 in there?