Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better segment hovering raycast #576

Closed
kianzarrin opened this issue Nov 28, 2019 · 12 comments · Fixed by #624 or boformer/NetworkSkins#47
Closed

Better segment hovering raycast #576

kianzarrin opened this issue Nov 28, 2019 · 12 comments · Fixed by #624 or boformer/NetworkSkins#47
Labels
feature A new distinct feature
Milestone

Comments

@kianzarrin
Copy link
Collaborator

in #564 I made it easier to hover over small segment. Even so hovering can still be hard for small junctions. I think this is a caveat with skylines built-in ray-cast but I think I have a work around.

Here is the problem:
Cities_Ct6sactalI
In the picture above I have demonstrated a situation in which its very hard to select the highlighted segment end. In fact the 2 mouse positions in the picture above are the only places the mouse can be to select the desired segment end. You notice that the mouse is near the right segment but still the left segment is selected. This is not right. I think that the selection areas should be like this:
Screenshot (124)
Terminology:

  • hover area: the area the mouse pointer should be in in order to chose the desired segment end. In picture above its red stakes.
  • highlight shape: the shape of the highlight which is a blue half sausage.

Note that I want to change the hover area only. The highlight shape is and shall remain half sausage.

@kianzarrin kianzarrin added feature A new distinct feature triage Awaiting issue categorisation labels Nov 28, 2019
@kianzarrin
Copy link
Collaborator Author

kianzarrin commented Nov 28, 2019

To solve this issue I suggest to do this with vector directions
Screenshot (123) - Copy
in picture above :

  • green arrows: end direction vectors of the segments.
  • white triangle: mouse pointer
  • red arrow: direction vector connecting the mouse pointer to the node.
  • yellow arc: angle between the mouse vector and the segment vector.

So once we find the hovered node ID then we can iterate through its segments. The desired segment is the one that makes the minimum angle with the mouse vector.

The code bellow shows the concept. Though I think it fails to calculate the direction vector between mouse and node properly.

// EDIT: i fixed his code
private ushort GetSegmentFromNode() {
    ushort minSegId = 0;
    if (HoveredNodeId != 0) {
        var netService = Constants.ServiceFactory.NetService;
        NetNode[] nodes = Singleton<NetManager>.instance.m_nodes.m_buffer;
        var dir0 = m_mousePosition - nodes[HoveredNodeId].m_position ;
        float min_angle = float.MaxValue;

        netService.IterateNodeSegments(
            HoveredNodeId,
            (ushort segmentId, ref NetSegment segment) => {
                Vector3 dir;
                if (segment.m_startNode == HoveredNodeId) {
                    dir = segment.m_startDirection;
                } else {
                    dir = segment.m_endDirection;
                }
                float angle = Vector3.AngleBetween(dir0, dir);
                if (angle < min_angle) {
                    min_angle = angle;
                    minSegId = segmentId;
                }
                return true;
            });
    }
    return minSegId;
}

@originalfoo
Copy link
Member

originalfoo commented Nov 28, 2019

This would be great when camera is looking downwards, but what happens if user has camera tilted upwards (looking more towards horizon) and tries to select a segment on the far side of a junction?

EDIT: Anything that makes node/segment selection easier is a win from my perspective.

@kianzarrin
Copy link
Collaborator Author

kianzarrin commented Nov 28, 2019

I haven't done casting before but if we could cast the mouse on the terrain and find the coordinates that would be great. Don't we already do the same thing about lane markers?

@kvakvs
Copy link
Collaborator

kvakvs commented Nov 29, 2019

The terrain can be uneven, streets will approach the junction from all 3d directions. So yes, cast to the terrain, and then solve in 3d space.

@originalfoo
Copy link
Member

originalfoo commented Nov 29, 2019

Note, however, that transition (including between segments of different direction of same type of asymmetric road) and junction (including level crossings) nodes always flatten terrain, regardless of existing terrain or slope of segments connected to them. (It's why doing junctions on sloped rail tracks is such a nightmare).

@originalfoo
Copy link
Member

Random idea: Could we buff the clickability of segments based on their length? So the shortest segment is easier to select via the node (it's 'select triangle' within the node would be enlarged slightly)?

@kianzarrin
Copy link
Collaborator Author

kianzarrin commented Jan 18, 2020

I got this working on my test tool: https://github.com/kianzarrin/KianHoverTool/blob/450a5bf42b43e4361b2f9d5b4530780b21b18022/KianHoverElements/Tool/KianToolBase.cs#L169
I have not tried "buff the clickability of segments based on their length"
I have not taken vertical angle into consideration I set the vertical axes to 0. (and considering that the junctions are flat I do not think this is necessary)

@kianzarrin
Copy link
Collaborator Author

I integrated it into DetermineHoveredElements() code from TMPE.

@aubergine10 I managed to "buff the clickability of segments based on their length" as you suggested. easy peasy fun! But do you think I should do it? I will make it depend on a boolean so that we can switch forth and back at will.
pro: slightly easier to select small segments (small advantage)
con: sophistication may confuse user (small issue).

@kianzarrin
Copy link
Collaborator Author

I tested this on roads with bridges over. It works no-problem!

@kianzarrin
Copy link
Collaborator Author

I tested this with trains. No improvements with regards to level crossings. I will look into this.

@kianzarrin
Copy link
Collaborator Author

The reason why it does not work on level crossing is that this code does not find nodes of level crossing:

                    // find train nodes
                    nodeInput.m_netService.m_itemLayers =
                        ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels ;
                    nodeInput.m_netService.m_service = ItemClass.Service.PublicTransport;
                    nodeInput.m_netService.m_subService = ItemClass.SubService.PublicTransportTrain;
                    nodeInput.m_ignoreNodeFlags = NetNode.Flags.None;
                    // nodeInput.m_ignoreNodeFlags = NetNode.Flags.Untouchable;

                    if (RayCast(nodeInput, out nodeOutput))
                    {

I did not manage to hover level crossing nodes. TMPE hover such nodes by first finding the hovered segment and then looking at segment ends. It feels weird to find the node based on segment and then find segment based on node. but its worth a shot.

To

@kianzarrin
Copy link
Collaborator Author

my pull request #615 is merged in but I am having second thoughts about it! In particular this:https://github.com/krzychu124/Cities-Skylines-Traffic-Manager-President-Edition/pull/615/files/ced446c5fbf2ca559049df904f7eb56f25479d03#r368252980

I am looking at segment end to mouse pointer angle even when the mouse pointer is not at node but rather in the middle of a segment. Now that I think about it maybe it is possible to bend the roads so extremely to make the wrong segment selected. ~~I tried but did not managed to find a way to make the code fail. does not mean that it can't ~~ I manged to reproduce the problem using move it mod:
Screenshot (343)
I can call GetHoveredSegmentFromNode() earlier but that way Level crossings will not benefit from the node hovering boost.
I can also get rid of the angle based code and use GetClosestPositionAndDirection()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new distinct feature
Projects
None yet
3 participants