Author Topic: NeoLemmix Formats - Styles  (Read 6600 times)

0 Members and 1 Guest are viewing this topic.

Offline namida

  • Administrator
  • Posts: 12399
    • View Profile
    • NeoLemmix Website
NeoLemmix Formats - Styles
« on: August 12, 2019, 09:13:02 AM »
This guide assumes you have read and are familiar with the basics of text-based files in NeoLemmix.

Please note: This guide is written for V12.11.X.

A custom style in NeoLemmix can consist of several components - terrain pieces, interactive objects, backgrounds, custom lemming sprites, and a "theme".

Each style exists inside its own folder in "styles". Please note - it is a VERY strong convention, that you should start your style's names with your own username, eg. "namida_bridge". The only exceptions that exist and have been accepted into the NeoLemmix styles are those from the official games (most of which are instead prefixed with the game they're from), plus "default" and "examples" which are obvious special cases. Within a style's folder, there will usually be a "theme.nxmi" file, and subfolders for each type of content.

It is also recommended that all your style / piece names be all-lowercase, and consist only of alphanumeric characters and underscores. In particular, uppercase letters and spaces should be avoided.

All images should be PNG files. No other formats are supported.



theme.nxmi

The theme.nxmi file defines a color scheme, as well as which lemming sprites to use, for levels that use this style as their theme. The theme.nxmi file is placed in the base folder of the style.

LEMMINGS - Specifies the style name to use the lemming sprites of. If the style has its own lemming sprites, usually, you'd use this style's name. Eg. LEMMINGS xmas would use the sprites from the "xmas" style.


If the lemming sprites you are using support recoloring (both Default and Xmas do), you may want to specify the colors for this too. If you are using recoloring with custom colors, you will need to check the spriteset's "scheme.nxmi" file to figure out the color names it uses. For the official styles, the names are listed below. You specify the colors for these names in exactly the same way as the above colors - in the same $COLORS section, not a second one.

Default-style lemmings (click to show/hide)

Xmas-style lemmings (click to show/hide)



Backgrounds

Backgrounds are very simple - place image files in a "backgrounds" folder, and they're good to go. That's really it.

You may optionally provide a matchingly-named .nxmb file. For example, a background "sky.png" might have a corresponding "sky.nxmb" file.

Currently the only line that is supported in an NXMB file is:

DEPRECATED - No value needed; marks the piece as deprecated. This means that, by default, the piece will not be visible in the editor (though there is an option to reveal deprecated pieces); it has no effect in-game.



Terrain pieces

Terrain pieces are almost the same as backgrounds - get the images, put them in a "terrain" folder.

Each terrain piece may (but does not have to) have a corresponding .nxmt file. For example, a terrain piece "steel_01.png" might have a corresponding "steel_01.nxmt" file. A PNG file for terrain, without a corresponding NXMT, is treated as if the NXMT existed but was empty.

The .nxmt file can contain the following lines:

STEEL - No value needed; marks the piece as steel.
DEPRECATED - No value needed; marks the piece as deprecated. This means that, by default, the piece will not be visible in the editor (though there is an option to reveal deprecated pieces); it has no effect in-game.
RESIZE_HORIZONTAL, RESIZE_VERTICAL, RESIZE_BOTH - No value needed. Specifies the direction(s) in which the object can be resized. It is valid to have both "RESIZE_HORIZONTAL" and "RESIZE_VERTICAL" as separate lines, instead of using "RESIZE_BOTH".
NINE_SLICE_XXX - (Where XXX is "TOP", "LEFT", "RIGHT" or "BOTTOM") Sets the nine-slicing margin - basically, a border region that's only drawn at the edges of the object even when resized, instead of being tiled with the rest of the object - on each side of the animation. Has no effect if the object is not resizable in the relevant direction.
DEFAULT_WIDTH, DEFAULT_HEIGHT - If the piece is resizable, this sets the initial size when placing the object in the editor. This is also used when loading a level file if the level does not specify the size - useful when changing the base size of a resizable object.



Interactive objects

Objects are a fair bit more complicated than terrains and backgrounds. Objects exist in the "objects" folder.

Each object consists of one or more PNG files, as well as a single NXMO file. Separate PNG files are used for separate animations; for multiple frames in a single animation, these are instead stored as a sprite strip - ie: a horizontal or vertical strip of equal-sized graphics, containing each animation frame.

