News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

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

As I understand there are two kind of colours, 8bit COLOR_VAL and 16bit PLAYER_COLOR_VAL.
Both of them are indexes into a colour table with predefined colours.

I don't find it very user friendly to select a colour by its index (in GUI and .tab file). I would like to be able to use an 24bit RGB (RGB888) value in the .tab file for various theme colours, such as text, backgrounds, highlight etc.

Example: text_colour = #AA12C3

This format is widely used in both web design and paint programs, I don't think it would be any problems for a PAK artist or user to figure out the colour.

I don't see any difference in performance to use a RGB colour from a table compared to an RGB value in a 32bit variable. I'm not suggesting to change the whole colour system, but theme colours maybe can have its own table with 32bit values, read from the PAK or .tab file. Since a 24bit RGB888 has to be stored in a 32bit variable anyway, we could prepare it for alpha as well; RGBA8888.

Or does this go deeper? Is the drawing routines not capable of handling RGB888?
- My code doesn't have bugs. It develops random features...

kierongreen

For now if you want to select a colour in such a way I suggest you load/input 24bit values then convert these to 16bit values to use internally in game. All drawing routines in simutrans are coded for 16bit only and it would be a huge change to move away from this (that's not to say never, but there are various implications and it's a step for another day).

Max-Max

I suspected that there was a good reason why we still used RGB555 :)

Okay, converting to RGB555 seems to be the best way. I found a type PIXVAL (RGB1555), I guess that would be the preferred type to use.
- My code doesn't have bugs. It develops random features...

kierongreen

Yes that sounds right.

Max-Max

#4
Hmm, I found that PIXVAL is defined in 4 different files.

bild_besch.cc(9)
grund_besch.cc(31)
simgraph16.cc(65)
simsys_w.cc(46)


Shouldn't it be defined in one place; simgraph.h only?
- My code doesn't have bugs. It develops random features...

kierongreen

#5
Would make sense...

Edit: incorporated suggestion into trunk
r6586 | kierongreen | 2013-07-12 14:56:57 +0100 (Fri, 12 Jul 2013) | 1 line

PIXVAL typedef moved to simgraph.h

Ters

It would also make sense for get_system_color() to return this type.

Max-Max

I have actually started to sketch on a color_t class that can do all the conversions, lookup, blending etc...

But this is only on the drawing board so far. I will try to send a patch today that makes it possible to set some colours (indexed so far) through the new themes.tab file. When I have the color_t class ready you can specify a color as (hex) #RRGGBB or (decimal) r,g,b or index.

I take it as kierongreen has taken care of the PIXVAL definition and return type.

I'm missing a colour index for NO_COLOR (or COL_DEFAULT, COL_INVALID) which can be used to specify that default colour should be used or no colour (transparent).

Since the COLOR_VAL is an unsigned we can't use the old trusty -1, but as I understand, there can only be 224 colours in the indexed colour table. Maybe we can pick an index a bit higher up for this purpose?

Suggestions?
- My code doesn't have bugs. It develops random features...

Ters

If you keep going the way you're going, you'll end up rewriting the entire graphics system. I advice you to return to your original goal.

Simutrans actually has 65536 indexed colors. The first 32768 change with the day/night cycle. Then there are a player colors, which change depending on active player, and color for lights, which change discontinuously with the day/night cycle. The remaining over 30000 indexes are unused. But this is only used for rendering the world as far as I know. The GUI operates on a the smaller color table which is defined by the pak set. These colors have special meaning, which should be referred to, but not be defined by, the GUI theme.

Makeobj has certain color values reserved for mapping to these indexed colors, as well as transparent. It might be a good idea to reuse them for consistency, though tab files could use a special token instead of an RGB triple. The magic color values should be documented somewhere for the artists. Yet artists sometimes inadvertently use these colors, resulting in objects that glow in the dark.

kierongreen

I've just removed all the typedefs from the individual cc files and put one in simgraph.h that's all.

Max-Max

I was only looking for an easier way to define a colour for highlight, shadow, text etc... An index number doesn't say much and the limited index table doesn't offer to many colours either.

I was just looking for a way to define an arbitrary (not reserved) colour.
The COL_DEFAULT (or similar) is just a way to say that the default colour should be used where a function call needs a colour parameter,  such in buttons, labels etc...
- My code doesn't have bugs. It develops random features...

