News:

Do you need help?
Simutrans Wiki Manual can help you to play and extend Simutrans. In 9 languages.

Wish: Diagonal graphics for signals

Started by makie, July 24, 2026, 10:15:41 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

makie

Wish: The possibility to define diagonal graphics for signals.

This look strange:

If it were possible to define custom graphics for diagonals, one could create suitable graphics for this case.

Isaac Eiland-Hall

Seems useful for road signs as well :)

victor_18993

Hi Prissi,

I have prepared and visually tested a proof of concept for optional diagonal
graphics on railway signals and static road signs.

I would like to keep the scope of this proposal deliberately small. I am not
proposing an immediate migration of paksets or a replacement of the existing
roadsign format.

Current proof of concept

The current patch adds an optional image block:

    diagonalimage[dir][state]

02-matrix-normal-diagonal.png

When present, the signal uses this list on a way for which
weg_t::is_diagonal() is true. Otherwise it continues using its normal
image[dir][state] list.

The runtime implementation has been tested for:

- normal and diagonal track;
- RED and GREEN states;
- per-slot fallback when a diagonal entry is "-";
- automatic image refresh when a later way_builder operation changes an
  existing signal tile from normal to diagonal;
- loading existing roadsign descriptors versions 1–6;
- no savegame, signalling, routing or network-state changes.

Compatibility issue found during review

The proof-of-concept writer currently emits roadsign descriptor version 7 for
every roadsign, including objects that do not define diagonalimage[].

The version-7 layout is:

    [name, copyright, normal images, diagonal images, cursor]

This works with the patched engine, and existing binary paksets continue to load
unchanged. However, recompiling an otherwise unchanged pakset with this makeobj
would unnecessarily convert all its roadsigns to version 7, making them require
the new engine.

I consider that broader than the feature needs, so I do not propose the current
writer behaviour as the final migration strategy.

Proposed intermediate transition

My preferred next step would allow the old and new systems to coexist:

1. Existing binary roadsign versions 1–6 remain fully supported.
2. If a .dat object does not contain usable diagonalimage[] entries, makeobj
  writes the existing version-6 layout exactly as before.
3. Only an object that explicitly opts in to usable diagonal graphics is written
  as version 7.
4. A partial diagonal list remains a fatal makeobj error.
5. An all-"-" diagonal block is treated as no diagonal graphics and remains
  version 6.
6. The new engine reads both version 6 and version 7 objects in the same pakset.
7. Pakset maintainers may therefore introduce diagonal signals gradually,
  object by object, without recompiling every other roadsign into the new
  format.

Under this intermediate model:

- current paksets continue to work unchanged;
- recompiling unchanged pakset sources preserves compatibility with existing
  engines;
- only the individual signals using the new feature require the updated engine;
- experimental diagonal signals can initially be distributed as optional
  addons;
- no pakset-wide migration is required.

This deliberately does not attempt to make a version-7 diagonal object load in
an old engine. The compatibility goal is instead to ensure that objects which do
not use the new feature remain in the historical format.

Possible further compatibility option

If preserving compatibility even for objects carrying diagonal graphics is
important, another possibility might be to keep the existing cursor child
position and append an optional diagonal-image child:

    [name, copyright, normal images, cursor, optional diagonal images]

That would only be viable if older readers safely ignore additional children.
I have not assumed this in the patch because I would prefer your guidance before
testing or relying on that behaviour.

Questions

1. Would conditional version-6/version-7 output be an acceptable intermediate
  migration strategy?
2. Would you prefer an append-only child layout, assuming old readers can safely
  ignore the additional child?
3. Should the first implementation remain an experimental addon/nightly feature
  until pakset maintainers have had time to adopt it?

The attached patch should therefore be considered a tested proof of concept for
the runtime behaviour, not a request to commit the current unconditional
version-7 writer unchanged.

I can revise the writer and regenerate the patch once the preferred compatibility
direction is clear.

Thanks.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

prissi

First: I would strongly suggest to apply for all signs, not only signals. I think there was even a patch around a long time ago. It had problems with "signals/drive_on_left" settings.

If signs were to included, I think a new imagelist for diagonal graphics works better, as several instances of signs have different number of images. So the offset calculation would be a quite complex. A missign diagonal child imagelist would be very straightforward and could set the flag on laoding time.

One thing that stopped diagonals was the drive-on-left feature. With this, the signals should be still end up in a reasonable position. Well, and someone has to draw new signs, signals, of course.

makie

Quote from: prissi on July 25, 2026, 06:05:15 AMFirst: I would strongly suggest to apply for all signs, not only signals. I think there was even a patch around a long time ago. It had problems with "signals/drive_on_left" settings.
New graphics won't change anything regarding the problem with "signals/drive_on_left". The problem already exists, and new graphics won't alter that.
Since they are then independent graphics, they can be positioned better than is currently the case as today the graphics are primarily positioned and designed for straight ways.

