public void ResetAnimationData() { var lastMobMode = MobMode; switch (LocationDetails.MovementType) { case eMovementType.Stopped: MobMode = eMobMode.PlayerTownNeutral; break; case eMovementType.Walking: MobMode = eMobMode.PlayerTownWalk; break; case eMovementType.Running: MobMode = eMobMode.PlayerRun; break; default: MobMode = eMobMode.PlayerNeutral; break; } if (lastMobMode != MobMode) { renderFrameIndex = 0; } currentDirectionCache = directionCache.FirstOrDefault(x => x.MobMode == MobMode && x.Direction == directionConversion[LocationDetails.MovementDirection]); if (currentDirectionCache != null) { return; } animationData = resourceManager.GetPlayerAnimation(Hero, MobMode, Equipment); if (animationData == null) { throw new OpenDiablo2Exception("Could not locate animation for the character!"); } var palette = paletteProvider.PaletteTable["Units"]; CacheFrames(animationData.Layers.Select(layer => resourceManager.GetPlayerDCC(layer, Equipment, palette)).ToArray()); }
private unsafe void CacheFrames(MPQDCC[] layerData) { var directionCache = new DirectionCacheItem { MobMode = MobMode, Direction = directionConversion[LocationDetails.MovementDirection] }; var palette = paletteProvider.PaletteTable[Palettes.Units]; var dirAnimation = animationData.Animations[0]; directionCache.FramesToAnimate = dirAnimation.FramesPerDirection; directionCache.AnimationSpeed = dirAnimation.AnimationSpeed; var minX = Int32.MaxValue; var minY = Int32.MaxValue; var maxX = Int32.MinValue; var maxY = Int32.MinValue; var layersIgnored = 0; foreach (var layer in layerData) { if (layer == null) { layersIgnored++; continue; } minX = Math.Min(minX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Left); minY = Math.Min(minY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Top); maxX = Math.Max(maxX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Right); maxY = Math.Max(maxY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Bottom); } if (layersIgnored > 0) { log.Warn($"{layersIgnored} animation layer(s) were not found!"); } var frameW = (maxX - minX); var frameH = (maxY - minY); directionCache.SpriteTexture = new IntPtr[directionCache.FramesToAnimate]; directionCache.SpriteRect = new SDL.SDL_Rect[directionCache.FramesToAnimate]; for (var frameIndex = 0; frameIndex < directionCache.FramesToAnimate; frameIndex++) { var texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, frameW, frameH); SDL.SDL_LockTexture(texture, IntPtr.Zero, out IntPtr pixels, out int pitch); UInt32 *data = (UInt32 *)pixels; var priorityBase = (directionConversion[LocationDetails.MovementDirection] * animationData.FramesPerDirection * animationData.NumberOfLayers) + (frameIndex * animationData.NumberOfLayers); for (var i = 0; i < animationData.NumberOfLayers; i++) { var comp = animationData.Priority[priorityBase + i]; if (!animationData.CompositLayers.ContainsKey(comp)) { continue; } var layer = layerData[animationData.CompositLayers[comp]]; if (layer == null) { continue; // TODO: This is most likely not ok } var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]]; var frame = direction.Frames[frameIndex]; for (var y = 0; y < direction.Box.Height; y++) { for (var x = 0; x < direction.Box.Width; x++) { var paletteIndex = frame.PixelData[x + (y * direction.Box.Width)]; if (paletteIndex == 0) { continue; } var color = palette.Colors[paletteIndex]; var actualX = x + direction.Box.X - minX; var actualY = y + direction.Box.Y - minY; data[actualX + (actualY * (pitch / 4))] = color; } } } SDL.SDL_UnlockTexture(texture); SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND); directionCache.SpriteTexture[frameIndex] = texture; directionCache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH }; this.directionCache.Add(directionCache); } currentDirectionCache = directionCache; }