News:

SimuTranslator
Make Simutrans speak your language.

Colour tables

Started by Max-Max, July 12, 2013, 11:22:42 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Max-Max

I was thinking that when an image asks for a colour it doesn't need to know if it is a special colour, the manager will know this from the requested colour and return whatever colour it should be replaced with because the manager knows what colours should be mapped to a colour ramp or not (from the PAK colour definition).

Today we use special RGB values to indicate a special colour and these (I guess) are replaced when drawn depending on day/night cycle. The Idea was to let the PAK designer define these RGB special colours by himself and then also let him define how these colours are switched.

The difference here is that instead of having a hard coded RGB definition of each special colour, the PAK designer can define them. These are read in and used instead of the hard coded RGB values and matched in the same way as now to change night/day colours.

Instead of having only a day/night colour, the PAK designer could provide a colour ramp so the day night defined colour is switched to a different colour depending on the day/night/season cycle...

I will try to illustrate a practical example:

The day colour 0xC1B1D1 is replaced with the colour 0xD3C380 during the night (regarding to the Wiki). These colours are hard coded.

What I mean is that the artist can define an arbitrary colour to be replaced with another arbitrary colour, isn't it how it works now? Except that these colours are hard coded?. The colours would be defined in the PAK file and read into the colour manager.

format Color[n] = <SpecialColourTrigger>, <type>, <colour> [, <colour> ...]

<SpecialColourTrigger> is the colour in the image that will be replaced.
<type> decides how this colour is replaced.
<colour> [, <colour> ...] are one or more colour parameters defined by the <type>

# define RGB color #000001 to be a Day/Night colour, alternating between Day #8888FF and Night #111144
color[0] = #000001, DN, #8888FF, #111144

# define RGB colour #000002 to be a time triggered colour changing at hours 06, 07, 09, 12, 17, 18, 20, 21
color[1] = #000002, T, 06:#222266, 07:#333388, 09:#5555CC, 12:#8888FF, 17:#5555CC, 18:#333388, 20:#222266, 21:#111144


The type can be anything we can imagine :)

With this concept we are not bound to a limited predefined set of day/night colours and it doesn't has to be just one colour change (day/night) but different colours at different times of the day (if the PAK designer wants to). It can also be used to switch on "lights" in different windows at different time.

For theme primitives an SYSCOL_XXXX enum is mapped against a preloaded RGB table.
If an artist which, a theme image could also use this scheme to get darker and glow during night time.

A theme must in some way be able to show a player colour and this can be defined in the same way by using a <type> for player colours.
With this concept we only need to distinguish between indexed SYSCOL_XXXX (to colour primitives and text) and image special image colours.
If the Indexed system colour's RGB value is checked against the special colour table, well then you can have text to glow in the dark too :)

All this is handled by the manager. If the manager builds a sorted list of hours when to change a colour it only needs to be called once every hour and to execute the change, then the colour request doesn't need any logic in the moment we use a colour.

(you get the picture, there are a number of ways to optimize this for performance).

I have no idea of how the colour stuff works now, but it was just a thought...
- My code doesn't have bugs. It develops random features...

Ters

Quote from: Max-Max on July 29, 2013, 11:45:38 PM
I was thinking that when an image asks for a colour it doesn't need to know if it is a special colour, the manager will know this from the requested colour and return whatever colour it should be replaced with because the manager knows what colours should be mapped to a colour ramp or not (from the PAK colour definition).

This happens when running makeobj, which is a somewhat different thing from Simutrans itself, though some code is shared. There are no magic RGB values in images as far as Simutrans itself is concerned. Day/night colors are not hard coded (except the defaults), but configurable by simuconf.tab for each pak set.

Max-Max

Why do we have hard coded day/night colours if they can be configured in the pack set? (more than for backward compatibility?)

I didn't find this information in the English Wiki, but if I understand you right; already now a PAK designer can define what colours should be day/night colours and what colour they should be replaced with? (pretty mush as I suggested above)
- My code doesn't have bugs. It develops random features...

Ters

The number of indexes are hard coded, but the actual colors are not. Hard coded defaults are likely for compatibility and convenience.

