Creating UI elements through script

Hello guys, im trying to create UI text element through script and I cant figure out what is wrong, the text object is created in onPress function, the text position is set to position of mouse/tap position when press happens , but the text is not shown on my 2D screen, entity is created, position is also set, i logged everything out but it just doesnt appear on the screen, is there anything i forgot maybe?

var TapLogoEffect = pc.createScript('tapLogoEffect');

// Initialize code called once per entity
TapLogoEffect.prototype.initialize = function() {
    // mouse events
    this.entity.element.on('mousedown', this.onPress, this);

    // touch events
    this.entity.element.on('touchstart', this.onPress, this);
    
    this.on('destroy', function() {
        
        this.app.off('mousedown', this.onPress, this);
        this.app.off('touchstart', this.onPress, this);
        
    }, this);

};

// Event handler for click
TapLogoEffect.prototype.onPress = function(event) {
    var mouseX = event.x;
    var mouseY = event.y;

    // Create a new text entity for "+1"
    var textEffect = new pc.Entity();
    this.app.root.findByName("Logo").addChild(textEffect);

    textEffect.addComponent("element", {
        type: pc.ELEMENTTYPE_TEXT,
        anchor: [0, 0, 0, 0],  // Anchored in screen space
        pivot: [0.5, 0.5],     // Pivot in the center
        fontSize: 32,
        color: new pc.Color(1, 1, 1, 1),  // White color
        text: "+1"
    });

    textEffect.element.zIndex = 100;
    textEffect.setLocalPosition(mouseX, mouseY, 0);
    console.log(textEffect.getLocalPosition());

    setTimeout(function(){

        //delete text in 1.5 seconds

    }, 1500);

};

// Update function (not used in this case)
TapLogoEffect.prototype.update = function(dt) { };

// Clean up the event listener when the script is destroyed

At least, the font is missing. If you create a text element in the editor without a font, you won’t see anything either.

What I personally always do is prepare things in the editor so I can easily apply them when needed. You can make a template of it and add it to your assets or just disable it in the editor. A special entity in your hierarchy used as a folder can help to organize this.

1 Like

Thats a nice idea, didn’t think of it this way, i reworked it and it is working as expected… well not quite expected, the text is created slightly off by 100px approx., both X and Y, i think it is not the issue with setting the position but getting the mouse input position on the screen, and also depends on screen size of the device im testing it on

Is the pivot of the text element centered?

After you mentioned it i tried but the result is kinda the same, it should be responsive to my screen size but its not…

Here you can see where it was instantiated, i pressed in the middle of screen

I think the topic below can help you, especially the example project from the last post (but this doesn’t work when Device Pixel Ratio is enabled).

Thanks for the reference project, however i tried to change the code and work around ui elements if it will help but still no results, the scale variable does something but i have really far from the same results, it looks it is depended on the entity it is created within, i tried to instantiate my template directly under 2D screen, different entities with group elements and everytime the result was different , sometimes better sometimes worse but i can never set the exact same position as my mouse, its weird it looks simple but i think there might be some issues with my UI elements and how i positioned them, there is one certain point on screen where i press and my template is going to have exact same position, but further i go with my mouse then so is my template being instantiated…maybe it has to do with my screen scaling or something , because its not always the same distance my template is created as i thought so

Hello @smokys :wave:

Quick suggestion…

If you always want your screen as portrait fix then use following values in Setting > Rendering
image

Maybe it will help?

1 Like

Hello, thank you for answer, it didnt help sadly :confused: however those settings you provided were crucial to be honest, it helped in other way, the project is public you can check and maybe find issue:
here is quick link for builded version to see how it works on your device PlayCanvas | HTML5 Game Engine

Just press the middle image to see, it is following the position of mouse in certain way but not exactly as expected, your settings made a slight change

1 Like

Here’s an example of putting a UI element in PlayCanvas screen space using a world position. https://developer.playcanvas.com/tutorials/world-to-ui-screen-space/

From the code, you should be able to adapt it to your needs

TLDR: Using the world setPosition, you can position it anywhere on the screen with -1, -1 being top left, and 1,1 being bottom right no matter the screen size. The positions are all normalised

Thank you for answer, but im not sure i follow, for what reason this should be better option than the one i used before? Im only working with UI elements there is no world entity that my UI should “follow”, or are you trying to highlight the “no matter the screen size” part?

Because internally, in the engine the elements are rendered in the ‘world’, just not in the way you normally associate it.

When you set the world position, the engine and the UI system will convert the position you pass it (between -1 and 1) into local position that is relative to the element hierarchy and screen. I personally find it a lot easier to use when I need to position an element relative to the ‘3D world’ or mouse position.

I still cant figure it out tbh, i reworked the code as you suggested, but not sure if im getting the mouse pos the right way using the onPress event, is there a way i can get global mouse position? it looks like im getting mouse pos relative to the UI element im pressing, maybe i need position relative to canvas

Really quick example project https://playcanvas.com/project/1262594/overview/click-me

1 Like