The base name of the object comes from the NXMO file's name. Animation graphic files are named after this, with the animation name seperated from the piece name by an underscore. For example, a file "trap.nxmo" might have a corresponding animation graphic "trap_constant.png". Animations without a name - this is often the case for the primary animation - will simply match the NXMO's name, so in a file "trap.nxmo", an animation with no name specified would come from "trap.png" (not "trap_.png"!).

For the primary animations, if an object type has a single "idle" frame (for example, a triggered trap), this will be the first frame, with the rest being the animation sequence. If an object type has two idle frames (for example, a locked exit - it has the "closed" idle frame and the "open" idle frame), the one it will generally start as, is the second frame; while the one it will generally remain as once used / activated / etc, is the first frame. In the case of a locked exit for example, the first frame is the exit when open, the second frame is the exit when closed, and the remaining frames are the opening sequence.

In the case of a splitter, the first frame is pointing right, and the second frame is pointing left.

In the case of pickup skills, the skills are in the same order as on the skill panel, and each skill has a "picked up" frame then a "not picked up" frame. However, you should rarely - if ever - make the primary animation for a pickup skill object manually. Instead, there is a special system for pickup skill objects.

The NXMO file consists of the following lines:

General properties

EFFECT (click to show/hide)
TRIGGER_X, TRIGGER_Y - Specifies either the top-left corner of the trigger area (for objects that have an area), or the coordinates of the trigger point (for objects that just have a single point, eg. entrances, receivers).
TRIGGER_WIDTH, TRIGGER_HEIGHT - Specifies the size of the trigger area, for objects that have areas.
SOUND - Specifies the sound file to play when the object is activated.
KEY_FRAME - Specifies the "key frame". Currently, this only does anything for teleporters and receivers - it specifies the frame number at which the corresponding receiver will begin its animation, or at which the lemming will be released, respectively.
RESIZE_HORIZONTAL, RESIZE_VERTICAL, RESIZE_BOTH - No value needed. Specifies the direction(s) in which the object can be resized. It is valid to have both "RESIZE_HORIZONTAL" and "RESIZE_VERTICAL" as separate lines, instead of using "RESIZE_BOTH".
DEFAULT_WIDTH, DEFAULT_HEIGHT - If the piece is resizable, this sets the initial size when placing the object in the editor. This is also used when loading a level file if the level does not specify the size - useful when changing the base size of a resizable object.
DEPRECATED - No value needed; marks the object as deprecated. This means that, by default, the object will not be visible in the editor (though there is an option to reveal deprecated pieces); it has no effect in-game.
EDITOR_CROP - Overrides the usual algorithm the editor uses to determine whether or not to crop empty space around the object. Takes a value of "true" or "false". Has no effect in-game.

For objects that have digits displayed, such as windows and exits (when the lemming count is limited) or pickup skills, the positioning of the digits can be specified as follows:

DIGIT_X and DIGIT_Y - Specifies the position digits are displayed at. For the Y coordinate, this is the top of the digit graphic always; for the X coordinate, it may be either the left, right or middle depending on alignment.
DIGIT_ALIGN - Specifies whether to align the digits to the left (-1), middle (0) or right (+1).
DIGIT_LENGTH - Specifies the minimum number of digits to be displayed. If this is zero, digits will not be displayed at all if the value is equal to zero. For pickup skills, digits will also not be displayed if the minimum length is zero and the skill count is 1.

You can also define custom digit graphics. This is done by adding a 10-frame secondary animation, that's always hidden, called "DIGITS".

Animations

An object can have one or more animations, which are semi-independent of each other, and can play, stop, or even disappear based on certain conditions. The primary animation of the object is defined in a $PRIMARY_ANIMATION section, and all others are defined in an $ANIMATION section. These are identical, except for some keys not being useable in the primary animation.

As mentioned above, each animation should be a separate PNG file - although if there are two animations with the same graphic (differing, perhaps, by their position), it is perfectly acceptable to only have one copy, and have multiple animations refer to it (just give them the same NAME value).

