Skip to content

Commit a5d08b9

Browse files
committed
Add shader replacement to sd file
1 parent 848b9fa commit a5d08b9

File tree

3 files changed

+78
-11
lines changed

3 files changed

+78
-11
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,44 @@ method to provide different textures for different engines/wagons as only one co
480480
needed, reducing install size and simplifying installation as users don't need to move/copy/edit any
481481
shape files.
482482

483+
.. index::
484+
single: ESD_ORTSShaderReplacement
485+
486+
Shader Replacement
487+
''''''''''''''''''
488+
489+
Similarly, it may be desired to replace the shaders used by a shape file in order to, for example, allow
490+
transparency to be applied to the shape and "alpha out" certain components. To change the shaders, add
491+
``ESD_ORTSShaderReplacement ( id ShaderName )`` where "id" is the integer index of the shader, starting from
492+
0, and "ShaderName" is the name of the new shader to use at this index. If an invalid shader index is given
493+
(eg: a negative number, or a number bigger than the max index), then a warning will be added to the log
494+
and the missing index will be skipped. Determining the order of shaders generally requires decompressing the
495+
shape file and looking at the ``shader_names`` block near the top of the file. The ``named_shader`` at the
496+
top of the list has an index of 0, the next one down has an index of 1, and so on. The accepted shader names are
497+
``Tex`` (fullbright), ``TexDiff`` (diffuse lighting), ``BlendATex`` (fullbright with transparency), ``BlendATextDiff``
498+
(diffuse with transparency), ``AddATex`` (fullbright with x-ray transparency), ``AddATexDiff`` (diffuse with x-ray
499+
transparency), if an invalid shader name is given a warning will be added to the log.
500+
501+
For example, the US2BSignal2.s shape included with Marias Pass uses one shader, the ``TexDiff`` shader. This
502+
disallows transparency. If, for any reason, transparency were desired on this shape, the shape descriptor file
503+
could be edited as follows::
504+
505+
SIMISA@@@@@@@@@@JINX0t1t______
506+
507+
shape ( US2BSignal2.s
508+
ESD_Detail_Level ( 0 )
509+
ESD_Alternative_Texture ( 0 )
510+
511+
Comment ( Change the first, and only, shader to allow for transparency. )
512+
ESD_ORTSShaderReplacement ( 0 "BlendATexDiff" )
513+
)
514+
515+
516+
Like replacing textures, if multiple shaders are to be modified, all can be added in a single ``ESD_ORTSShaderReplacement``
517+
parameter by specifying additional pairs of indices and shader names. Note that changing shaders in this manner will
518+
change the shader for *all* sub objects linked to that shader. Changing the shader of an individual sub object from
519+
inside the .sd file is impractical, so an alternate method may be required if additional specificity is desired.
520+
483521
Translation Matrix Modification
484522
'''''''''''''''''''''''''''''''
485523

Source/Orts.Formats.Msts/ShapeDescriptorFile.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ public SDShape(STFReader stf)
8686
new STFReader.TokenProcessor("esd_ortsbellanimationfps", ()=>{ ESD_CustomAnimationFPS = stf.ReadFloatBlock(STFReader.UNITS.Frequency, null); }),
8787
new STFReader.TokenProcessor("esd_ortscustomanimationfps", ()=>{ ESD_CustomAnimationFPS = stf.ReadFloatBlock(STFReader.UNITS.Frequency, null); }),
8888
new STFReader.TokenProcessor("esd_ortstexturereplacement", ()=>{ ParseReplacementStrings(stf, ref ESD_TextureReplacement); }),
89+
new STFReader.TokenProcessor("esd_ortsshaderreplacement", ()=>{
90+
stf.MustMatch("(");
91+
// Allow for multiple pairs of replaced and replacement values
92+
while (!stf.EndOfBlock())
93+
{
94+
int replacedIdx = stf.ReadInt(-1);
95+
string replacement = stf.ReadString();
96+
// Add pair of values so long as we haven't reached the end of block
97+
if (!string.IsNullOrEmpty(replacement) && !ESD_ShaderReplacement.ContainsKey(replacedIdx))
98+
ESD_ShaderReplacement.Add(replacedIdx, replacement);
99+
}
100+
}),
89101
new STFReader.TokenProcessor("esd_ortsmatrixrename", ()=>{ ParseReplacementStrings(stf, ref ESD_MatrixRename); }),
90102
new STFReader.TokenProcessor("esd_ortsmatrixparent", ()=>{ ParseReplacementStrings(stf, ref ESD_MatrixParent); }),
91103
new STFReader.TokenProcessor("esd_ortsmatrixtranslation", ()=>{ ParseMatrixOverride(STFReader.UNITS.Distance, stf, ref ESD_MatrixTranslation); }),
@@ -96,11 +108,11 @@ public SDShape(STFReader stf)
96108
// Allow for multiple pairs of replaced and replacement values
97109
while (!stf.EndOfBlock())
98110
{
99-
int replaced = stf.ReadInt(null);
111+
int replacedIdx = stf.ReadInt(null);
100112
float replacement = stf.ReadFloat(STFReader.UNITS.Distance, null);
101113
// Add pair of values so long as we haven't reached the end of block
102-
if (replacement != 0)
103-
ESD_LODOverride.Add(replaced, replacement);
114+
if (replacement != 0 && !ESD_LODOverride.ContainsKey(replacedIdx))
115+
ESD_LODOverride.Add(replacedIdx, replacement);
104116
}
105117
}),
106118
});
@@ -127,6 +139,8 @@ public SDShape(STFReader stf)
127139
public float ESD_CustomAnimationFPS = 8;
128140
// Dictionary of <original texture name, replacement texture name>
129141
public Dictionary<string, string> ESD_TextureReplacement = new Dictionary<string, string>();
142+
// Dictionary of <shader index, shader name>
143+
public Dictionary<int, string> ESD_ShaderReplacement = new Dictionary<int, string>();
130144
// Dictionary of <original matrix name, replacement matrix name>
131145
public Dictionary<string, string> ESD_MatrixRename = new Dictionary<string, string>();
132146
// Dictionary of <matrix name, new matrix parent name>
@@ -152,22 +166,23 @@ protected void ParseReplacementStrings(STFReader stf, ref Dictionary<string, str
152166
string replaced = stf.ReadString();
153167
string replacement = stf.ReadString();
154168
// Add pair of values so long as we haven't reached the end of block
155-
if (replaced != ")" && replacement != ")")
169+
if (replaced != ")" && replacement != ")" && !renamePairs.ContainsKey(replaced))
156170
renamePairs.Add(replaced, replacement);
157171
}
158172
}
159173