The color values mapped to indexes by makeobj is also hard coded, likely because there is little reason for doing otherwise. Flexible colors here has the drawback that you can't reuse images across pak sets without replacing these colors.

wlindley

Can we unite the "industry colors" (see the MapColor parameter here) into the global color table?  In the same way we can draw player objects with primary-and-secondary color-scale values, it would be quite nice if one could draw factories with primary-and-secondary industry-colors, using the same two sets of "player" colors.  In that way, one could draw a single shop that would inherit whatever industry colors were assigned to it in the dat file -- a single set of images (four rotations, plus four snow rotations) would suffice for the butcher, the baker, the candle-stick maker, and so on, with only a mapcolor= parameter in the dat file (and a new mapcolor2= parameter, i suppose, for the secondary color).

Ters

More special colors makes it easier for the artist to inadvertently use a special color. Just doing such simple color replacements in the image editor might be the lesser evil.

Regarding my former post, I was mostly thinking of transparency and player colors. Color for lights has some merit in that one could use the same color both in and out, and these aren't fully interchangeable between pak sets anyway. There is still the issue that a color that works normally in one pak set has a special meaning in another, which can be confusing.

Max-Max

We are talking about artists here and we can assume they know one or two things about colours. Just assuming that something is confusing is like a farmer would tell me that a piece of code is to confusing for me to understand (unless the farmer happen to be programmer as well) :o

It is our job to make complex things easy for the novice, meaning we handle the complexity, not the artist :) I'm pretty sure we can do quite amazing things with colours under the hood and provide the artists with rich possibilities...

For example, I made a swatch palette with all the special colours (named and everything) ready to use in Photoshop. These small things may be all the artist need to understand the concept.
- My code doesn't have bugs. It develops random features...

Ters

Artists often get into trouble with the special colors we already have, using them when they shouldn't. That is very easy in image editors and 3D programs, as they don't know which colors makeobj treats specially, nor have logic to avoid certain colors. I also think most artists are amateurs, or more used to that colors are just colors.

Quote from: Max-Max on July 30, 2013, 10:50:12 PM
It is our job to make complex things easy for the novice, meaning we handle the complexity, not the artist :)
It's just that to me, you're suggesting making thing more complex for the artists.

Fabio

one idea if/when going rgb32 (with alpha) would be to remove special colors altogether and use 1 or 2 bw image masks to tell makeobj which areas should glow at night and which should be player-re-colored.

wlindley

I was hoping to use the already-reserved "player colors" (in the .png files), but have them handled differently for factories.  Currently, because all factories are owned by the public player, those colors just become grey (or was it orange; it has been some time since I checked). My suggestion was that they be translated to a higher range in the 65K color table, but still treated as group-of-8-color-scales like the player colors but for the industry MapColor.

As for masks -- can we at least use .png's transparency instead of a reserved background color?

Ters

Quote from: Fabio on July 31, 2013, 08:09:11 AM
one idea if/when going rgb32 (with alpha) would be to remove special colors altogether and use 1 or 2 bw image masks to tell makeobj which areas should glow at night and which should be player-re-colored.

I've been thinking at alternative solutions, and I don't think this will work. A mask for player color could be possible, but not for day/night colors. Not without losing the feature that day and night colors are different. Windows are blackish at day and lit at night. One would need many sets of images then: one image with base colors, one image with mask for player colors, one image with day colored light and one image with night colored lights. It might be possible to merge day colored lights with base colors. That would give lots of freedom, but at the cost of having to keep the sets aligned and matching. I don't know what artists think of this. As these images are just different aspects of the same thing, it would count as one image internally.

Quote from: wlindley on July 31, 2013, 08:33:01 AM
I was hoping to use the already-reserved "player colors" (in the .png files), but have them handled differently for factories.

There might be issues with caching of player-recolored images, but perhaps not much worse than a game with multiple players anyway. As a player, I'd prefer that simple color swaps only indicate ownership, and not to tell different industries apart.

Max-Max