FRAMES - Specifies the number of frames in the animation.
NAME - Specifies the name of the animation. See the above explanation about filenames.
COLOR - Specifies the name of a color (from the level's theme) that will be used to recolor the animation. This is not likely to be useful outside of a few objects in the "default" style.
HORIZONTAL_STRIP - Specifies that the animation's frames are arranged horizontally. If this is absent, they're assumed to be vertical.
Z_INDEX - Specifies the front-to-back order of animations. Lower values are drawn first; ties are broken by "primary first, then in-file order after that". The Z index, if not specified, defaults to 1 for the primary animation and 0 for all other animations.
INITIAL_FRAME - Specifies the initial frame of the animation. This has no effect for the primary animation if the object is a triggered object, but it does work for the primary animation on objects that have constant animation (eg. water, fire, etc). As well as numeric inputs, "RANDOM" is a valid value.
OFFSET_X and OFFSET_Y - Specifies the offset from the object's position at which this animation is displayed. Can be used on the primary animation, although it seems a bit silly to do so (but maybe there's a good use case I haven't thought of).
NINE_SLICE_XXX - (Where XXX is "TOP", "LEFT", "RIGHT" or "BOTTOM") Sets the nine-slicing margin - basically, a border region that's only drawn at the edges of the object even when resized, instead of being tiled with the rest of the object - on each side of the animation. Has no effect if the object is not resizable in the relevant direction.

The remainder of this section does not apply to the primary animation, only to secondary animations.

HIDE - No value needed. If present, the animation will initially be marked as "Hidden". Note that this does NOT automatically mean it won't be visible - see note below.
STATE - Specifies the initial state of the animation. Valid options are explained below. If absent, the default is either "PAUSE" (if "HIDE" is present) or "PLAY" (if not).
EDITOR_HIDE - This overrides the editor's determination of whether it should show the animation or not, and instead forces it to be hidden. Has no effect in-game.

You can then define conditions under which the animation will change state, by using $TRIGGER sections. When no trigger section's conditions are fulfilled, the animation reverts to its default visibility and state. When multiple sections' conditions are fulfilled, the last one in the file order has priority. The contents of these sections are:

CONDITION - Specifies the condition for the trigger. Explained below.
HIDE - No value needed. If present, the animation will be marked as "Hidden" when the trigger condition is met. Note that this does NOT automatically mean it won't be visible - see note below.
STATE - Specifies the state of the animation when the trigger condition is met. Valid options are explained below. If absent, the default is either "PAUSE" (if "HIDE" is present) or "PLAY" (if not).

Explanation of animation states (click to show/hide)




Custom lemming sprites

Lemming sprites must have a PNG file for each state, as well as a "scheme.nxmi" file which sets various attributes of the lemming sprites.

A lemming sprite PNG file consists of the frames of the animation arranged vertically. The two directions are arranged horizontally; left-facing on the left, right-facing on the right (or in other words - the sprites face away from the middle of the image). The number of frames can be arbitrary, though for certain animations it may look weird if they don't fit well with physics, so it's generally advised to use the same number of frames as the default sprites, or an integer multiple thereof. Also note that some states may have an upper limit due to physics; for example, it's pointless to give a Reacher animation more than 6 frames, as a lemming never remains a reacher for longer than that (they'll become a shimmier or faller after 6 frames at most).

Note that when a lemming first transitions into a state, animation starts from the 2nd frame (unless the animation only has one frame).

Lemming sprites are an "all or nothing" deal - you must either provide a full set, or not provide any at all. Even if an animation is intended to be the same regardless of the lemming's direction, a separate left and right version must be included.

Required graphic files (click to show/hide)

The scheme.nxmi follows the usual text-based format, and will have two or three sections.

$STATE_RECOLORING (click to show/hide)

$SPRITESET_RECOLORING (click to show/hide)

$SHADES (click to show/hide)

$ANIMATIONS (click to show/hide)



Aliases

The "alias.nxmi" file, which is optional and can be placed in your style's base folder, specifies information about which piece names should redirect to others. For example, if you specify an alias from "style1:blah" to "style2:beep", then all instances of the piece "blah" from style1, will be replaced with the piece "beep" from style2, when the level is loaded. The usual use case for this is when pieces are moved between styles, or renamed.

The alias.nxmi file can consist of any number of sections with one of the following keywords:

- $STYLE
- $GADGET
- $TERRAIN
- $BACKGROUND
- $LEMMINGS


