How can I set coordinates so that x,y = 0,0 bottom left screen of the background image for this scene sprite?
0,0 is now centre of the viewport; that is not usable.
So I would like to align it to bottom left corner of the image.
I am trying to move a custom mouse (scene) to the same coordinates as the Windows mouse. When I move it to 0,0 (bottom left screen) they match but moving it up and right the distance between them becomes larger. I donât know what I am doing wrong here.
Note that TCastleWindowBase.MousePosition (or TCastleUserInterface.Container.MousePosition) are in âscreen coordinatesâ - i.e. in real pixels of the Playerâs monitor. And all UI and transforms are scaled in âeffective coordinatesâ - i.e. original (unscaled) pixels before they are scaled to Playerâs monitor. There are two values proportional to each other with TCastleUserInterface.UIScale (or TCastleWindowBase.Container.UiScale) coefficient. You can see this conversion done in the example Iâve posted above. For your specific case it will be:
Ah indeed, itâs TWindowContainer, not TUiContainer. And TUiContainer in turn hides FCalculatedUIScale as a private field allowing TCastleUserInterface to access it through âalmost-cheatingâ mechanism
So, overall, that means you cannot get access to UiScale except from a TCastleUserInterface derivative. I see you have designed your game screen in Castle Editor - that means you should load it as a TUiState, right?
This way if you are updating the Mouse.Translation inside some of the TUiState events (e.g. Update) then you can simply:
I am not using Castle Editor and TUistate (yet), the game screen was just for trying things out.
So how can I access UiScale within a TCastleUserInterface derivative?
@Carring Indeed the UI scaling is making this non-trivial.
But we have a dedicated methods in CGE viewport to make it easy: TCastleViewport.PositionTo2DWorld documented on Castle Game Engine: CastleViewport: Class TCastleViewport . If you pass ScreenCoordinates = true parameter, then it will automatically work with mouse position, and handle some things:
that UI scaling may be used (mouse positions are provided unscaled)
that viewport may not fill the entire screen.
So you can use the resulting value as MyTransform.Translation. E.g. code like this will make sense:
The ScreenCoordinates = false is also useful, it means that you provide values in viewport size (so e.g. X between 0 and MyViewport.EffectiveWidth). This allows to reliably ask âwhat is the position inside world at any corner of the TCastleViewportâ, e.g. MyViewport.PositionTo2DWorld(Vector2(0, 0), false) (left-bottom corner), MyViewport.PositionTo2DWorld(Vector2(MyViewport.EffectiveWidth, MyViewport.EffectiveHeight), false) (right-top corner) etc.
See also some related utils like PositionToRay, PositionToCameraPlane, PositionToWorldPlane. They all define ScreenCoordinates parameter with the same meaning.
Thatâs because mouse position doesnât have Z coordinate - itâs on the screen. But scenes indeed have Z coordinate - it goes from the Player (negative values) to depth (positive value). Here Z means Z-sorting, i.e. the scenes with higher Z are further away from the camera. So, if you want to have mouse cursor over all other scenes - be sure to give it the minimal Z coordinate value, e.g. like this:
P.S. Note, that itâs much more readable if you enclose the code pieces in â`â symbols (the back-quote one, which is on the same key where â~â symbol is.
If you use a matching pair those in one line you get blocks like this.
Or you can put three back-quote symbols on a separate line - and another three in the end to have a big block of code inside
This way your code will be much more readable and wonât lose indentation. (Yes, I didnât yet look at your code in that topic youâve mentioned above just for this reason - I canât such a big piece without any indentation and markup, and indenting it manually would take a lot of time.
For very large pieces of code you might also want to use https://pastebin.com/ or even a public git repository (at GitHub, GitLab or any other convenient git hosting with visual code viewer).
And I will experiment with your suggestion on the enclosure of the code.
(edit)
About the Z coordinate: Is it not the other way around that the higher the Z coordinate is, the scene is more placed in the front? When I give Mouse Z - 1 it is not visible on the screen. I think it is placed behind the background scene as it has Z 0 and other scenes have Z 1 and 2. I have to give Mouse Z a higher Z value than the other scenes to place it in front of all the others. so I gave it number 9.
As for placing the mouse cursor in front: remember to also call Viewport.Items.SortBackToFront2D after adding new mouse scene to Viewport.Items, to make proper blending. See Blending ¡ castle-engine/castle-engine Wiki ¡ GitHub for gory details.
I would like to use it in some way to make a certain picture area (sea) not accesible for a walking character (Transform). So I guess it is a transparant color overlapping an area that cannot be used for movement. It is however not quite clear how I can use this. Do you have a small example of this?
I believe you can do it a similar way. However, as youâve noticed that the example has an image underneath, because in that case itâs trivial - just check the appropriate pixel with scaling. As youâre using TCastleTransforms, it becomes significantly less straightforward - you either need to hack into the TCastleScene underneath to get access to the textureâs pixels or (worse at the first glance, but in a general case may be more reliable) render it into a texture and access pixels of this texture without displaying it on screen.
A hacky, but maybe a viable solution for this specific usecase is use separate alpha channel, but not to render alpha, but to store âdepth mapâ or âmovement mapâ (as in TGrayscaleImage from the example) and have it rendered with a special shader to keep the information and have easy access to it when the user clicks the screen, but do not actually render it as an alpha channel. TGA format allows to do something like that, but I believe youâll need a custom shader for that if done correctly, and this is a complex task.
A much more valid (but incomparably more complex) approach is to create a mesh (almost a navmesh) underneath, that would receive clicks and generate corresponding callbacks or using MouseRayHit. This should work out of the box and delegate the problem to the graphic artist (as in just click in blender to create the outline of the walkable area for every location properly aligned with the image).