#46
I think I will go back to the original request of this thread to try reserving some system colours in a new sys_color array.
Now we have a bunch of COLOR_VAL variables defining what color index should be used for various system colours:

COLOR_VAL gui_theme_t::theme_color_highlight           = MN_GREY4;
COLOR_VAL gui_theme_t::theme_color_shadow              = MN_GREY0;
COLOR_VAL gui_theme_t::theme_color_face                = MN_GREY2;
COLOR_VAL gui_theme_t::theme_color_button_text         = COL_BLACK;
COLOR_VAL gui_theme_t::theme_color_text                = COL_BLACK;
COLOR_VAL gui_theme_t::theme_color_text_highlite       = COL_WHITE;
COLOR_VAL gui_theme_t::theme_color_selected_text       = COL_WHITE;
COLOR_VAL gui_theme_t::theme_color_selected_background = COL_BLUE;
COLOR_VAL gui_theme_t::theme_color_static_text         = COL_BLACK;
COLOR_VAL gui_theme_t::theme_color_disabled_text       = MN_GREY4;
COLOR_VAL gui_theme_t::button_color_text               = COL_BLACK;
COLOR_VAL gui_theme_t::button_color_disabled_text      = MN_GREY0;
COLOR_VAL gui_theme_t::button_color_focus              = COL_WHITE;


The artist/user can override these values through the themes.tab file, but only redirect them to a new index not a specific colour.
This is quite frustrating because you need precisely that RGB colour to go with your theme, and it isn't available!

My thought was to create a system colour table (array) where the index is a specific system colour (such as color_shadow, or color_text_highlite). This table is of PIXVAL type (RGB1555) so the RGB colour can be loaded from the themes.tab file. In this way the artist/player can control the system colours a bit better.

As every one can see, these system colours are mainly text colours, an important part to control if you make a light or dark theme.
It looks trivial in my mind  :::) but I have not been in that part so much yet to truly understand how much work there is. I can say that these colours are not recoloured, nor accessible through the artists images (no mapping as we do for special colours).

enum sys_colors_et {
  SYSCOL_HIGHLIGHT = 0x<some suitable value>,
  SYSCOL_SHADOW,
  SYSCOL_FACE.
  SYSCOL_BUTTON_TEXT,
     ...
     ...
  SYS_COL_END_LIST
};

PIXVAL sys_colors[SYS_COL_END_LIST];
load_sys_colors();
display_proportional_clip(a,b,"bla bla",  ALIGN_LEFT | DT_DIRTY | DT_CLIP, SYSCOL_BUTTON_TEXT);


Any one up for the task?
- My code doesn't have bugs. It develops random features...

prissi

You can request any color by using #AB12CF in simuconf.tab. Despite any change you make later, simucponf.tab can use this already. As there are already too much construction areas with the themeable GUI (i.e. dialogue need to work with different sizes) and we need to release a stable version before the end of the year, I would not consider this top priority. The lookup tables are anyway needed for the factory and player color.

The color system is somethign I woudl suggest to renovate on its own at a later stage.

Max-Max

Alright, I complete renovation of the colours system is highly welcomed. I sooo want 24bit RGB/A (RGBA8888) :)
- My code doesn't have bugs. It develops random features...

Max-Max

#49
I think we need to address this issue again.

If the artist has the full RGB1555 range when designing the theme, he must also have the same range when setting the system colours.
In the current implementation he can set a RGB888 value, but  instead of converting it to a RGB1555 value, just as his images are, it its mapped to an indexed colour. This may end up as something very different than the same RGB888 value he used in the theme.

The two rgbmap_day_night and rgbmap_all_day colour tables are of the size 0x8000+LIGHT_COUNT+16 and there must be an index range available for system colours.

Can some one point out a block free colours indexes that I can use for system colours? I will have the theme manager to load RGB888 from the theme.tab, convert to RGB1555 and put them in the list  so they can be used with the normal colour index oriented display_xxx routines.

maybe 0x8F00 - 0x8FFF ?

***EDIT
After some more digging it seems like the primitive draw functions use specialcolormap_day_night[] and specialcolormap_all_day[] both the size of 256 entries. Maybe I should increase this to 512 so we get another 256 user defined system colours.