These sections consist of two lines, a "FROM" and a "TO". These specify the piece name to translate from and to, respectively. In the case of $STYLE and $LEMMINGS, you would specify just a style name. In the case of the other three, you must specify a style name and a piece name, for example "orig_dirt:clump_01". However, there is a shortcut here - to refer to "this style", you can leave the style name blank. To use the same example, assuming this was the alias.nxmi file inside "orig_dirt", you could shorten it to just ":clump_01" (note that the colon is still there).

If the source piece is not resizable, but the target piece is, you may want to add "WIDTH" and/or "HEIGHT" lines as well, to specify the default sizing of the piece.

No style other than "default" should ever specify an alias FROM a piece in a different style. However, it's perfectly fine for an alias to point TO a piece in a different style.



High Resolution Data

By default, all styles will attempt to use the pixel art upscaler when used in high-resolution mode. It is possible to either specify the upscaling information, or to outright provide high-resolution graphics.

Upscaling configuration is done via an "upscaling.nxmi" file in the style's base folder.

upscaling.nxmi (click to show/hide)

You can also outright provide high-resolution graphics. You do so by placing files with the same name as the low-resolution images, into folders with the same name but an "-hr" suffix. For example, for high-resolution backgrounds, you'd place these in a folder called "backgrounds-hr".

Note that you cannot ONLY provide high-resolution graphics. Every piece MUST have a low-resolution graphic; you can then optionally add a high-resolution graphic as well.

A high resolution graphic should be exactly double the size of the low resolution graphic. In the case of terrain, any pixel that's solid in the low-resolution graphic, should correspond to a 2x2 region of which at least one (preferably two or more) pixels are solid in the high-resolution graphic; likewise, any pixel that's not solid in the low-resolution graphic should correspond to a 2x2 region where no pixel is solid in the high-resolution graphic. This is not important for other graphics, though they should still line up with the position of the low-resolution ones.

Note that no NXMT / NXMO / NXMB file or scheme.nxmi is provided for the high-resolution graphics. They use the same metainfo as the low resolution ones (of course, where there are coordinates, these would be doubled in high-resolution).
« Last Edit: March 28, 2022, 06:34:10 PM by namida »
My Lemmings projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)

Offline WillLem

  • Posts: 3383
  • Unity isn't sameness, it's togetherness
    • View Profile
Re: NeoLemmix Formats - Styles
« Reply #1 on: February 18, 2020, 06:03:45 PM »
Thanks for posting the above Namida, it's incredibly useful!

Just a heads up. Having a bit of trouble with $SHADES... the colours that are being automatically chosen are completely unrelated to either the source or destination colour.

For example, for hair I've got light blue and dark blue, and I've specified light blue as the source and dark blue as the ALT shade. The light blue gets recoloured to a light shade of yellow exactly as specified, but the dark blue becomes a random shade of dark maroon.

I fixed it by simply specifing the dark blue as a source shade in $SPRITESET_RECOLORING and then adding to the $STATE_RECOLORING accordingly, but I'm guessing that the whole point of $SHADES is to avoid having to do this...?

Offline namida

  • Administrator
  • Posts: 12399
    • View Profile
    • NeoLemmix Website
Re: NeoLemmix Formats - Styles
« Reply #2 on: February 18, 2020, 06:06:54 PM »
How different are the original VS shade colors? It works best when the hue is the same, or at least very similar.
My Lemmings projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)

Offline WillLem

  • Posts: 3383
  • Unity isn't sameness, it's togetherness
    • View Profile
Re: NeoLemmix Formats - Styles
« Reply #3 on: February 18, 2020, 07:46:55 PM »
How different are the original VS shade colors? It works best when the hue is the same, or at least very similar.

I think that they are slightly different hues when I look closely at it; the lighter blue has a fair bit more green in it, spectrum-wise. This could be what's happening.

I've managed to get it all sorted anyway by using $SPRITESET/STATE_RECOLORING, this allows much more targeted recolouring which has enabled me to get exactly the results I'm after. I just thought I'd point it out in case anyone else has the same issue.

EDIT: I could be wrong, but I think the first 2 digits of the Hex value have to be the same in order for it to be considered a shade of the same colour (at least for NL purposes). Altering the 'V' value of the HSV spectrum allows for lighter/darker shades of the same colour without changing the first 2 digits, whereas using the 'S' value mixes up the Hex values extensively. This could be something to do with it.
« Last Edit: February 18, 2020, 07:54:46 PM by WillLem »