Parts Files
|
Like .dyc files, .par files also tend to go in the same directory as a character's specification (.dat) file, although this is not required.
For more information on terminology, see the Dynamic Character Primer.
Layout
- Lines beginning with
!
are comments. - Properties are of the form
PropertyName=PropertyValue
- Rules begin with a
%
Example
! bang to comment line ! Human Parts definition file ! [Root] Character\Dynamic\Human\Female\ [Slots] ! ! The slots are the areas defined for the Human in which various parts can go ! Hair Base Keyword=name:Base;type:hair;hasIncludes:no;path:hair;order:1; Hair Bangs Keyword=name:Bangs;type:hair;hasIncludes:no;path:hair;order:2; % onif(Hair Base) % LODoff(6) Helmet Keyword=name:Hat/Helmet;main:headwear;type:clothing; % hides(Hat) Head Torso Left Arm Right Arm Waist Left Leg Right Leg [Divisions] Hair: Hair Base,Hair Bangs Head: Head,Helmet Upper Body: Torso,Left Arm,Right Arm Lower Body: Waist,Left Leg,Right Leg [Parts] ! ! Slot: Part, Mesh file ! Hair Base: Empty,empty Hair Base: Bowl,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_bowl.hgm % hides(Hair Bangs) Hair Base: Medium,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_medium.hgm % hides(Hair Bangs) Hair Base: Mop,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_mop.hgm % hides(Hair Bangs) Hair Base: Wiry,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_wiry.hgm % substitutes(Hair Bangs:Parted Long,empty) Hair Base: Bobbed,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_bobbed.hgm Hair Base: Flip,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_flip.hgm Hair Base: Cropped,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_cropped.hgm Hair Base: Long,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_long.hgm Hair Base: Short,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_short.hgm Hair Base: Spiked,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_spiked.hgm Hair Base: Cornrows,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_cornrows.hgm % substitutes(Hair Bangs:Parted Long,empty) Hair Base: Wavy,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_wavy.hgm Hair Base: Half Tied,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_halftied.hgm Hair Base: Tied Up,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_tiedup.hgm Hair Base: Double Tied,Character\Dynamic\Human\Shared_Geometry\Hair\hairbase_doubletied.hgm Hair Bangs: Empty,empty Hair Bangs: Curved,Character\Dynamic\Human\Shared_Geometry\Hair\hairbangs_curved.hgm Hair Bangs: Parted,Character\Dynamic\Human\Shared_Geometry\Hair\hairbangs_parted.hgm Hair Bangs: Parted Long,Character\Dynamic\Human\Shared_Geometry\Hair\hairbangs_parted_long.hgm Hair Bangs: Split,Character\Dynamic\Human\Shared_Geometry\Hair\hairbangs_split.hgm Helmet: Empty,empty Helmet: Round Dome,Character\Dynamic\Human\Shared_Geometry\Helmet\helmet_round_dome.hgm % hides(Hair Bangs) % substitutes(Hair Base:Wiry,Cropped) % substitutes(Hair Base:Short,Cropped) % substitutes(Hair Base:Mop,Cropped) % substitutes(Hair Base:Spiked,Cropped) % substitutes(Hair Base:Bobbed,Cropped) % substitutes(Hair Base:Medium,Cropped) % substitutes(Hair Base:Flip,Cropped) % substitutes(Hair Base:Wavy,Cropped) % substitutes(Hair Base:Half Tied,Cropped) % substitutes(Hair Base:Bowl,Cropped) Head: FaceGen,head_whole_facegen.hgm Torso: Bare,torso_bare.hgm Keyword=default Upper Right Arm: Bare,arm_ur_bare.hgm Lower Right Arm: Bare,arm_lr_bare.hgm % LODSubstitutes(3,LoResBare) Lower Right Arm: LoResBare(alternate),arm_lr_bare_lowres.hgm Keyword=lores Waist: Pants,legs_pants_default.hgm Keyword=default Lower Right Leg: Bare,leg_lr_bare.hgm Keyword=footwear Lower Left Leg: Bare,leg_ll_bare.hgm Keyword=footwear [Banks] female_base_upper_body female_base_lower_body hair female_head
Root
This is the repository folder where the .par
file that you're editing is located. It's also the directory where part files will be searched for if the part specified isn't a complete FQN path (that is, if it's partName.hgm instead of Character\SomeDirectory\partName.hgm).
Slots
Each slot name is listed here, with properties and rules following it (indentation isn't required, but is nice for readability).
The only currently available property for slots is the keyword property.
Note that subslots are not specified here; instead, they go as properties under individual parts.
Divisions
Slots are organized into one or more divisions. The divisions are used to communicate information to the user interface (that is, to HSL scripts). The parts system doesn't use divisions internally for anything, this is merely potentially useful information for HSL scripts, which request slots by division. You need to coordinate the use of divisions with your UI design and implementation teams.
The format for divisions is as follows:
DivisionName: FirstSlotInDivision,SecondSlotInDivision,ThirdSlotInDivision
And so forth. The order of slots is preserved when HSL requests the slots in a division using the functions GetDivisions()
and GetDivisionStatus()
.
Each division must be completely specified on a single line (that is, one line per division), so you might want to turn off word wrapping in your text editor to make the .par easier to read.
Parts
A part specification consists of an initial definition line with properties on following lines.
The definition line looks like this:
SlotName: PartName,PathToPart\partFileName.hgm
If PathToPart is omitted, the part file is searched for in the directory where the current .par is located.
The first part specified for a slot becomes the default part, which is the part that's filled in when the slot first becomes visible.
Properties
Valid properties for parts are the following:
- Keyword
- Subslot - Essentially the same as a slot specification in the [Slot] section above, but specifies a subslot. Any rules or keyword properties specified after this property are assigned to the subslot, until another part specification is reached. This means that you should put all part rules and keywords before any subslot properties. Subslot parts should be listed as a group in a separate area of the [Parts] section, just like you'd do for the parts of a slot.
- Subslots use the same rules as regular slots.
- Subslots cannot themselves have subslots.
Empty Parts
Empty parts give the user the option to not have anything selected in a visible slot. Without an empty part specified for a slot, at any given time that slot will either be a.) disabled or b.) guaranteed to have something visible in it.
Specify an empty part like so:
SlotName: Empty,empty
At this time, empty parts can't have rules or properties.
Typically, you'll want the empty part to be the first part specified (the default part), so that when a slot is enabled it doesn't automatically force an option on the user and visibly change their character.
Alternates
An alternate part is never returned as an option to the user. So if PartA is substituted out with PartB and PartB is an alternate, the system will report PartA as still being selected. This allows you to have LOD parts, as well as parts that are used to combat polygon penetration, etc. (i.e. switch to an alternate short hair part when wearing a hood so that fancy hairdos don't stick out of the hood) and the user will remain unawares. Tag a part as an alternate by adding (alternate) to the end of its name, i.e. SpecialHair(alternate).
Banks
In this section, specify all texture banks used by the parts in this .par file. This is so that HSL scripts that work with part files are guaranteed to have access to these before any parts are selected that use them.
Rules
Rules are a powerful feature that allows slots to change parts automatically. For example, if the character has a hood on, their hair slot should be set to empty so that the hair won't penetrate the hood. You can also make specialized parts that fit with other parts. For example, boots with cuffs are often problems with robes because the cuff part will penetrate the geometry of the robe. An artist can create a version of boots with no cuffs that gets substituted in when robes are on; to the user it will just look right.
- % hides(slotName) - Completely hides slotName, making it completely inaccessible to the user.
- % shows(slotName) - Shows the given slotName, making it accessible to the user.
- % onif(slotName) - Causes the slot whose rule this is to be hidden if slotName is hidden or is currently empty.
- % substitutes(slotName:PartNameToSwitchOut,PartNameToSwitchIn) - Replaces PartNameToSwitchOut in slotName with PartNameToSwitchIn. Assumes that PartNameToSwitchIn exists in slotName.
The following is only allowed to be specified under slots:
- % lodoff(LODLevel) - Hides the slot when the character reaches or is beyond a certain LOD level.
Tip: Enabling tooltips in HeroBlade will allow you to see a character's current LOD level. |
The following is only allowed to be specified under parts:
- % lodsubstitutes(LODLevel,LODPartName) - Swaps out the part for whom this rule is being specified with LODPartName when the character reaches LOD level LODLevel. Assumes LODPartName is in the same slot as the part for whom this is being specified. LOD substitutes are evaluated in order for the first match, consequently when using multiple lod substitutes the highest must be listed first (top->bottom). (i.e. lodsubstitutes 5, must come before lodsubstitutes 4, which comes before lodsubstitutes 3, etc).
- Rules are evaluated in order specified in the .par file, top-to-bottom. So all rules of the currently visible slots on the character are evaluated first (top-to-bottom), then all rules of the currently selected parts on the visible character are evaluated, based on their slot order, also top-to-bottom.
For tips on actually creating rules, see this section.
Keywords
Keywords are properties that allow you to stuff arbitrary string data into a slot, part, layer, or piece. HSL script have access to these, so feel free to use keywords to add whatever data your UI needs. The syntax is as follows:
Keyword=whateverKeywordDataYouWantHere
The only restriction on the string on the right side of the = is that it doesn't have an = in it.
As with all settings, a piece inherits its layer's keyword if the piece doesn't have its own override. Likewise, a part also inherits its slot's keyword if the part doesn't have one specified.
An example keyword might be:
Keyword=wearable,category:headwear
Again, keywords are simply data that you would pass along to HSL scripts that need it. This is a utility for your UI designers to interface with the intentions of the artists. Work with the UI designer/implementors on what your available keywords should be.
Keywords are accessed in HSL scripts using any of the following flavors of GetKeyword
:
GetSlotKeyword(character as NodeRef, slot as String) as String GetPartKeyword(character as NodeRef, slot as String, part as String) as String GetLayerKeyword(character as NodeRef, bankName as String, layerName as String) as String GetPieceKeyword(character as NodeRef, bankName as String, layerName as String, pieceName as String) as String GetFaceShapeControlKeyword(character as NodeRef, control as Int) as String GetPieceKeyword(character as NodeRef, bankName as String, layerName as String, pieceName as String) as String GetFaceMorphKeyword(characters as NodeRef, morph as String) as String
See Technical:Character Functions for more information on the above functions.
Tips
Designing Rules
The main aim of rules is preventing visual artifacts, like polygon penetration. This section will help you determine what rules to write to accomplish what you want to do.
Here are some quick rules of thumb to use when trying to figure out what rules to use:
- substitutes() is primarily used for
- swapping in a part that's specified as an alternate, or
- making one or several (but not all) parts in a slot unavailable when a certain part or slot is selected
- hides() is your primary tool for selectively disabling a complete slot based on a slot or part being visible
- shows() is your primary tool for selectively enabling a complete slot based on a slot or part being visible
- If you have a slot that will absolutely not work with another slot, use this
- onif() is used to specify that a slot is completely dependent on another one
- For example, a Left Shoe slot should have an onif(Lower Left Leg) rule so you don't have a floating shoe if the Lower Left Leg slot became unavailable.
- onif() will pretty much only be used by slots and parts that are ornamentation, like tassels hanging from a skirt.
Reducing Numbers of Rules
If a majority of the parts in a slot feature the same hides() rule, try instead using hides() on the slot and shows() on the few parts that actually need the slot, like so:
Hat: Baseball cap,baseball_cap.hgm % hides(Ponytail) Hat: Do-rag,do_rag.hgm % hides(Ponytail) Hat: Cowboy,cowboy_hat.hgm Hat: Astronaut Helment,astronaut_helmet.hgm % hides(Ponytail)
would become
[Slots] Hat % hides(Ponytail) [Parts] Hat: Baseball Cap,baseball_cap.hgm ! ...all parts that hide the ponytail no longer need a hides rule Hat: Cowboy,cowboy_hat.hgm % shows(Ponytail)