For road traffic signs, there is a problem with horizontal diagonal signs. Correctly aligned traffic signs are not really recognizable for the player. I mean the content of the traffic sign. Viewed from the side, a metal sign is simply a line. Probably need some tricks there. Railway signals are simpler here because they are always three-dimensional and therefore better recognizable.
QuoteIf signs were to included, I think a new imagelist for diagonal graphics works better, as several instances of signs have different number of images. So the offset calculation would be a quite complex. A missign diagonal child imagelist would be very straightforward and could set the flag on laoding time.
 
I don't really care how it's implemented program technically.
QuoteOne thing that stopped diagonals was the drive-on-left feature. With this, the signals should be still end up in a reasonable position.
This is a problem independent of the graphics. Think, an individual offset parameter for this in the .dat is the simplest solution to this problem. As "drive_left_offset" maybe for x and for y.
QuoteWell, and someone has to draw new signs, signals, of course.
That's the goal. Although pixel art isn't really my strong suit, so I'm very slow at it and for me it is hard work.

victor_18993

I reviewed the current roadsign image path and the earlier proof of concept before going any further with this request.

The most compatible approach seems to be adding a second optional image list for diagonal graphics, parallel to the existing image list, rather than extending the current list.

Conceptually:

image[direction][state]
diagonalimage[direction][state]

Both lists would use the same direction slots, states and index calculation. When the way is displayed as diagonal and a diagonal image exists, the object would use it. If that entry is missing, it would fall back to the existing normal image.

This appears to have several advantages:

- it can apply to all roadsigns, not only railway signals;
- existing paksets would keep their current behaviour;
- signal states, bidirectional signs, electrified variants and rotation could keep the current indexing;
- no signalling, reservation or routing logic would need to change;
- the existing way diagonal state could be reused instead of introducing a second definition of "diagonal".

There are still some design decisions that should be agreed before implementing it:

1. Whether the additional list should remain compatible with roadsign descriptor version 6, using an unused flag to indicate its presence, or whether the descriptor should be increased to version 7.
2. Whether traffic lights should be included in the first implementation or handled separately, since they currently use eight direction slots.
3. Whether the first version may intentionally leave closed diagonals outside its scope, because the current is_diagonal() flag does not cover that case.
4. Whether drive_on_left positioning should remain a separate issue, as Makie suggested.

There is also one required implementation detail: when construction changes a tile from a normal alignment to a diagonal one, the roadsign image must be recalculated as well as the way image, otherwise the old graphic can remain visible.

Before preparing another patch, does this optional parallel image-list design match what you had in mind?

Makie, if so, would you be able to provide a small test object or the diagonal graphics you are already preparing? Without real images we can test backward compatibility and image selection, but not the final positioning and visual result.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: victor_18993 on August 03, 2026, 12:10:37 AMMakie, if so, would you be able to provide a small test object or the diagonal graphics you are already preparing? Without real images we can test backward compatibility and image selection, but not the final positioning and visual result.
I need 1–2 days for that.

Quotebut not the final positioning
Don't worry about the final positioning.
That depends on the graphic and can easily be adjusted using the parameters in the .dat file as well as within the graphic itself.

victor_18993

Thanks. Before you prepare any test graphics, it may be better to wait until Prissi has confirmed the final scope.
I would not want you to spend time on assets that might need to be changed or redone afterwards. 

Once the remaining decisions are settled, we can work on the implementation and the graphics in sync, using the same agreed scope.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)

makie

Quote from: victor_18993 on August 03, 2026, 12:10:37 AM2. Whether traffic lights should be included in the first implementation or handled separately, since they currently use eight direction slots.

Traffic lights can not build at diagonals, there are no diagonal crossings.

prissi

My late comment:
I would call the diagonal image definition just diagonal[.... as the string matchin could catch the image[ part of diagonalimage[ Also, it is less to type and similar to ways and wayobjs.

makie

Quote from: victor_18993 on August 03, 2026, 12:10:37 AMMakie, if so, would you be able to provide a small test object or the diagonal graphics you are already preparing?
Here the normal rail signal: Standardsignal
https://makie.de/diagonal-signal.zip

victor_18993

We are already working on this patch and will provide a diff together with the corresponding tests once it is ready.

The implementation is not entirely straightforward, as it affects the descriptor format, image selection, compatibility with existing objects and the behaviour of roadsigns when the way geometry changes. At the moment, it looks possible to have a testable version during this week, but I would prefer to leave the timing open.

As you know, once the implementation is underway, additional variables or compatibility issues may appear and require more work than initially expected.

Thank you for providing the test object. It will be useful for validating the final behaviour.
En la vida todo son vivencias y cada una de ellas nos hace mas grandes,¿Como de grande eres tu? :)