Forums » StepMania Development » [SM 5.1] New noteskin format and modifier system

Hm, that's not a bad idea, but it can't be done by the noteskin yet. You could fake it with some theme code, but it wouldn't turn out good. I could extend the system so that instead of specifying just width and padding for each column, the noteskin has to specify position, width, and draw order for each column.
< cybik> til Kyzentun fixes bugs for breakfast
--
< maxvg1> shakesoda: then why do i still play lol
<@shakesoda> because you're an ITG player. And thus, a masochist
--
<@shakesoda> Kyzentun: I think you might need to put down the meshes for a bit
Reply
Next up on the drawing table: Noteskin parameters, and theme layers in the notefield.
I haven't yet implemented these ideas at all, so they might change a lot.

Notskin parameters will be a standardized way for noteskins to have options that the player can set. For example, I've got a noteskin with little explosion particles when notes are hit (http://i.imgur.com/XGSbx8w.png). A noteskin parameter could be used to allow the player to use the options menu in a theme to turn those on or off.
To use parameters, a noteskin would have this in noteskin.lua, inside the table that is returned:

skin_parameters= {
frames= 2,
tap_graphic= "Love",
rots= {Left= 90, Down= 0, Up= 180, Right= 270},
},
skin_parameter_info= {
frames= {type= "int", min= 1, max= 4},
tap_graphic= {"3_9", "Chromatic", "Emoticon", "Grammar", "GrooveNights", "ITG2", "Love", "Tactics"},
rots= {
Left= {min= 0, max= 360},
Down= {min= 0, max= 360},
Up= {min= 0, max= 360},
Right= {min= 0, max= 360},
},
},


And notes.lua would have something like this:

return function(button_list, stepstype, skin_parameters)
local tap_graphic= skin_parameters.tap_graphic
local tap_frames_per_quantization= skin_parameters.frames
local rots= skin_parameters.rots

(then the other stuff that normally occurs in notes.lua, using tap_graphic and such)


skin_parameters is a lua table that can contain whatever the noteskin author wants to be modifiable. This is one of those places where I can't give much guidance beyond "Think about the choices you want the player to have". It can contain tables in a nested structure, so you can organize and build whatever data structure you want.