System colours are for example The highlight and shadow colours of "3D" rectangles, text colours etc...
- My code doesn't have bugs. It develops random features...

prissi

OpenTTD uses 216 color and never had much a trouble with those colors. The actual difference of colors on a monitor will much larger than the differences on the screen. At least no artist complained so far.

Ters

Quote from: Max-Max on October 05, 2013, 06:28:22 PM
In the current implementation he can set a RGB888 value, but  instead of converting it to a RGB1555 value, just as his images are, it its mapped to an indexed colour. This may end up as something very different than the same RGB888 value he used in the theme.

This not how it should be in my opinion. The variable that now holds the indexed color should hold the RGB555/565 color value, not an index. Indexed colors are only needed if images need to refer to them. Is that the case?

Max-Max

Quote from: prissi on October 05, 2013, 07:59:04 PMOpenTTD uses 216 color and never had much a trouble with those colors. The actual difference of colors on a monitor will much larger than the differences on the screen. At least no artist complained so far.
Maybe that is because the artist has never been able to set text colours, highlight etc. before. I found it quite annoying when I started to make the theme-paks, so I'm complaining ;)

Quote from: Ters on October 05, 2013, 08:05:07 PM
This not how it should be in my opinion. The variable that now holds the indexed color should hold the RGB555/565 color value, not an index.
I totally agree with you, but since no one is remaking this now the simplest solution was to extend the current system.
Quote from: Ters on October 05, 2013, 08:05:07 PMIndexed colors are only needed if images need to refer to them. Is that the case?
No, all basic drawing and text drawing are using an index into specialcolormap_all_day[]. Images are using direct PIXVAL.




I have already a working mock-up now. It turned out it was enough to increase the specialcolormap_all_day[] to make it work. Now the RGB1555 version of the RGB888 will be used and are stored at index 256 and up.

Now we can get rid of all the variables holding the system colour indexes.
- My code doesn't have bugs. It develops random features...

Ters

Quote from: Max-Max on October 05, 2013, 08:46:21 PM
I totally agree with you, but since no one is remaking this now the simplest solution was to extend the current system.

Touching the special colors, especially as a hack, is the last option. It affects way too many things. There should be half a dozen easier and better solutions.

Max-Max

Quote from: Ters on October 05, 2013, 09:54:07 PM
Touching the special colors, especially as a hack, is the last option. It affects way too many things. There should be half a dozen easier and better solutions.
I have not touch the special colours at all, they are exactly as before. I have only extended the array and placed the system colours on top of them. In this way I can use indexes > special colours and all the display_xxx primitives like, lines, boxes and text can now benefit from the extra system colours without any modifications.

Images are not using this indexed table and all the image related functions, used to recolour with special colours are unaffected.

In what way is this a hack? See it like we have expanded the list of special colours, but these are only used by the GUI system.
How would you have done it to not be considered a hack?

Since no one is working on a new colour solution on this side of the moon, I think this is the most clean way to do it, with a minimum impact of what we already have.
- My code doesn't have bugs. It develops random features...

Ters

I don't like it because it widens the gap between the special indexed colors available for drawing primitives and the indexed colors used in images. All these indexed tables, somewhat related yet somewhat different is confusing.

Building more functionality upon it makes it more difficult to change later. It's a hack because it's a small tweak that makes something kind of do what you want in a roundabout way, rather than doing it properly. And it's roundabout because it's pointless and overkill to have to allocate a handle (index) for something a trivial as a color value. The only thing justifying that is the ability to recolor images at runtime.

Maybe I can make some proper primitive drawing functions during the day. simgraph16.cc is a part of the code I know. But that might be the wrong choice if it turns out that recoloring GUI images at runtime is something we need later.

Max-Max

We do need player colours in the GUI so the artist can indicate the player somehow and in the end I can imagine that also factory colours would be handy. I have seen some requests on factory colours from the artists.