prissi

You could match the RGB value with the index. I added a get_color to the tabfile, which will always return an index, but internally handles also #AABBCC .

Ters

Quote from: Max-Max on July 12, 2013, 10:03:15 PM
I was only looking for an easier way to define a colour for highlight, shadow, text etc... An index number doesn't say much and the limited index table doesn't offer to many colours either.

It depends on what you want to highlight or give a shadow (not cast a shadow). For things colored according to player, like station and vehicle window title bars, one would have to use indexes or pseudo-colors. Not the real indexes in the 256 color specialcolormap, but ones that are remapped according to player. There are 32 such colors per player, divided in two 16 color ranges that each are variations of the two base colors for a player.

For colors that should be the same in all windows, specific RGB values should be used. I see no need to stick to indexed colors.

As for special values to indicate default color and transparency, I think PIXVAL values up near 0xFFFF is free. For specifying "use default color" in a tab file, I would suggest not specifying a color at all.

Max-Max

I'm a little bit confused here :o I will try explain what I want to do:

When I draw the images for a theme (only GUI related images) in for example photoshop I use any color I want in RGB888.

1) In simutrans I want the same coulours to be used as I chose in photoshop (oviosly converted to RGB555 by simutrans) not converted to nerest indexed system/predefined/special palette colour.

2) In the case of a missing theme element a fallback representation will be drawn. The draw routine needs a COLOR_VAL and this is an index, not a RGB555 value.

I don't see any reasons why the GUI should respond to any night/day coulours only player coulours would do. Currently there is no reserved index for system coulours, such as button highlight, button shadow, button face, static text, disabled text to mention a few. These coulours are a part of the theme and needs to be specified in the theme.

Have I understood right that it is possible to use a separate colour table (or space in the it table) where we could read in the RGB coulours from the theme file?

Or can this be solved in another way?
- My code doesn't have bugs. It develops random features...

Ters

I believe GUI colors should work like regular image colors, except that the special color values for lights should preferably not be used (they would still work, for now). For images, that means it stays as it is now. When specifying colors in the theme file, rather than painting them directly in images, it would be better to use symbolic names for these colors rather than magic RGB codes. This is on an assumption that the theme doesn't need to specify particular colors for a particular player, just the single active player for the particular GUI element.

Or is it really necessary for GUI images to be recolored by the theme tab file?

When reading in a theme that doesn't define a particular color for a theme element, a default color should be assigned for it during loading of the theme, so no special color value is needed for this further in.

Max-Max

QuoteI believe GUI colors should work like regular image colors...
Ok, That was my understanding too...  :thumbsup:

QuoteWhen specifying colors in the theme file, rather than painting them directly in images...
No, this isn't what I mean.

If you are happy with the gui look built into Simutrans (fallback code) you must be able to define what colour highlight, shadow, text, backgrounds should be painted in. I might want to have a dark background and then I must be able to define a matching RGB colour to draw the text with. In this way I can create colour theme by only redefining the gui system colours in the theme.tab file.

in the theme.tab file I can define the colours for the elements.

gui_static_text  = #AABBCC
gui_face         = #000022
gui_disable_text = #777777


These colours needs to be stored in the colour table so we can refer to them by index. But we want this index to have the specified colour from the theme.tab file.

Today we don't have reserved colour indexes for gui system colours (text, disabled, highlight, shadow, face etc...).
As Prissi mentioned before, this colour can be defined either as RGB or by index. If it is by index the indexed colour's RGB value is simply copied to the gui color table.

QuoteWhen reading in a theme that doesn't define a particular color for a theme element, a default color should be assigned for it during loading of the theme...
Yes, this is already how it works now. All gui elements have both fallback drawing and colours.

QuoteOr is it really necessary for GUI images to be recolored by the theme tab file?
No, you use the player colour and transparent colour as usual when designing the theme graphic images (for now). I haven't looked at the blending possibilities yet. I guess we can do quite interesting stuff with them as well, but maybe later down the road, who knows ;)

So what I understand of this is:
1) No we have no indexed system colours for gui.
2) It is possible to reserve indexes for these gui system colours (we have space).

Prissi
I guess you can give a hand here if you have time. I think it is an excellent idea to be able to refer to an indexed colour by name in the theme.tab file. In this way I could, for example, define the background to be the player colour. I don't think we need all of them, but at least the player colours.
- My code doesn't have bugs. It develops random features...