160174
// Handle matrix adjustment parameters
161175
protected void ParseMatrixOverride(STFReader.UNITS units, STFReader stf, ref Dictionary<string, Vector3> matrixParams)
162176
{
163-
Vector3 data = new Vector3(0);
177+
Vector3 data = Vector3.Zero;
164178

165179
stf.MustMatch("(");
166180
string matName = stf.ReadString();
167181
data = stf.ReadVector3(units, Vector3.Zero);
168182
stf.SkipRestOfBlock();
169183

170-
matrixParams.Add(matName, data);
184+
if (!matrixParams.ContainsKey(matName))
185+
matrixParams.Add(matName, data);
171186
}
172187
}
173188

Source/RunActivity/Viewer3D/Shapes.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2145,8 +2145,8 @@ void LoadContent()
21452145
SoundFileName = sdFile.shape.ESD_SoundFileName;
21462146
CustomAnimationFPS = sdFile.shape.ESD_CustomAnimationFPS;
21472147

2148-
// Replace textures as defined in the sd file
2149-
foreach (string tex in sdFile.shape.ESD_TextureReplacement.Keys)
2148+
// Replace textures as defined in the .sd file
2149+
foreach (KeyValuePair<string, string> texSwap in sdFile.shape.ESD_TextureReplacement)
21502150
{
21512151
bool found = false;
21522152

@@ -2155,16 +2155,30 @@ void LoadContent()
21552155
// Check if shape uses one of the textures we want to replace
21562156
// Ignore case, ignore file extension
21572157
if (Path.GetFileNameWithoutExtension(sFile.shape.images[i].ToLower()) ==
2158-
Path.GetFileNameWithoutExtension(tex.ToLower()))
2158+
Path.GetFileNameWithoutExtension(texSwap.Key.ToLower()))
21592159
{
2160-
sFile.shape.images[i] = sdFile.shape.ESD_TextureReplacement[tex];
2160+
sFile.shape.images[i] = texSwap.Value;
21612161
found = true;
21622162
}
21632163
}
21642164

21652165
if (!found)
21662166
Trace.TraceWarning("Shape descriptor file {0} specifies texture {1} to be replaced, " +
2167-
"but shape {2} does not contain this texture.", DescriptorPath, tex, filePath);
2167+
"but shape {2} does not contain this texture.", DescriptorPath, texSwap.Key, filePath);
2168+
}
2169+
2170+
// Replace shaders as defined in the .sd file
2171+
foreach (KeyValuePair<int, string> shaderSwap in sdFile.shape.ESD_ShaderReplacement)
2172+
{
2173+
if (shaderSwap.Key >= 0 && shaderSwap.Key < sFile.shape.shader_names.Count)
2174+
{
2175+
sFile.shape.shader_names[shaderSwap.Key] = shaderSwap.Value;
2176+
}
2177+
else
2178+
{
2179+
Trace.TraceWarning("Shape descriptor file {0} specifies shader index {1} to be replaced, " +
2180+
"but shape {2} does not have this many shaders.", DescriptorPath, shaderSwap.Key, filePath);
2181+
}
21682182
}
21692183

21702184
int[] modifiedHierarchy = null;

0 commit comments

Comments
 (0)