News:

Beta test the new forum at https://simutrans.forum/
Simutrans Sites
Know our official sites. Find tools and resources for Simutrans.

PAK image magic numbers

Started by Max-Max, June 19, 2013, 03:45:40 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Max-Max

So far I have only seen magic numbers for all images in the PAK file, such as:

const sint16 lw = skinverwaltung_t::window_skin->get_bild(12)->get_pic()->w;

Where 12 in this case is the round button left image constant.

Would it not be a good thing to create an enum with all the image constants?
The question is, should it be one large enum for all images in a PAK file or divided into several enums, one for each "set", like skin, ground, toolbar etc...

Does some one have the time to do this, only to create the enums, not to replace all the magic numbers.
I can replace the magic numbers when I see them in the code.
- My code doesn't have bugs. It develops random features...

Ters

An alternative is to access the images by name. Using the established Simutrans pattern for that, one would then have a big array with the names of the images and a pointer to a pointer. As images are loaded, the pointers pointed to get pointed to the image that has been loaded. When loading is complete, one can run through the array, see which entries have not been filled in and easily generate an error message with the names of what's missing.

It's a rather massive change, though, as it would affect every stage a pak file goes through from writing to loading and use. Some conversion from the current system would also be needed, in order to load old paks.

On the other hand, since the images no longer have to be in the same file, one can more easily swap out parts, perhaps even override.

Max-Max

QuoteAn alternative is to access the images by name.
Is that in place? I haven't seen this anywhere yet.

...or are you suggesting we implement a new system where we can have a name lookup for each image that is resolved at load?
- My code doesn't have bugs. It develops random features...

prissi

As the images in a skin needs to be numbers (and all buttons certainly has to be together) an enum on button makes sense.

A similar enum for scrollbars could be in place too; of course one would have to stop to reuse scroll bar images for posbuttons (not a bad think per se).

Accessing by name seem a little over the top, since the skins will be certainly pak files.

Max-Max

#4
One of my original ideas is to have the skin PAK separated from the other. Then it would be possible to select your favourite theme/skin regardless of the PAK you are playing.

There is already a skin folder, so one might scan this folder and display a list of themes for the player to chose between.

Yes, I think too that enums will do the trick to clean up a bit. Question is, where to put'em and how do we divide them?
one enum for skin elements, one enum for toolbar elements, etc... or just one big mother :redx: load of enum for all images?

Just out of curiosity...
QuoteAs the images in a skin needs to be numbers
...why?
- My code doesn't have bugs. It develops random features...

prissi

I would liek to have paks skin.button.pak which contains all skins for buttons, and so on.

Toolbar images must be pak dependent, because tools depend on paks; there may be paks using maglev for monorails or narrowgauge as normal and not using planes and so on. Those images cannot come from the skins. (One can still scale them, if needed, that is rather trivial.)

Ters

Also, since the toolbar is defined by the pak set, there should be no hardcoded magic numbers in the game code, right? These are all in menuconf.tab.

I think whatever header defines skinverwaltung_t should define the enum(s). As for splitting the current menu.WindowSkin.pak into several files, I assume then that since this pak file comes with the game, there is no need for backwards compatibility? Sounds complicated otherwise. In any case, I think there should be one enum per pak file, or rather skin node / image list.

prissi

Ters made a good suggestion:

- Do not care for backward compability of images.
- define enums in skinverwaltung_t include
- do not touch the toolbars

Fabio

toolbars could have background buttons separated from actual image so that you can skin the button safeguarding the tool image.

prissi

Yes, but this is not relevant to skinning. Furthermore, also these images would need to be scaled up or the sizes would not match the background images.

Ters

As long as the icons are smaller than the button skin, it isn't absolutely necessary to scale the icons to button size. But if the icons on the other hand are bigger than the buttons...

prissi

Please, scalable and skinable toolbars were discussed in the pak128 forum some time ago. Lets focus on GUI themes, please ...

Max-Max

So far I'm focusing on the current magic numbers. When that is done, you can set margin, buttons, edit box sizes (as seen in the picture under the project description).
- My code doesn't have bugs. It develops random features...

Max-Max

I have a question regarding reading "variables" from the menu.WindowSkin.PAK file.

