Manual for ObjectNMLGenerator

ObjectNMLGenerator is a scripting tool that generates NML code for OpenTTD's Object NewGRFs via a graphical user interface (GUI).
It is designed for users with little or no experience in NML or coding, with the main focus on making the process comprehensible.

This manual provides the essential information needed to get started. For deeper understanding of NML, refer to these resources:

Although the generated NML code covers basic functionality (object dimensions, number of views, options for snow sprites and ground sprites, etc.), experienced users can still benefit from the programatically generated templates. These templates can be extended with advanced features as needed.

The following sections describe the process step by step, starting with setup and continuing through to usage.

Table of Contents

1 Setup
2 Sprites
3 Using the app
3.1 Toolbar
3.2 GRF block
3.3 Object properties
3.4 List of objects
3.5 Export
3.5.1 Generate NML
3.5.2 Generate & Compile
4 Settings
Contact

1 Setup

For convenience, a portable Windows release is available in the Releases section. It includes precompiled Lua binaries and other required dependencies, and does not require installation.

It is recommended to create a subfolder named gfx (for your sprites) in the root folder of your NewGRF project. Extract the contents of ObjectNMLGenerator-winx64-portable.zip into this root folder as well.

The folder structure matters because:

The _files folder contains internal script files and should not be modified.

You can start the program by running START.bat.

Example folder structure

After extraction:

After running the app:

2 Sprites

Add your sprites to the gfx folder. The images must follow these rules:

  1. Image format: .png
  2. Color depth:
  3. Views: the number of "options" in an object's submenu
  4. No margin between ground tiles and the edges/padding of a sprite (even if the ground is transparent).
  5. Height is arbitrary, but sprites taller than ~200 px above ground may cause graphical glitches.

Additional notes:

3 Using the app

To illustrate usage, this section follows a practical example, which can be found in the _example folder.

3.1 Toolbar

Toolbar

New list
Resets all input data (all unsaved entries will be lost!).
Hotkey: Ctrl + N

Open/Save list
ObjectNMLGenerator uses a YAML-like format to store your projects as lists of objects and their parameters.
The saved .yaml file can be reopened in the GUI (or even edited directly in a text editor).
Hotkeys: Ctrl + O and Ctrl + S

Example of a saved object:

1:
  bpp: 8
  snow: ON
  classname: Example objects
  image_height: 85
  bpp_snow: 8
  name: Example 1x1
  file: 1x1.png
  file_snow: 1x1_snow.png
  class: EXAM
  ground: 2
  file_ground: ground.png
  image_width: 64
  views: 1
  Ydim: 1
  Xdim: 1

Tip: You can drag and drop a YAML file directly onto the GUI.

Settings
Opens a dialog window for configuring the app's behavior.
See Settings for details.
Hotkey: Ctrl + K

Help
Opens Manual.html in your default browser.
If the file is not found locally, the app will offer to open the online version instead.
Hotkeys: Ctrl + H or F1

Tip: You can use Ctrl + Q or ESC in the main dialog window to close the app.

3.2 GRF block

GRF block

The fields inside the GRF block represent values that will be inserted into the "header" of your NewGRF.
The basics are explained below; for more details, see NML Tutorial: Starting an NML file.

Grf ID
GRFID is a four-byte string that uniquely identifies your NewGRF.
If two NewGRFs share the same GRFID, only one can be loaded in-game, also the other cannot be uploaded to the game's online content manager.

Examples of valid GRFID (backslash indicates that the next two characters represent one byte, i.e. two hexadecimal digits):

SF\1A\01, HTT\1F, OTTD, etc.

More details: TT-Wiki: Grfid

Version
The current version of your NewGRF. Increase this number with each release.

Min. comp. version
The minimum compatible version. Set this to the current version whenever backward compatibility is broken.
More details: TT-Wiki: Starting an NML file and TT-Wiki: NewGRF compatibility

NewGRF name
The name displayed in the NewGRF list in the main menu.

NewGRF description
The description displayed in the NewGRF list in the main menu.
Supports multiline strings. For information about special formatting and tags, see TT-Wiki: Language files

NewGRF url
Optional, but useful.
Usually this is a link to your project’s GitHub page or TT-Forums thread.


This is how the example GRF block looks like in-game:

GRF block in-game

3.3 Object properties

In this section, you define all properties necessary to generate a functional NML code.

Object properties

Tip: Click and hold the left or right mouse button on the eye icon next to a filename to display its preview.
To enable on-hover previews, see Settings.

File
Each object definition begins by loading a PNG file with sprites. The file location is arbitrary, but the script assumes that all sprites will be in the gfx folder at the time of compilation.
The filename serves as the identifier in the List of objects.

W - H - bpp
Width, height, and color depth of the loaded PNG.
This is display-only: if the source file changes, you must reload it so the algorithm can process it correctly.

