Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Resolved Trouble scaling text

Discussion in 'Scripting' started by phoda, May 29, 2020.

  1. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    So I have this setup where i determine caret position from code since i use my own input field, i use just text field. So let me just explain problem
    Code (CSharp):
    1. Canvas: 1902x1080
    2. CMD container: has shell and input text
    3. when you type, characters are added to input text,
    4. because its horizontal layout items are from left to right
    5. Caret posititon is determined by shell text positon (0,0) and then add shell.width  text.width (of rect transform) to x position
    6.  
    7. I have other system of force update canvas and text generator and generating position by text vertices
    both of these methods work fine so for example at 1920x1080 resolution:
    Code (CSharp):
    1. Shell postion: 0, -25
    2. Shell width: 208
    3. Input position: 208, -25
    4. Input width: 221
    5. Caret position: 429, -36
    6.  
    7. This works perfectly fine with TextGenerator and width calculation method
    but if i change resolution to same aspect like 1280x720 or different aspect 800x600, Everything is destroyed, i tried using canvas scaler to multiply or take base resolution and divide it by current but nothing works

    Here are data for 800x600:
    Code (CSharp):
    1. Shell position: 0, -25
    2. Shell width: 199.5
    3. Input position: 436.28, -25
    4. Input width: 212
    5. Caret position: -19.68
    Okay i would understand that there is some big problem with my code if just the caret didnt work, but even input text position is wrong (shell cant be since it is at 0 position), shouldnt horizontal layout do the work?

    I tried using my own calculator so each update game calculates position of shell text and size, then use that to position input at end of shell and get width for caret to use, but that messes up even 1920x1080 resolution

    best that i got so far is using TextGenerator and then form those vertices using reference resolution/current resolution which is about 2.4 multiuplier for 800x600 but it is off for small amount which is good until about 20 chracters when gap is noticable

    Any help?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,797
    I cannot help you with your specific problem, but it made me think of a totally different way to get a caret.

    Here was my thinking:

    1. lay a second UI.Text (or TMPRo) object over the one you're using
    2. make sure all its settings match (size, etc.)
    3. have a script that copies changes in text from the first to the second UI.Text:
    -----> copy only as many characters as the caret
    -----> wrap the copy with HTML clear color tags
    -----> append the caret text

    It took me about 15 minutes to set up. You're welcome to tinker with it too... the entire package is enclosed, a single scene and a single script, and amazingly, it pretty much works. There's an edge case for end of line wraps but you can avoid that if you're doing your own text editing I presume.

    It amused me how quickly Unity lets you set stuff up like this. I love Unity3D!

    No guarantee it will behave on other encodings than simple ASCII. But... the price is right!

    PS: the text fields are slightly skewed to align the carets... might have to play with that.
     

    Attached Files:

  3. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    I dont have problem with setting up custom caret, my caret works fine, i do it by getting where caret is, display text until caret calculate position of caret at end of ext then display whole text. works fine.

    my problem is scaling to resolution for some reason it, horizontal layout doesnt scale it automatically
     
  4. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    Code (CSharp):
    1. //Get before and after text
    2.         string inputTextCaret = UIDB.t_Input.text;          //Gets what is inputed in cmd, stored so it can be returned later
    3.  
    4.         //Set only text before caret to text field
    5.         if(GetCaretPosition() > inputTextCaret.Length) {
    6.             SetCaretPosition(inputTextCaret.Length);
    7.         }
    8.         string preText = inputTextCaret.Substring(0, GetCaretPosition());
    9.         UIDB.t_Input.text = preText + "A";          //We add 1 character to move the caret 1 position to right
    10.  
    11.         //Caret position
    12.         Canvas.ForceUpdateCanvases();          //Forces update of canvas and it's text so caret can be updated properly
    13.         TextGenerator gen = UIDB.t_Input.cachedTextGenerator;          //Get TextGenerator from input
    14.         if (gen.verts.Count > 0)          //Calculate position of caret
    15.         {
    16.             Vector3 v = gen.verts[gen.verts.Count - 1].position;
    17.             v.x *= 1 / UIDB.mainCanvas.scaleFactor; //<----WORKS
    18.             v.x *= (UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width + UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y / Screen.height) / 2;
    19.             //v.x *= UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width;
    20.             DebugUtility.Log("scale factor: " + UIDB.mainCanvas.GetComponent<CanvasScaler>().scaleFactor);
    21.             DebugUtility.Log("scaling of canvas: " + UIDB.mainCanvas.scaleFactor);
    22.             DebugUtility.Log("wanted: " + (Screen.width / UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x + Screen.height / UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y) / 2);
    23.             DebugUtility.Log("my scaling: " + (UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width + UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y / Screen.height) / 2);
    24.  
    25.             v.y = 0 - ((RectTransform)UIDB.t_Input.transform).rect.height / 2 - ((RectTransform)UIDB.o_Caret.transform).rect.height / 2;
    26.             v = UIDB.t_Input.transform.TransformPoint(v);
    27.  
    28.  
    29.            
    30.             UIDB.o_Caret.transform.position = v;          //Add offset so we position caret correctly
    31.             //UIDB.mainCanvas.scaleFactor
    32.         }
    33.        
    34.  
    35.         //Set text in canvas AFTER caret
    36.         UIDB.t_Input.text = inputTextCaret;
    Okay so i got it to work, was quite stupid, so i calculated my own scale as scaler should do it screen width / ref res + screen height / ref height and all that / 2. Thing is i got 0.486111 and it should be 0.481125123 so i was always a bit off. i just used scale of canvas and did 1 / scale without doing my math even tho, i dont know why scaler is not right since it has some of its own math