I brought up the idea of a colour manager earlier, to handle animated colours, such as day/night changes, colour conversions etc...
The artist would have a lot more freedom if he could chose the RGB values for these colours as well. This can easily be done by simply modify the special colour table. In my implementation I limited it to only be system colours, but it could go for all of them.
- My code doesn't have bugs. It develops random features...

Ters

The special colors table has a layout designed for player colors, where one can go one index up or down within a block to get a brighter or darker player color. Generic colors don't fit into this structure. They would fit into rgbmap_all_day, but that's only used for recoding images, not the primitive drawing functions.

Max-Max

Quote from: Ters on October 06, 2013, 02:42:43 PM
The special colors table has a layout designed for player colors, where one can go one index up or down within a block to get a brighter or darker player color. Generic colors don't fit into this structure. They would fit into rgbmap_all_day, but that's only used for recoding images, not the primitive drawing functions.
The Artist could set the Primary and Secondary colour and Simutrans can calculate the shades. This would give the artist/user more freedom. I have an idea of replacing the Player Color pick dialogue with an RGB colour picker. This may cause collisions in multilayer games, but it can be handled either by using the old colour picker for multilayer games or to just have the player to chose another colour if the one he selected is to close another player's colour.

There is always a solution to every problem ;)

PS. Wouldn't it be a good idea to move all colour related code to simcolor.h and a Simcolor.cc ?? DS.
- My code doesn't have bugs. It develops random features...

Ters

Quote from: Max-Max on October 06, 2013, 03:43:32 PM
PS. Wouldn't it be a good idea to move all colour related code to simcolor.h and a Simcolor.cc ?? DS.

It would be nice if it atleast was all collected together in one part of simgraph16.cc. The possibly main argument for keeping it in simgraph16.cc is that the color code is tied to 16-bit graphics. While we don't have 8-bit graphics anymore, there is still the 0-bit graphics.

Max-Max

So what approach would you recomed to implement the customized system colours.
Obviously we need to store them somewhere and they need to be fetched somehow, probably indexed.

I could create a color_list class where each color can be accessed through the operator[]. This could be the base class for colour lists in general. In the future it could also handle animated colour palettes so the system wouldn't have to keep track of when to switch colours.

Or I could just add another PIXVAL system_colormap[xxx];

I would prefer the class solution because it encapsulates colour handling, such as colour conversion, animation, loading etc...
It can also be derived into different types of colour lists.
- My code doesn't have bugs. It develops random features...

Fabio

If one day we moved to full RGBA32 would we have a concurrent simgraph32 or would we simply update existing files?

Max-Max

QuoteIf one day we moved to full RGBA32 would we have a concurrent simgraph32 or would we simply update existing files?
If we encapsulate colour handling into objects it would be easier to add new formats, such as RGBA32 and have the correct conversion in the object.
The use of a canvas concept would encapsulate the differences in low level drawing.

However there is a design pattern for this kind of problem, the Bridge pattern that allows a logical structure evolve independent of the hardware capabilities. They even don't need to use the same interface.

The canvas provide a public logical interface with primitives and use a separate class for the low level drawing. By switching this low level class, we can switch between many different platforms and/or graphical formats. We already have some sort of similar structure today, but they aren't encapsulated and separated.

In the theme manager there is a candidate for a canvas class, currently working on low level raw bitmaps, but can be the starting point for a canvas design.
- My code doesn't have bugs. It develops random features...

Ters

Quote from: Max-Max on October 06, 2013, 04:11:01 PM
So what approach would you recomed to implement the customized system colours.
Obviously we need to store them somewhere and they need to be fetched somehow, probably indexed.

How are they to be used? The advantage of indexed colors in Simutrans is that you can either encode them in color values (as images do) or do arithmetic on the indexes to get related colors (as for player color).

Quote from: Max-Max on October 06, 2013, 04:28:36 PM
If we encapsulate colour handling into objects it would be easier to add new formats, such as RGBA32 and have the correct conversion in the object.

If we encapsulate colour handling into files it would be easier to add new formats, such as RGBA32 and have the correct conversion in the file.

It's the same concept of modularization. The only real difference is that with objects, you can in theory switch them at runtime. (It can be done with file modules as well, but then it gets really ugly.)