Ters

Why is it necessary to store the element colors in the index table when there is no need for image recoloring? That's what the index tables primarily are for, from my understanding. The GUI could just store the colors in its own table, and send the actual colors to the drawing routines. I'm unsure if there are any drawing routines that can either accept a real color or a indexed color, except for some related to images.

Max-Max

But how do you send an RGB colour value to the display_XXX functions?

display_text_proportional_len_clip()
display_fillbox_wh_clip()
display_vline_wh_clip()
display_ddd_box_clip
etc...


Doesn't these functions need a colour index?
- My code doesn't have bugs. It develops random features...

Ters

We can always write new functions if it makes sense to do so. It is important to think through how it best should work and then write the code to support that, not make strange solutions based on what functions are available.

Max-Max

This is why I'm asking. I haven't been digging enough in the low level graphic routines to make this decision by myself.

What is it you propose, new display_xxx routines that takes an RGB value as colour?
- My code doesn't have bugs. It develops random features...

kierongreen

That would certainly give more flexibility in future.

Max-Max

Isn't it easier to just add some more system indexed colours, load the RGB values from themes.tab into the colour table?

We have to store the RGB values in a system colour variable anyway, so I don't see what the difference is from reading the RGB values or passing the index of the RGB value.

If we are to rewrite all display_XXX routines to take RGB insted of index, we will end up in a lot of rewriting. It feels like a separate project in itself.
- My code doesn't have bugs. It develops random features...

Ters

What should refer to these special colors? Only code?

Max-Max

Yes, code only.

The user defines the colours in theme.tab, for example:

gui_static_text  = #AABBCC
gui_face         = #000022
gui_disable_text = #777777


These user defined colours are used internally in all display_xxx.
- My code doesn't have bugs. It develops random features...

kierongreen

I can look into the routines when I get home in a couple of days.

Max-Max

Splendid!

The system colours are now stored as COLOR_VAL in simskin.cc and handy defines in simcolor.h
themes_init() in simwin.cc are reading in them from theme.tab file.

The system works with indexes now and if we go for the expanded index table themes_init() should read the RGB values into the colour table.

I guess you will see what needs to be done ;)
- My code doesn't have bugs. It develops random features...

Ters

I think a new color table and therefore new functions are needed in any case. The player color table is a player color table, so it can't be used for new colors. The other one is tied to the day/night cycle. Even if the latter might be used by the current GUI, I think it's best to make a clear distinction between colors used for lights and colors used for the user interface. The former is specified in pak/simuconf.tab while the latter would belong in theme.tab.

Edit:
Didn't see the last post before posting.

prissi

As for now, the RGB is just translated into the best matching color index. Why is this not enough for the moment?

Also, as stated, the player colro table (the one with the 248 indexed colors) must not be touched, or player colors and factory colors and a lot of other hardcoded stuff in many routines which uses index will be wrong. But as also mentioned, a routine to draw a line/box with an RGB color is quite straight forward. Most of the current code just lookup the color from the inex anyway before drawing.

Recoloring images will be different though.

Max-Max

That was why I suggested to expand the current colour table and no, the default colours aren't enough. If you design a theme in photoshop, you are quite picky with the colours, especially if they are translated to RGB555 in Simutrans.

This is why I feel the need of a separate colour table that reads in RGB colours from the theme.tab file.
Each index in this table will become a GUI system colour such as Highlight, shadow, face, text, disabled text, static text, focus colour etc...

I think it would be good to create a colour class with member functions for colour manipulation. You could for example add two colours with a simple operator+(), get the index of nearest matching colour in the special colour table, blend a colour with alpha from another colour etc...

With an RGB/HSV colour dialogue the user could for example pick his player colour.
- My code doesn't have bugs. It develops random features...

Ters

Quote from: prissi on July 28, 2013, 10:56:57 PM
As for now, the RGB is just translated into the best matching color index. Why is this not enough for the moment?

I imagine that the best matching color could be very different.

Quote from: Max-Max on July 28, 2013, 11:45:57 PM
I think it would be good to create a colour class with member functions for colour manipulation. You could for example add two colours with a simple operator+(), get the index of nearest matching colour in the special colour table, blend a colour with alpha from another colour etc...

I don't think one should ever go from a color to an index, only the other way. You never know what index you end up with, what that index is for, and that index might stand for a very different color at different times.