If I add a new variable to the skin's .dat file, lets say button=100.25
How do I read it in Simutrans?

I found functions to read type, name and copyright, but they read them by index, not name. Isn't all names in a node tree that can be searched and read?
- My code doesn't have bugs. It develops random features...

Ters

Just writing something in skins.dat won't do anything at all. You have to write the code to read this variable from the dat file and write it to the pak file. If it is also just a simple variable, code is also needed to read it from the pak file and into a variable in the besch. For a nested node of an existing type, reading it is automatic, but an accessor is needed. What exactly is "button=100.25" supposed to mean? Menus are very a very generic data structure, so changing this isn't trivial.

Dwachs

For each pak/dat data, there is a pair of reader and writer code in besch/reader and besch/writer. The writers read dat files and produce pak files (makeobj), the reader reads the binary pak files and assign the data to besch properties.

In order to add more properties you usually have to modify three files: the besch file (besch/*.cc), the writer and reader.
Parsley, sage, rosemary, and maggikraut.

Max-Max

I thought it was a generic structure to read/write information in the .pak file :(
Why isn't the read/writer a part of the object it is serving?

button=100.25 was only an exampel of an arbitrary variable.

I need to add variables that defines GUI sizes, default colours for things like text, highlight, shadow etc...
- My code doesn't have bugs. It develops random features...

Ters

Quote from: Max-Max on July 06, 2013, 01:06:26 PM
I thought it was a generic structure to read/write information in the .pak file :(
Why isn't the read/writer a part of the object it is serving?

The writer writes to the file, but not from the same data structure the reader reads into. It is more associated with the format of the dat file. So it doesn't make sense for it to be part of the besch class.

The reader is not part of the besch class because one instance of each type of reader is registered in the pak loading system. They are some sort of self-registering singleton. It is the reader that figures out which besch class to instantiate for a given pak file node. The loader just loops through all registered readers and ask if any of them recognize the kind of node it has encoutered. The reader also contains a lot of compatibility code, which it is nice to have outside of the besch classes, especially those besch classes that have lots of code of their own.

Quote from: Max-Max on July 06, 2013, 01:06:26 PM
I need to add variables that defines GUI sizes, default colours for things like text, highlight, shadow etc...
You might have to come up with a new kind of pak node. First you should figure out how all this information should be organized, in memory, in the pak file and in the dat file. Also whether the parameters should be defined in a pak file or in a tab file.

Max-Max

My thought was that the artist defines button sizes, margins, padding, colours etc... and this goes into the theme PAK file together with the images.

The user selects his favourite theme to play with. But lets say that the artist designed the theme for a desktop screen, and the user want to play on portable with a touch screen. The user needs to enlarge the interactive elements in some way.

Here I was thinking to have a config file, in the .dat format that overrides the values set by the artist in the selected theme.pak file.
Images can't be overridden of course, only the variables.

So when loading a theme I need to read both a .dat file (for overriding) and a .pak file (artist's theme).

Implementing a node structure with arbitrary variables and their values, like the one when reading a .dat file, into the PAK file would benefit all objects I think. Instead of pending on a binary indexed structure, a value could be fetched by its name.

Such system would remove need of knowing the index of a variable and makes it a bit easier to be compatible between PAK file versions.
- My code doesn't have bugs. It develops random features...

Ters

If the variables can be overridden, I would put them in tab files to begin with. That's how they work now. Tab files override each other from game, to pak set, to user. (Might have to introduce theme in this mix.) This allows people to see the default values, which is hidden from them when in pak files.

Quote from: Max-Max on July 06, 2013, 03:32:06 PM
Implementing a node structure with arbitrary variables and their values, like the one when reading a .dat file, into the PAK file would benefit all objects I think. Instead of pending on a binary indexed structure, a value could be fetched by its name.

An arbitrary sturcture isn't as ideal solution, because one constantly has to worry about things not being there. The structure should be fixed somehow. That said, the current structure for storing GUI images isn't suited to what you are up to. It is a simple reuse of an image list which works well elsewhere, probably because it wasn't worth it making something more complex at the time. Up until then, one had to change the code and recompile to do any changes at all. (I've been told Simutrans wasn't born with interchangeable paks.)

I see two options:

       
  • Create a new node type for GUI components, each with its own fixed set of images (center, upper-right corner and so on, plus selected/normal/pressed/disabled). The component node would have a name, and be referenced by that. The node might also contain non-overridable fields.
  • Have the theme pak contain only image nodes and put everything else in tab file. The tab file would reference the image by its name, rather than some index in a list. Perhaps use image list nodes for cases where images belong together in fixed groups, like images for corners and sides of a box.

prissi

#20
Instead you theme defines, I had written a short tab file reading something. You can leave this to me, it is very straightforward. I can submit it, if you like.

I would suggest to read buttons as skin.button.pak, skin.scrollbar.pak, skin.gadgets.pak, ...

Since the images have already a size, I see no need to define it again somewhere again in a tab file.

The tab file should be rather:


theme_name="OrangeBorder"

pak_file_path="OrangeBorder"

window_border_width=3
window_border_color=3

left_margin_width=10
right_margin_....


Inside the folder "OrangeBorder" below this theme.dat there will be the pak files with the button definition.

Alternatively, one could define "buttons=skin.orenge_buttons.pak" and so on. But this make collisions more likely.

Max-Max

QuoteInstead you theme defines, I had written a short tab file reading something.
I have started to move away from the defines and read the actual size from the skin images.
Have you written the tab file or the code reading it?

QuoteYou can leave this to me, it is very straightforward. I can submit it, if you like.
I would be grateful if you could help out with a reader for the user tab file.

QuoteI would suggest to read buttons as skin.button.pak, skin.scrollbar.pak, skin.gadgets.pak, ...
I gave this some thought, and I think it would be easier to have it all in one PAK file. Artists and users can easily share the themes by only distributing one file. A component based theme it could mess up quite bad if one might mix theme components from different themes.

QuoteSince the images have already a size, I see no need to define it again somewhere again in a tab file.
This was my thought too until I tested it and discovered that all buttons became around 64 pixel wide  :::)

My thought is that the artist may (if he feels it is needed) to specify the size of the gui components, as he/she intended them to be, in the PAK file. The user can for the previous stated reasons override this in a user .tab file.

For example, button width:

Set default button width to a hardcoded default value.
Read theme PAK file and overwrite button width if the artist has specified another button width in the PAK file.
Read the users .tab file and overwrite the button width again if the user wants another button size.

the skin (or maybe theme) map will have one single PAK file for each theme and one single .tab file with user overridden values (common for all themes). In this way the user can make a touch screen configuration that will be applied regardless of the theme. I guess this is a must if you switch theme on your portable device.

For the time being I'm still using the current PAK format and we could implement the user theme tab file to override default values. Further down the road I have to write a new theme PAK format, as suggested earlier. But one small step at...
- My code doesn't have bugs. It develops random features...

Ters

From what I could see when looking at the pak file loading code, Simutrans can read multiple base nodes from one pak file. It is just that makeobj makes one file per named object. I haven't looked at makeobj code to see whether this is easy to change. Making a pak file merger shouldn't be too hard, though.

Fabio

individual object paks can be merged either at compile time either with makeobj merge line command. both are used e.g. in pak128.bat script (check svn out).
each object preserves its name, but you'll have a single file to distribute.

Max-Max

I have to write new writer down the road anyway. I'm planning to use the same concept as the Torque game engine uses for its skin, guardian colours to chop up the graphics.
- My code doesn't have bugs. It develops random features...

prissi

If you start like this, you will run into a problem: There are button with colored back and uncolored (normal) ones. Support for the first will be rather tricky within the current system, especially when you use different images and shades for depressed buttons. It might work with some additional special player color replacements.

But back to topic: I would prefer the user to either use a single pak file or individual ones. Several paks have certain buttons defined their way (Just look at the new menus in pak 192) http://www.simutrans-forum.de/forum/index.php?page=Attachment&attachmentID=18712 and hence may want to have their default instead the game default for at least some UI elements.

You can merge those pak (and unmerge) them since 0.82 or so using makeobj.


Max-Max

I was only showing the concept of a guard colour. Different buttons may need its own image.

The coloured button will be its own class (most buttons will be a new class). Just make the button surface transparent and the button class will paint the colour under it or we can have a fixed predefined colour that will be replaced, no big deal... :)
- My code doesn't have bugs. It develops random features...