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