[1114] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using Oni.Imaging;
|
---|
| 4 |
|
---|
| 5 | namespace Oni.Akira
|
---|
| 6 | {
|
---|
| 7 | internal class MaterialLibrary
|
---|
| 8 | {
|
---|
| 9 | private readonly MarkerMaterials markers = new MarkerMaterials();
|
---|
| 10 | private readonly Dictionary<string, Material> materials = new Dictionary<string, Material>(StringComparer.OrdinalIgnoreCase);
|
---|
| 11 | private Material notFound;
|
---|
| 12 |
|
---|
| 13 | #region internal class MarkerMaterials
|
---|
| 14 |
|
---|
| 15 | internal class MarkerMaterials
|
---|
| 16 | {
|
---|
| 17 | private Material ghost;
|
---|
| 18 | private Material stairs;
|
---|
| 19 | private Material door;
|
---|
| 20 | private Material danger;
|
---|
| 21 | private Material barrier;
|
---|
| 22 | private Material impassable;
|
---|
| 23 | private Material blackness;
|
---|
| 24 | private Material floor;
|
---|
| 25 |
|
---|
| 26 | public Material GetMarker(string name)
|
---|
| 27 | {
|
---|
| 28 | EnsureMaterials();
|
---|
| 29 |
|
---|
| 30 | switch (name)
|
---|
| 31 | {
|
---|
| 32 | case "_marker_door":
|
---|
| 33 | return door;
|
---|
| 34 | case "_marker_ghost":
|
---|
| 35 | return ghost;
|
---|
| 36 | case "_marker_stairs":
|
---|
| 37 | return stairs;
|
---|
| 38 | case "_marker_danger":
|
---|
| 39 | return danger;
|
---|
| 40 | case "_marker_barrier":
|
---|
| 41 | return barrier;
|
---|
| 42 | case "_marker_impassable":
|
---|
| 43 | return impassable;
|
---|
| 44 | case "_marker_blackness":
|
---|
| 45 | return blackness;
|
---|
| 46 | case "_marker_floor":
|
---|
| 47 | return floor;
|
---|
| 48 | default:
|
---|
| 49 | return null;
|
---|
| 50 | }
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | public Material GetMarker(Polygon polygon)
|
---|
| 54 | {
|
---|
| 55 | EnsureMaterials();
|
---|
| 56 |
|
---|
| 57 | var flags = polygon.Flags & ~(GunkFlags.ProjectionBit0 | GunkFlags.ProjectionBit1 | GunkFlags.Horizontal | GunkFlags.Vertical);
|
---|
| 58 | var adjacencyFlags = GunkFlags.Ghost | GunkFlags.StairsUp | GunkFlags.StairsDown;
|
---|
| 59 |
|
---|
| 60 | if ((flags & (GunkFlags.DoorFrame | adjacencyFlags)) == GunkFlags.DoorFrame)
|
---|
| 61 | return door;
|
---|
| 62 |
|
---|
| 63 | if ((flags & adjacencyFlags) != 0)
|
---|
| 64 | return ghost;
|
---|
| 65 |
|
---|
| 66 | if ((flags & GunkFlags.Invisible) != 0)
|
---|
| 67 | {
|
---|
| 68 | flags &= ~GunkFlags.Invisible;
|
---|
| 69 |
|
---|
| 70 | if ((flags & GunkFlags.Danger) != 0)
|
---|
| 71 | return danger;
|
---|
| 72 |
|
---|
| 73 | if ((flags & GunkFlags.Stairs) != 0)
|
---|
| 74 | return stairs;
|
---|
| 75 |
|
---|
| 76 | if ((flags & (GunkFlags.NoObjectCollision | GunkFlags.NoCharacterCollision)) == GunkFlags.NoObjectCollision)
|
---|
| 77 | return barrier;
|
---|
| 78 |
|
---|
| 79 | if ((flags & (GunkFlags.NoObjectCollision | GunkFlags.NoCharacterCollision | GunkFlags.NoCollision)) == 0)
|
---|
| 80 | return impassable;
|
---|
| 81 |
|
---|
| 82 | //
|
---|
| 83 | // What's the point of a invisible and no collision polygon?!
|
---|
| 84 | //
|
---|
| 85 |
|
---|
| 86 | if ((flags & GunkFlags.NoCollision) != 0)
|
---|
| 87 | return null;
|
---|
| 88 |
|
---|
| 89 | Console.Error.WriteLine("Unknown invisible material, fix tool: {0}", flags);
|
---|
| 90 | }
|
---|
| 91 | else
|
---|
| 92 | {
|
---|
| 93 | if ((flags & (GunkFlags.TwoSided | GunkFlags.NoCollision)) == (GunkFlags.TwoSided | GunkFlags.NoCollision)
|
---|
| 94 | && polygon.Material != null
|
---|
| 95 | && polygon.Material.Name == "BLACKNESS")
|
---|
| 96 | {
|
---|
| 97 | return blackness;
|
---|
| 98 | }
|
---|
| 99 | }
|
---|
| 100 |
|
---|
| 101 | return null;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | private void EnsureMaterials()
|
---|
| 105 | {
|
---|
| 106 | if (ghost != null)
|
---|
| 107 | return;
|
---|
| 108 |
|
---|
| 109 | CreateGhost();
|
---|
| 110 | CreateBarrier();
|
---|
| 111 | CreateDanger();
|
---|
| 112 | CreateDoor();
|
---|
| 113 | CreateStairs();
|
---|
| 114 | CreateImpassable();
|
---|
| 115 | CreateBlackness();
|
---|
| 116 | CreateFloor();
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | private void CreateBarrier()
|
---|
| 120 | {
|
---|
| 121 | var surface = new Surface(128, 128);
|
---|
| 122 |
|
---|
| 123 | var fill = new Color(0, 240, 20, 180);
|
---|
| 124 | var sign = new Color(240, 20, 0, 255);
|
---|
| 125 |
|
---|
| 126 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 127 |
|
---|
| 128 | surface.Fill(0, 0, 128, 1, sign);
|
---|
| 129 | surface.Fill(0, 127, 128, 1, sign);
|
---|
| 130 | surface.Fill(0, 1, 1, 126, sign);
|
---|
| 131 | surface.Fill(127, 1, 1, 126, sign);
|
---|
| 132 | surface.Fill(64, 1, 1, 126, sign);
|
---|
| 133 | surface.Fill(1, 64, 126, 1, sign);
|
---|
| 134 |
|
---|
| 135 | barrier = new Material("_marker_barrier", true)
|
---|
| 136 | {
|
---|
| 137 | Flags = GunkFlags.NoObjectCollision | GunkFlags.Invisible,
|
---|
| 138 | Image = surface
|
---|
| 139 | };
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | private void CreateImpassable()
|
---|
| 143 | {
|
---|
| 144 | var surface = new Surface(128, 128);
|
---|
| 145 |
|
---|
| 146 | var fill = new Color(240, 0, 20, 180);
|
---|
| 147 | var sign = new Color(240, 20, 0, 255);
|
---|
| 148 |
|
---|
| 149 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 150 |
|
---|
| 151 | surface.Fill(0, 0, 128, 1, sign);
|
---|
| 152 | surface.Fill(0, 127, 128, 1, sign);
|
---|
| 153 | surface.Fill(0, 1, 1, 126, sign);
|
---|
| 154 | surface.Fill(127, 1, 1, 126, sign);
|
---|
| 155 | surface.Fill(64, 1, 1, 126, sign);
|
---|
| 156 | surface.Fill(1, 64, 126, 1, sign);
|
---|
| 157 |
|
---|
| 158 | impassable = new Material("_marker_impassable", true)
|
---|
| 159 | {
|
---|
| 160 | Flags = GunkFlags.Invisible,
|
---|
| 161 | Image = surface
|
---|
| 162 | };
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | private void CreateGhost()
|
---|
| 166 | {
|
---|
| 167 | var surface = new Surface(128, 128);
|
---|
| 168 |
|
---|
| 169 | var border = new Color(16, 48, 240, 240);
|
---|
| 170 | var fill = new Color(208, 240, 240, 80);
|
---|
| 171 |
|
---|
| 172 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 173 |
|
---|
| 174 | surface.Fill(0, 0, 128, 1, border);
|
---|
| 175 | surface.Fill(0, 127, 128, 1, border);
|
---|
| 176 | surface.Fill(0, 1, 1, 126, border);
|
---|
| 177 | surface.Fill(127, 1, 1, 126, border);
|
---|
| 178 | surface.Fill(64, 1, 1, 126, border);
|
---|
| 179 | surface.Fill(1, 64, 126, 1, border);
|
---|
| 180 |
|
---|
| 181 | ghost = new Material("_marker_ghost", true);
|
---|
| 182 | ghost.Flags = GunkFlags.Ghost | GunkFlags.TwoSided | GunkFlags.Transparent | GunkFlags.NoCollision;
|
---|
| 183 | ghost.Image = surface;
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | private void CreateDoor()
|
---|
| 187 | {
|
---|
| 188 | var surface = new Surface(128, 128);
|
---|
| 189 |
|
---|
| 190 | var fill = new Color(240, 240, 0, 208);
|
---|
| 191 | var line = new Color(0, 0, 240);
|
---|
| 192 |
|
---|
| 193 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 194 |
|
---|
| 195 | surface.Fill(1, 1, 126, 1, line);
|
---|
| 196 | surface.Fill(1, 1, 1, 126, line);
|
---|
| 197 | surface.Fill(1, 126, 126, 1, line);
|
---|
| 198 | surface.Fill(126, 1, 1, 126, line);
|
---|
| 199 |
|
---|
| 200 | door = new Material("_marker_door", true)
|
---|
| 201 | {
|
---|
| 202 | Flags = GunkFlags.DoorFrame | GunkFlags.TwoSided | GunkFlags.Transparent | GunkFlags.NoCollision,
|
---|
| 203 | Image = surface
|
---|
| 204 | };
|
---|
| 205 | }
|
---|
| 206 |
|
---|
| 207 | private void CreateDanger()
|
---|
| 208 | {
|
---|
| 209 | var surface = new Surface(128, 128);
|
---|
| 210 |
|
---|
| 211 | var fill = new Color(255, 10, 0, 208);
|
---|
| 212 | var sign = new Color(255, 255, 255, 255);
|
---|
| 213 |
|
---|
| 214 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 215 | surface.Fill(52, 16, 24, 64, sign);
|
---|
| 216 | surface.Fill(52, 96, 24, 16, sign);
|
---|
| 217 |
|
---|
| 218 | danger = new Material("_marker_danger", true)
|
---|
| 219 | {
|
---|
| 220 | Flags = GunkFlags.Danger | GunkFlags.Invisible | GunkFlags.NoCollision | GunkFlags.NoOcclusion,
|
---|
| 221 | Image = surface
|
---|
| 222 | };
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | private void CreateStairs()
|
---|
| 226 | {
|
---|
| 227 | var surface = new Surface(128, 128);
|
---|
| 228 |
|
---|
| 229 | var fill = new Color(40, 240, 0, 180);
|
---|
| 230 | var step = new Color(40, 0, 240, 180);
|
---|
| 231 |
|
---|
| 232 | surface.Fill(0, 0, 128, 128, fill);
|
---|
| 233 |
|
---|
| 234 | for (int y = 0; y < surface.Height; y += 32)
|
---|
| 235 | surface.Fill(0, y, surface.Width, 16, step);
|
---|
| 236 |
|
---|
| 237 | stairs = new Material("_marker_stairs", true)
|
---|
| 238 | {
|
---|
| 239 | Flags = GunkFlags.Stairs | GunkFlags.Invisible | GunkFlags.NoObjectCollision | GunkFlags.TwoSided,
|
---|
| 240 | Image = surface
|
---|
| 241 | };
|
---|
| 242 | }
|
---|
| 243 |
|
---|
| 244 | private void CreateBlackness()
|
---|
| 245 | {
|
---|
| 246 | var surface = new Surface(16, 16, SurfaceFormat.BGRX);
|
---|
| 247 |
|
---|
| 248 | surface.Fill(0, 0, 16, 16, Color.Black);
|
---|
| 249 |
|
---|
| 250 | blackness = new Material("_marker_blackness", true)
|
---|
| 251 | {
|
---|
| 252 | Flags = GunkFlags.TwoSided | GunkFlags.NoCollision,
|
---|
| 253 | Image = surface
|
---|
| 254 | };
|
---|
| 255 | }
|
---|
| 256 |
|
---|
| 257 | private void CreateFloor()
|
---|
| 258 | {
|
---|
| 259 | var surface = new Surface(256, 256);
|
---|
| 260 |
|
---|
| 261 | surface.Fill(0, 0, 16, 16, Color.White);
|
---|
| 262 |
|
---|
| 263 | for (int x = 0; x < 256; x += 4)
|
---|
| 264 | {
|
---|
| 265 | surface.Fill(x, 0, 1, 256, Color.Black);
|
---|
| 266 | surface.Fill(0, x, 256, 1, Color.Black);
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 | floor = new Material("_marker_floor", true)
|
---|
| 270 | {
|
---|
| 271 | Flags = GunkFlags.NoCollision,
|
---|
| 272 | Image = surface
|
---|
| 273 | };
|
---|
| 274 | }
|
---|
| 275 |
|
---|
| 276 | public Material Barrier
|
---|
| 277 | {
|
---|
| 278 | get
|
---|
| 279 | {
|
---|
| 280 | EnsureMaterials();
|
---|
| 281 | return barrier;
|
---|
| 282 | }
|
---|
| 283 | }
|
---|
| 284 |
|
---|
| 285 | public Material Ghost
|
---|
| 286 | {
|
---|
| 287 | get
|
---|
| 288 | {
|
---|
| 289 | EnsureMaterials();
|
---|
| 290 | return ghost;
|
---|
| 291 | }
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 | public Material Danger
|
---|
| 295 | {
|
---|
| 296 | get
|
---|
| 297 | {
|
---|
| 298 | EnsureMaterials();
|
---|
| 299 | return danger;
|
---|
| 300 | }
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | public Material DoorFrame
|
---|
| 304 | {
|
---|
| 305 | get
|
---|
| 306 | {
|
---|
| 307 | EnsureMaterials();
|
---|
| 308 | return door;
|
---|
| 309 | }
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | public Material Stairs
|
---|
| 313 | {
|
---|
| 314 | get
|
---|
| 315 | {
|
---|
| 316 | EnsureMaterials();
|
---|
| 317 | return stairs;
|
---|
| 318 | }
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | public Material Floor
|
---|
| 322 | {
|
---|
| 323 | get
|
---|
| 324 | {
|
---|
| 325 | EnsureMaterials();
|
---|
| 326 | return floor;
|
---|
| 327 | }
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | public Material Blackness
|
---|
| 331 | {
|
---|
| 332 | get
|
---|
| 333 | {
|
---|
| 334 | EnsureMaterials();
|
---|
| 335 | return blackness;
|
---|
| 336 | }
|
---|
| 337 | }
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | #endregion
|
---|
| 341 |
|
---|
| 342 | public MarkerMaterials Markers => markers;
|
---|
| 343 |
|
---|
| 344 | public Material NotFound
|
---|
| 345 | {
|
---|
| 346 | get
|
---|
| 347 | {
|
---|
| 348 | if (notFound == null)
|
---|
| 349 | notFound = GetMaterial("notfoundtex");
|
---|
| 350 |
|
---|
| 351 | return notFound;
|
---|
| 352 | }
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | public IEnumerable<Material> All => materials.Values;
|
---|
| 356 |
|
---|
| 357 | public Material GetMaterial(string name)
|
---|
| 358 | {
|
---|
| 359 | Material material;
|
---|
| 360 |
|
---|
| 361 | if (!materials.TryGetValue(name, out material))
|
---|
| 362 | {
|
---|
| 363 | material = markers.GetMarker(name);
|
---|
| 364 |
|
---|
| 365 | if (material == null)
|
---|
| 366 | material = new Material(name);
|
---|
| 367 |
|
---|
| 368 | materials.Add(name, material);
|
---|
| 369 | }
|
---|
| 370 |
|
---|
| 371 | if (name.StartsWith("lmap_", StringComparison.OrdinalIgnoreCase))
|
---|
| 372 | {
|
---|
| 373 | material.Flags |= GunkFlags.NoCollision | GunkFlags.NoOcclusion | GunkFlags.SoundTransparent;
|
---|
| 374 | }
|
---|
| 375 |
|
---|
| 376 | return material;
|
---|
| 377 | }
|
---|
| 378 | }
|
---|
| 379 | }
|
---|