예제 #1
0
        public GenericGraphicResource RequestGraphicResource(string path, bool async = false)
        {
            GenericGraphicResource resource;
            if (!cachedGraphics.TryGetValue(path, out resource)) {
#if UNCOMPRESSED_CONTENT
                string pathAbsolute = PathOp.Combine(DualityApp.DataDirectory, "Animations", path);
#else
                string pathAbsolute = PathOp.Combine(DualityApp.DataDirectory, "Main.dz", "Animations", path);
#endif

                SpriteJson json;
                using (Stream s = FileOp.Open(pathAbsolute + ".res", FileAccessMode.Read)) {
                    lock (jsonParser) {
                        json = jsonParser.Parse<SpriteJson>(s);
                    }
                }

                resource = new GenericGraphicResource {
                    FrameDimensions = new Point2(json.FrameSize[0], json.FrameSize[1]),
                    FrameConfiguration = new Point2(json.FrameConfiguration[0], json.FrameConfiguration[1]),
                    FrameDuration = (json.FrameRate <= 0 ? -1 : (1f / json.FrameRate) * 5),
                    FrameCount = json.FrameCount
                };

                if (json.Hotspot != null) {
                    resource.Hotspot = new Point2(json.Hotspot[0], json.Hotspot[1]);
                }

                if (json.Coldspot != null) {
                    resource.Coldspot = new Point2(json.Coldspot[0], json.Coldspot[1]);
                    resource.HasColdspot = true;
                }

                if (json.Gunspot != null) {
                    resource.Gunspot = new Point2(json.Gunspot[0], json.Gunspot[1]);
                }

                PixelData pixelData;
                using (Stream s = FileOp.Open(pathAbsolute, FileAccessMode.Read)) {
                    pixelData = new Png(s).GetPixelData();
                }

                // Use external palette
                if ((json.Flags & 0x01) != 0x00) {
                    ColorRgba[] palette = paletteTexture.Res.BasePixmap.Res.MainLayer.Data;

                    ColorRgba[] data = pixelData.Data;
#if !DISABLE_ASYNC
                    Parallel.ForEach(Partitioner.Create(0, data.Length), range => {
                        for (int i = range.Item1; i < range.Item2; i++) {
#else
                        for (int i = 0; i < data.Length; i++) {
#endif

                            int colorIdx = data[i].R;
                            data[i] = palette[colorIdx].WithAlpha(palette[colorIdx].A * data[i].A / (255f * 255f));

                            // ToDo: Pinball sprites have strange palette (1-3 indices down), CandionV looks bad, other levels look different
                        }
#if !DISABLE_ASYNC
                    });
#endif
                }

                bool linearSampling = (json.Flags & 0x02) != 0x00;

                Pixmap map = new Pixmap(pixelData);
                map.GenerateAnimAtlas(resource.FrameConfiguration.X, resource.FrameConfiguration.Y, 0);
                if (async) {
                    GenericGraphicResourceAsyncFinalize asyncFinalize = new GenericGraphicResourceAsyncFinalize();
                    asyncFinalize.TextureMap = map;

#if !DISABLE_NORMAL_MAPPING
                    string filenameNormal = pathAbsolute.Replace(".png", ".n.png");
                    if (FileOp.Exists(filenameNormal)) {
                        using (Stream s = FileOp.Open(filenameNormal, FileAccessMode.Read)) {
                            asyncFinalize.TextureNormalMap = new Pixmap(new Png(s).GetPixelData());
                        }
                    } else {
                        resource.TextureNormal = defaultNormalMap;
                    }
#else
                    resource.TextureNormal = defaultNormalMap;
#endif

                    asyncFinalize.LinearSampling = linearSampling;

                    resource.AsyncFinalize = asyncFinalize;
                } else {
                    TextureMagFilter magFilter; TextureMinFilter minFilter;
                    if (linearSampling) {
                        magFilter = TextureMagFilter.Linear;
                        minFilter = TextureMinFilter.LinearMipmapLinear;
                    } else {
                        magFilter = TextureMagFilter.Nearest;
                        minFilter = TextureMinFilter.Nearest;
                    }

                    resource.Texture = new Texture(map, TextureSizeMode.NonPowerOfTwo,
                        magFilter, minFilter, json.TextureWrap, json.TextureWrap);

#if !DISABLE_NORMAL_MAPPING
                    string filenameNormal = pathAbsolute.Replace(".png", ".n.png");
                    if (FileOp.Exists(filenameNormal)) {
                        using (Stream s = FileOp.Open(filenameNormal, FileAccessMode.Read)) {
                            pixelData = new Png(s).GetPixelData();
                        }

                        resource.TextureNormal = new Texture(new Pixmap(pixelData), TextureSizeMode.NonPowerOfTwo,
                            magFilter, minFilter, json.TextureWrap, json.TextureWrap);

                        resource.TextureNormal.Res.DetachSource();
                    } else {
                        resource.TextureNormal = defaultNormalMap;
                    }
#else
                    resource.TextureNormal = defaultNormalMap;
#endif
                }

                cachedGraphics[path] = resource;
            }

            resource.Referenced = true;
            return resource;
        }