Max-Max

QuoteI don't think one should ever go from a color to an index, only the other way. You never know what index you end up with, what that index is for, and that index might stand for a very different color at different times.
Makes sense, you might end up with a night colour ;)

What I meant was that we should try to encapsulate the colour manipulation/handling in a class.

The class can function as an adaptor between current system and "new" system to gradually replace the index system.
Each colour table can be an class instance and return a colour object for the requested system colour.

This colour object can be added, assigned, manipulated etc through member functions and operators like.

MyColor = "FFAADD";                // Assign from a Hex string
MyColor = RGB8(234,211,34);  // Assign from an RGB888 valaue (converted to RGB555)
MyColor = ThatColor;               // Assign from another colour object
MyColor = ThatColor + RGB8(1,3,6); // Assign from ThatColor + an RGB888 to RGB555 converted colour
MyColor.Blend(50);                  // Blend MyColor 50%
MyColor.Blend(30,ThatColor);  // Blend MyColor 30% with That colour

And so on...

A System color manager can handle the table of system colours.

ColManager[SYSCOL_TEXT] = RGB(0,0,0); // Assigna system colour
ColManager[SYSCOL_FACE].Blend(20,"AAAAAA"); Blend the system colour 20% with the Hex string colour
MyColor = ColManager[PLAYER_COL1]; Get the color of PLAYER_COL1

You get what I mean....
- My code doesn't have bugs. It develops random features...

Ters

Doing blending a color_t at a time is not an efficient way of doing it large scale, so while such a member function might be useful, it is likely that most blending will not use it.

One thing here is that Simutrans' architecture is made to support different color depths, though only "0" and 16-bit is currently used. Should we keep this feature, or drop it for simplicity? 8-bit support is likely pointless.

A single manager for all indexed colors might be difficult, because the different color tables behave differently. It might be better to have one manager for each color table.

Max-Max

If I could get a Christmas present It would definitely be 32bit (RGBA8888) :)

The benefit of having one colour manager is that you don't need to know anything about colour tables, night colours, player colours etc... The manager will pick the right values from the right table for you. You don't need to know how colours are stored or managed and access them all in the same way through the same interface.

If you really want to have separated managers, define a common interface in an ADT and derive each manager from it.

I'm just brain storming here, but with a manager we are no longer bound to a fixed colour space because the manager will store and maintain all colours for us.

One cool thing that might be possible is animated colour palettes. The PAK designer could define a colour ramp that will be used as a function of time over a day/night cycle. The colour manager would return colours from the ramp depending on the day/night time. The PAK designer could also define what colours should be replaced by such function and would not be bound to use any specific colours for night and day.

A color.dat file might define these special colours and maybe how they change. Depending on the complexity we could for example say that the ramp should be distributed over day or night cycle or at a specific time.

As I said, I'm just brainstorming and I see great potential here to add more tools for the artists to work with...
- My code doesn't have bugs. It develops random features...

prissi

Allmost any gui elements will be/is derived from PNGs (at least for title bars, icons, buttons ,... ) The old thing from a color index are font colors and the outline of a box (a 1 px thin line). For those an index seems ok.

Also the current code does not use adding two colors at all. The only thing are lighter and darker player colors. But as said previously, almost any function (like text drawing etc.) that takes an index concerts it into an rgb555. It will be very easy to have a function with index which just calls then the main function with rgb (888 of course).

32 bit is quite easy. But the larger the screens nowadys make even a larger hit to the performance. It was substancial slower the last time I played around (You could easily compile a 32 bit version, at least for GDI by setting the right defines in simsys_w32.cc imho).

Ters

Quote from: Max-Max on July 29, 2013, 09:24:44 PM
The benefit of having one colour manager is that you don't need to know anything about colour tables, night colours, player colours etc...

But you need to anyway. If it's a player color, the cached pre-remapped image must be regenerated or disregarded when you're drawing something belonging to another player than the one that was cached. If it's a night color, the same must be done when the day-night cycle changes.

When accessing a player color, you must also say for which player. This parameter would be useless for everything else. The internal logic is also very different, so you'd have lots of external code that just calls into one function, that in turn branches out to corresponding internal code.

GUI code shouldn't use special colors (lights). Nothing but the user interface should use theme colors. Everything uses player colors, though.