Skip to content

Commit 7b583b7

Browse files
committed
refactor: Simplify loading game textures
1 parent 65ef2f9 commit 7b583b7

File tree

1 file changed

+42
-95
lines changed

1 file changed

+42
-95
lines changed

Source/RunActivity/Viewer3D/Materials.cs

Lines changed: 42 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ namespace Orts.Viewer3D
3838
[CallOnThread("Loader")]
3939
public class SharedTextureManager
4040
{
41+
const int MaxSelectorDirectoryNames = 5;
42+
readonly HashSet<string> SelectorDirectoryNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
43+
"Autumn",
44+
"AutumnSnow",
45+
"Snow",
46+
"Spring",
47+
"SpringSnow",
48+
"Winter",
49+
"WinterSnow",
50+
};
51+
4152
readonly Viewer Viewer;
4253
readonly GraphicsDevice GraphicsDevice;
4354
Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>();
@@ -52,123 +63,59 @@ internal SharedTextureManager(Viewer viewer, GraphicsDevice graphicsDevice)
5263

5364
public Texture2D Get(string path, bool required = false)
5465
{
55-
return (Get(path, SharedMaterialManager.MissingTexture, required));
66+
return Get(path, SharedMaterialManager.MissingTexture, required);
5667
}
5768

5869
public Texture2D Get(string path, Texture2D defaultTexture, bool required = false)
5970
{
6071
if (Thread.CurrentThread.Name != "Loader Process")
6172
Trace.TraceError("SharedTextureManager.Get incorrectly called by {0}; must be Loader Process or crashes will occur.", Thread.CurrentThread.Name);
6273

63-
if (path == null || path == "")
64-
return defaultTexture;
74+
if (string.IsNullOrEmpty(path)) return defaultTexture;
6575

6676
path = path.ToLowerInvariant();
67-
if (!Textures.ContainsKey(path))
77+
if (Textures.ContainsKey(path)) return Textures[path];
78+
79+
// DO NOT add additional formats here without explicit approval
80+
// - DDS is used for newer, Open Rails-specific content
81+
// - ACE is used for older, MSTS-specific content
82+
switch (Path.GetExtension(path))
6883
{
69-
try
70-
{
71-
Texture2D texture;
72-
if (Path.GetExtension(path) == ".dds")
84+
case ".dds":
85+
case ".ace":
86+
try
7387
{
74-
if (File.Exists(path))
75-
{
76-
DDSLib.DDSFromFile(path, GraphicsDevice, true, out texture);
77-
}
78-
else
79-
// This solves the case where the global shapes have been overwritten and point to .dds textures
80-
// therefore avoiding that routes providing .ace textures show blank global shapes
88+
var levelPath = path;
89+
for (var levels = 0; levels < MaxSelectorDirectoryNames; levels++)
8190
{
82-
var aceTexture = Path.ChangeExtension(path, ".ace");
83-
if (File.Exists(aceTexture))
84-
{
85-
texture = Orts.Formats.Msts.AceFile.Texture2DFromFile(GraphicsDevice, aceTexture);
86-
Trace.TraceWarning("Required texture {0} not existing; using existing texture {1}", path, aceTexture);
87-
}
88-
else return defaultTexture;
89-
}
90-
}
91-
else if (Path.GetExtension(path) == ".ace")
92-
{
93-
var alternativeTexture = Path.ChangeExtension(path, ".dds");
94-
95-
if (File.Exists(alternativeTexture))
96-
{
97-
DDSLib.DDSFromFile(alternativeTexture, GraphicsDevice, true, out texture);
98-
}
99-
else if (File.Exists(path))
100-
{
101-
texture = Orts.Formats.Msts.AceFile.Texture2DFromFile(GraphicsDevice, path);
102-
}
103-
else
104-
{
105-
Texture2D missing()
106-
{
107-
if (required)
108-
Trace.TraceWarning("Missing texture {0} replaced with default texture", path);
109-
return defaultTexture;
110-
}
111-
Texture2D invalid()
91+
var dds = Path.ChangeExtension(levelPath, ".dds");
92+
var ace = Path.ChangeExtension(levelPath, ".ace");
93+
if (File.Exists(dds))
11294
{
113-
if (required)
114-
Trace.TraceWarning("Invalid texture {0} replaced with default texture", path);
115-
return defaultTexture;
95+
DDSLib.DDSFromFile(dds, GraphicsDevice, true, out Texture2D texture);
96+
return Textures[path] = texture;
11697
}
117-
//in case of no texture in wintersnow etc, go up one level
118-
DirectoryInfo currentDir;
119-
string searchPath;
120-
try
98+
if (File.Exists(ace))
12199
{
122-
currentDir = Directory.GetParent(path);//returns the current level of dir
123-
searchPath = $"{Directory.GetParent(currentDir.FullName).FullName}\\{Path.GetFileName(path)}";
124-
}
125-
catch
126-
{
127-
return missing();
128-
}
129-
if (File.Exists(searchPath) && searchPath.ToLower().Contains("texture")) //in texture and exists
130-
{
131-
try
132-
{
133-
texture = Formats.Msts.AceFile.Texture2DFromFile(GraphicsDevice, searchPath);
134-
}
135-
catch
136-
{
137-
return invalid();
138-
}
139-
}
140-
else
141-
{
142-
return missing();
100+
return Textures[path] = Formats.Msts.AceFile.Texture2DFromFile(GraphicsDevice, ace);
143101
}
102+
// When a texture is not found, and it is in a selector directory (e.g. "Snow"), we
103+
// go up a level and try again. This repeats a fixed number of times, or until we run
104+
// out of known selector directories.
105+
var directory = Path.GetDirectoryName(levelPath);
106+
if (string.IsNullOrEmpty(directory) || !SelectorDirectoryNames.Contains(Path.GetFileName(directory))) break;
107+
levelPath = Path.Combine(Path.GetDirectoryName(directory), Path.GetFileName(levelPath));
144108
}
109+
if (required) Trace.TraceWarning("Ignored missing texture file: {0}", path);
145110
}
146-
else
111+
catch (Exception error)
147112
{
148-
Trace.TraceWarning("Unsupported texture format: {0}", path);
149-
return defaultTexture;
113+
Trace.WriteLine(new FileLoadException(path, error));
150114
}
151-
152-
Textures.Add(path, texture);
153-
return texture;
154-
}
155-
catch (InvalidDataException error)
156-
{
157-
Trace.TraceWarning("Skipped texture with error: {1} in {0}", path, error.Message);
158115
return defaultTexture;
159-
}
160-
catch (Exception error)
161-
{
162-
if (File.Exists(path))
163-
Trace.WriteLine(new FileLoadException(path, error));
164-
else
165-
Trace.TraceWarning("Ignored missing texture file {0}", path);
116+
default:
117+
Trace.TraceWarning("Ignored unsupported texture file: {0}", path);
166118
return defaultTexture;
167-
}
168-
}
169-
else
170-
{
171-
return Textures[path];
172119
}
173120
}
174121

0 commit comments

Comments
 (0)