Snow
Adds a snow variant of the sprite. Enable the toggle and select a PNG containing snow sprites.
The snow PNG resolution must match the "regular" variant:

Snow

Ground
Choose from a list of predefined base set ground sprites:

List of available grounds

Or browse for a custom file. Custom ground sprites must be a single tile with 32 bpp color depth:

Note: If you select but ground.png is not found in the gfx folder, this example sprite will be generated automatically.

Name
The display name shown in the in-game purchase menu.

Dimensions
The X and Y dimensions of the object, measured in tiles (maximum: 15 × 15 tiles).
A key parameter that determines the correct spritelayout in-game.
To prevent a common mistake, here is how OpenTTD's coordinate system works, shown on a 3x1 object:

Important: Notice how the 2nd and 4th views swap the X and Y coordinates.

Number of views
The number of "options" in an object's submenu. See Sprites for instructions on preparing images.

Class
A string literal of exactly 4 characters (allowed characters are A-Z, 0-9).
Defines the category in the in-game objects menu.
Objects with the same class will be grouped together in the menu (even across different NewGRFs!).

Examples: SF11, HTT1, OTTD, etc.

Classname
The actual name of a class that will be displayed in the objects menu.
Currently, the classname of the first occurrence of a class is used (although it is recommended to keep the same classname for all members of the same class to avoid confusion).

Add object
Adds the defined object to the List of objects.
If an object with the same filename already exists, the app will prompt you to overwrite it.
This allows you to update an existing object:

  1. Select the object from the List of objects.
  2. Edit its properties.
  3. Click Add object, confirm the prompt, and the object will be updated.

Important: Without clicking on Add object, the changes will not be added.

Properties in context

This screenshot illustrates how the defined properties appear in-game:

Object menu

3.4 List of objects

List of objects

This section displays all currently defined objects.
Since filenames are unique, the sprite filename serves as the identifier. The Class string indicates the object category.

The order of entries here determines the in-game order.
Use the ↑ and ↓ buttons to change the order, or the Remove object button to delete a selected item.

3.5 Export

Export


Quick summary

  1. Enter the desired output name in Save as.
  2. Choose Generate NML to create .nml and .lng files, or Generate & Compile to also produce a .grf.
  3. If compiling, ensure nmlc.exe is placed in the app’s root folder.
  4. Find the generated files in the root directory and copy the .grf to ...\Documents\OpenTTD\newgrf to use it in the game.

Note: If you change the output filename in the Save as text box, the name entered here will be remembered as the new default (unless changed in Settings).


Below is a more detailed description of the two export options:

3.5.1 Generate NML

If all fields are filled in correctly, the app generates the following output in the root folder:

If you want to add another language, you have to do so before the compilation.
For instructions, go to NML Tutorial: Language files.

These files are then ready to be used by the NML Compiler (NMLC).
If you prefer to compile the code yourself but are unsure how, follow the instructions here:
NML Tutorial: Compiler.

Note: Remember the folder structure mentioned in Setup.
The generated lang folder and .nml file must share a location with gfx.

3.5.2 Generate & Compile

This option performs the same code-generation step as Generate NML, but then also automatically compiles the NML code into a .grf file.

IMPORTANT:
Copy or extract the compiler (nmlc.exe) into the root folder of the app (i.e., next to START.bat).

If nmlc.exe is not found in the root folder, the app will prompt you to download the latest release from the official page: NML Releases on Github.
(look for the nml-standalone-x.x.x-win64.zip archive).

Missing compiler

Note: ObjectNMLGenerator releases do not include the compiler.
This not only reduces the size bloat, but more importantly it ensures that you always obtain the latest version of nmlc.

The output of the compiler is displayed in a dedicated popup console, which is helpful for spotting errors, because NMLC typically provides useful hints.

A successful compilation might look like this:

NMLC console

After compilation, the resulting .grf file will appear in the root folder.
Copy it into ...\Documents\OpenTTD\newgrf, then enable it in NewGRF Settings within the game (if you can't find it in the list, click Rescan files).

4 Settings

Settings

By default, the app is cautious and often prompts for confirmation before performing an operation.
Once you become familiar with the workflow, you may prefer to disable some of these safeguards by adjusting preferences in the Settings menu.

Additionally, you can choose whether to remember the last used folder and output filename, and whether the preview eye icon should also activate on mouse hover.

The dialog window can be opened either from the Toolbar or with the hotkey Ctrl + K.

To reset all settings to their defaults, delete the settings.ini file in the _files directory.

Contact

If you have questions about the app, you can reach me
@chujo on OpenTTD's Discord (discord.gg/openttd)

For general questions about NML or NewGRF development,
feel free to ask in the # add-on-development channel.