skin_parameter_info contains some basic information on the fields, so that the theme can build a menu for the player to pick from. The info for each field is stored in a table. For numerical fields, if the type field is not set to "int", then the theme can use a menu for a float number, and allow the player to set values like 1.5. (this example marks frames as an int, because 1.5 frames of animation in a sprite doesn't make sense). The min and max values are so the theme can know what range to limit choices to. Imagine a noteskin with 4 frames available for each note, but with the option to use only 1 frame to make notes unanimated.
Boolean values in skin_parameters are assumed to allow both true and false values. There does not have to be an entry in skin_parameter_info for boolean values.
String parameters need to supply a list of valid strings for the player to pick from.

So the system would work like this:
1. The player picks a noteskin.
2. The player goes to a noteskin config menu and sets some parameters.
3. The engine takes those choices, does some sanity checking, then passes them to the noteskin, as an argument to the loading functions.
4. The loading functions look at the parameters and adjust behavior appropriately.



Theme layers in the notefield:
Some themes may wish to do things that are convenient only in the notefield, like judgment flashes or hold judgments. So the idea here is to allow the theme to specify some layers above and below the notes, identical to the layers in the noteskin, for containing those things. I have no idea how I'll do this yet, I'm just thinking it could be useful to someone.


Problems:
Constructing a dynamic menu that can handle any table data structure of floats, ints, bools, and strings in the OptionRow system will be challenging. Making it work out nicely in Consensual is going to be a fair bit of work, and Consensual has tools for arbitrary configured numbers.
Translation will also be difficult. The theme will only have the name of the option to go off of. It can't have entries in the standard language files for every noteskin, because that info belongs with the noteskin. So there will have to be some way to embed translated field names in the noteskin for the theme to display for each language. Maybe add a translations section with entries for each language to the type info for the skin parameter.

Last edited: 3 December 2015 6:08am

< cybik> til Kyzentun fixes bugs for breakfast
--
< maxvg1> shakesoda: then why do i still play lol
<@shakesoda> because you're an ITG player. And thus, a masochist
--
<@shakesoda> Kyzentun: I think you might need to put down the meshes for a bit
Reply

skin_parameters= {
frames= 2,
tap_graphic= "Love",
rots= {Left= 90, Down= 0, Up= 180, Right= 270},
},
skin_parameter_info= {
frames= {type= "int", min= 1, max= 4},
tap_graphic= {"3_9", "Chromatic", "Emoticon", "Grammar", "GrooveNights", "ITG2", "Love", "Tactics"},
rots= {
Left= {min= 0, max= 360},
Down= {min= 0, max= 360},
Up= {min= 0, max= 360},
Right= {min= 0, max= 360},
},
},

Well, where to put option name?

Last edited: 16 December 2015 2:43am

Reply
This might be a good way to handle translating the titles and explanations for the options:

skin_parameter_info= {
frames= {
type= "int", min= 1, max= 4, translation= {
en= {title= "Frames", explanation= "Number of frames per quantization."},
ja= {title= "japanese title goes here", explanation= "japanese explanation goes here"},
}},
tap_graphic= {
values= {"3_9", "Chromatic", "Emoticon", "Grammar", "GrooveNights", "ITG2", "Love", "Tactics"},
translation= {
en= {title= "Tap Graphic", explanation= "Which graphic to use for taps."},
}},
rots= {
translation= {
en= {title= "Rotations", explanation= "The angle to rotate notes in each column to."},
},
Left= {
translation= {
en= {title= "Left", explanation= "The angle to rotate Left arrows to."},
},
min= 0, max= 360},
Down= {
translation= {
en= {title= "Down", explanation= "The angle to rotate Down arrows to."},
},
min= 0, max= 360},
Up= {
translation= {
en= {title= "Up", explanation= "The angle to rotate Up arrows to."},
},
min= 0, max= 360},
Right= {
translation= {
en= {title= "Right", explanation= "The angle to rotate Right arrows to."},
},
min= 0, max= 360},
},
},

The type info for each field has a translations table in it. Each entry in the translations table is for one language. They use the same two letter codes as used by the theme language files. There is an entry for the title and the explanation in each language field.
I think this can be made to work similarly to the normal translation system, where if there isn't a translated string, it falls back on english. If there is no english entry, it can use the first entry in the translation table. If there is no translation table, it'll have to just use the field name.

Does this seem like a good idea?
< cybik> til Kyzentun fixes bugs for breakfast
--
< maxvg1> shakesoda: then why do i still play lol
<@shakesoda> because you're an ITG player. And thus, a masochist
--
<@shakesoda> Kyzentun: I think you might need to put down the meshes for a bit
Reply
Good. didn't think to translate option title and explanation.
Reply
Update:
I have noteskin parameters implemented, and a menu for setting the parameters in Consensual


(Note: Normally, only one level of menu is shown on the select music screen. This screenshot shows 6 levels of the menu structure to make it possible to see how each layer of the menu is nested.)

I haven't settled on a menu design for the OptionRow system in the engine though. The OptionRow system does not make this task easy.
Each player can choose a different noteskin.
Each noteskin can have different parameters.
Parameters can be nested as deep as the noteskin author wants.
So the option rows must be dynamically generated when the player picks their noteskin, and there must be different option rows for the two players.
The OptionRow system does allow making rows that only one player can use, but having a lot of them would probably confuse the issue.
I'm considering making a lua option row that acts like the nested menu system I have in Consensual. The player would pick an element in the row and the row items would change to the stuff in that section of the noteskin params. This will also probably confuse people.
Guess there's nothing to do but implement it and have someone try it out.
< cybik> til Kyzentun fixes bugs for breakfast
--
< maxvg1> shakesoda: then why do i still play lol
<@shakesoda> because you're an ITG player. And thus, a masochist
--
<@shakesoda> Kyzentun: I think you might need to put down the meshes for a bit
Reply
Could intervals larger than a quarter note be specified in this new system as well? I want to make a noteskin with ReRave style quantizations, where half notes/downbeats are red and upbeats are blue.

Also, for playerizing 3D Noteskins, could some simple texture swaps on the model be feasible?
For example, have a little circle of texture "cut out" of the note's face; in normal mode, that sections normal texture would be "put back in", but in routine mode, it would be replaced by, say, a colored disk that said "1P","2P", etc. as needed. I understand this will only work on really simple 3Dskins, but it's a start.
Reply
Quantizations larger than a single beat will be easy to implement. I just have use logic similar to what I used to allow animations longer than a single beat.

That playerizing idea sounds interesting. It would require some way of specifying that certain polygons in the model are for the player texture, and a way to shift the player texture without affecting the rest of the model. That's going to be difficult.
< cybik> til Kyzentun fixes bugs for breakfast
--
< maxvg1> shakesoda: then why do i still play lol
<@shakesoda> because you're an ITG player. And thus, a masochist
--
<@shakesoda> Kyzentun: I think you might need to put down the meshes for a bit
Reply