| 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 | }
 | 
|---|