protected override void LoadDrawable(Drawable drawable) { switch (Type) { case CollectionType.Aircraft: case CollectionType.Vehicle: LoadUnitDrawable((UnitDrawable)drawable); break; case CollectionType.Building: LoadBuildingDrawable((BuildingDrawable)drawable); break; case CollectionType.Infantry: case CollectionType.Overlay: case CollectionType.Smudge: case CollectionType.Terrain: LoadSimpleDrawable((ShpDrawable)drawable); break; case CollectionType.Animation: LoadAnimDrawable((AnimDrawable)drawable); break; default: throw new InvalidEnumArgumentException(); } // overrides from the modconfig var cfgOverrides = ModConfig.ActiveConfig.ObjectOverrides.Where(ovr => // matches collection (ovr.CollectionTypes & Type) == Type && // matches collection (ovr.TheaterTypes & Theater) == Theater && // matches object regex Regex.IsMatch(drawable.Name, ovr.ObjRegex, RegexOptions.IgnoreCase)) .OrderByDescending(o => o.Priority); foreach (var cfgOverride in cfgOverrides) { Logger.Debug("Object {0} receives overrides from regex {1}", drawable.Name, cfgOverride.ObjRegex); if (cfgOverride.Lighting != LightingType.Default) drawable.Props.LightingType = cfgOverride.Lighting; if (cfgOverride.Palette != PaletteType.Default) { drawable.Props.PaletteType = cfgOverride.Palette; drawable.Props.CustomPaletteName = cfgOverride.CustomPaletteFile; } if (!string.IsNullOrWhiteSpace(cfgOverride.FrameDeciderCode) && !_cannotCompile) { try { var fdc = FrameDeciders.GetOverrideFrameDecider(cfgOverride); if (fdc != null) drawable.Props.FrameDecider = fdc; } catch (TypeLoadException exc) { _cannotCompile = true; Logger.Error("Custom framedecider could not be compiled. You need .NET 4.5 for this." + " Functionality will be unavailable.\r\n{0}", exc); } } } }
internal Palette GetPalette(Drawable drawable) { // Starkku: Altered as a part of a fix for crash that happened if custom palette was declared but file wasn't there. Palette pal = null; if (drawable.Props.PaletteType == PaletteType.Custom) { pal = _palettes.GetCustomPalette(drawable.Props.CustomPaletteName); if (pal == null) { if (drawable is BuildingDrawable || drawable is UnitDrawable) return _palettes.UnitPalette; else if (drawable is AnimDrawable) return _palettes.AnimPalette; else return _palettes.IsoPalette; } } else { pal = _palettes.GetPalette(drawable.Props.PaletteType); } return pal; }
public AnimationObject(string name, Drawable drawable) { Name = name; Drawable = drawable; }
public void AddAnimation(int subtile, Drawable drawable) { AnimationSubtile = subtile; AnimationDrawable = drawable; }
protected virtual void LoadDrawable(Drawable d) { }
unsafe public static void Draw(ShpFile shp, GameObject obj, Drawable dr, DrawProperties props, DrawingSurface ds, int transLucency = 0) { shp.Initialize(); int frameIndex = props.FrameDecider(obj); Palette p = props.PaletteOverride ?? obj.Palette; frameIndex = DecideFrameIndex(frameIndex, shp.NumImages); if (frameIndex >= shp.Images.Count) return; var img = shp.GetImage(frameIndex); var imgData = img.GetImageData(); if (imgData == null || img.Width * img.Height != imgData.Length) return; Point offset = props.GetOffset(obj); offset.X += obj.Tile.Dx * Drawable.TileWidth / 2 - shp.Width / 2 + img.X; offset.Y += (obj.Tile.Dy - obj.Tile.Z) * Drawable.TileHeight / 2 - shp.Height / 2 + img.Y; Logger.Trace("Drawing SHP file {0} (Frame {1}) at ({2},{3})", shp.FileName, frameIndex, offset.X, offset.Y); int stride = ds.BitmapData.Stride; var heightBuffer = ds.GetHeightBuffer(); var zBuffer = ds.GetZBuffer(); var w_low = (byte*)ds.BitmapData.Scan0; byte* w_high = (byte*)ds.BitmapData.Scan0 + stride * ds.BitmapData.Height; byte* w = (byte*)ds.BitmapData.Scan0 + offset.X * 3 + stride * offset.Y; // clip to 25-50-75-100 transLucency = (transLucency / 25) * 25; float a = transLucency / 100f; float b = 1 - a; int rIdx = 0; // image pixel index int zIdx = offset.X + offset.Y * ds.Width; // z-buffer pixel index short hBufVal = (short)(obj.Tile.Z * Drawable.TileHeight / 2); short zOffset = (short)((obj.BottomTile.Rx + obj.BottomTile.Ry) * Drawable.TileHeight / 2); if (!dr.Flat) hBufVal += shp.Height; for (int y = 0; y < img.Height; y++) { if (offset.Y + y < 0) { w += stride; rIdx += img.Width; zIdx += ds.Width; continue; // out of bounds } for (int x = 0; x < img.Width; x++) { byte paletteValue = imgData[rIdx]; short zshapeOffset = obj is StructureObject ? (GetBuildingZ(x, y, shp, img, obj)) : (short)0; if (paletteValue != 0) { short zBufVal = zOffset; if (dr.Flat) zBufVal += (short)(y - img.Height); else if (dr.IsBuildingPart) { // nonflat building zBufVal += zshapeOffset; } else zBufVal += img.Height; if (w_low <= w && w < w_high /*&& zBufVal >= zBuffer[zIdx]*/) { if (transLucency != 0) { *(w + 0) = (byte)(a * *(w + 0) + b * p.Colors[paletteValue].B); *(w + 1) = (byte)(a * *(w + 1) + b * p.Colors[paletteValue].G); *(w + 2) = (byte)(a * *(w + 2) + b * p.Colors[paletteValue].R); } else { *(w + 0) = p.Colors[paletteValue].B; *(w + 1) = p.Colors[paletteValue].G; *(w + 2) = p.Colors[paletteValue].R; //var pal = Theater.Active.GetPalettes().UnitPalette.Colors; //*(w + 0) = pal[zshapeOffset].R; //*(w + 1) = pal[zshapeOffset].G; //*(w + 2) = pal[zshapeOffset].B; } zBuffer[zIdx] = zBufVal; heightBuffer[zIdx] = hBufVal; } } //else { // *(w + 0) = 0; // *(w + 1) = 0; // *(w + 2) = 255; //} // Up to the next pixel rIdx++; zIdx++; w += 3; } w += stride - 3 * img.Width; zIdx += ds.Width - img.Width; } }
private void InitDrawableDefaults(Drawable drawable) { drawable.OwnerCollection = this; drawable.Props.PaletteType = Defaults.GetDefaultPalette(Type, Engine); drawable.Props.LightingType = Defaults.GetDefaultLighting(Type); drawable.IsRemapable = Defaults.GetDefaultRemappability(Type, Engine); drawable.Props.FrameDecider = Defaults.GetDefaultFrameDecider(Type); // apply collection-specific offsets switch (Type) { case CollectionType.Building: case CollectionType.Overlay: case CollectionType.Smudge: drawable.Props.Offset.Offset(Drawable.TileWidth / 2, 0); break; case CollectionType.Terrain: case CollectionType.Vehicle: case CollectionType.Infantry: case CollectionType.Aircraft: case CollectionType.Animation: drawable.Props.Offset.Offset(Drawable.TileWidth / 2, Drawable.TileHeight / 2); break; } }
public override void LoadFromRules() { base.LoadFromRules(); IsBuildingPart = true; InvisibleInGame = Rules.ReadBool("InvisibleInGame") || LampNames.Contains(Name.ToUpper()); string foundation = Art.ReadString("Foundation", "1x1"); if (!foundation.Equals("custom", StringComparison.InvariantCultureIgnoreCase)) { int fx = foundation[0] - '0'; int fy = foundation[2] - '0'; Foundation = new Size(fx, fy); } else { int fx = Art.ReadInt("Foundation.X", 1); int fy = Art.ReadInt("Foundation.Y", 1); Foundation = new Size(fx, fy); } Props.SortIndex = Art.ReadInt("NormalYSort") - Art.ReadInt("NormalZAdjust"); // "main" building image before anims Props.ZShapePointMove = Art.ReadPoint("ZShapePointMove"); _canBeOccupied = Rules.ReadBool("CanBeOccupied"); _techLevel = Rules.ReadInt("TechLevel"); _conditionYellowHealth = 128; _conditionRedHealth = 64; IniFile.IniSection audioVisual = OwnerCollection.Rules.GetOrCreateSection("AudioVisual"); if (audioVisual != null) { if (audioVisual.HasKey("ConditionYellow")) { int conditionYellow = audioVisual.ReadPercent("ConditionYellow"); _conditionYellowHealth = (int)(256 * (double)conditionYellow / 100); } if (audioVisual.HasKey("ConditionRed")) { int conditionRed = audioVisual.ReadPercent("ConditionRed"); _conditionRedHealth = (int)(256 * (double)conditionRed / 100); } } _baseShp = new ShpDrawable(_config, _vfs, Rules, Art); _baseShp.OwnerCollection = OwnerCollection; _baseShp.LoadFromArtEssential(); _baseShp.Props = Props; _baseShp.Shp = _vfs.Open <ShpFile>(_baseShp.GetFilename()); var extraProps = Props.Clone(); extraProps.SortIndex = 0; foreach (string extraImage in AnimImages) { var extra = LoadExtraImage(extraImage, extraProps); if (extra != null && extra.Shp != null) { _anims.Add(extra); var extraDmg = LoadExtraImage(extraImage + "Damaged", extra.Props); if (extraDmg != null && extraDmg.Shp != null) { _animsDamaged.Add(extraDmg); } else // no damaged anim --> use normal anim also in damaged state { _animsDamaged.Add(extra); } } } // RA2 and later support adding fire animations to buildings, supports custom-paletted animations. if (_config.Engine >= EngineType.RedAlert2) { LoadFireAnimations(); } // Add turrets if (Rules.ReadBool("Turret") && Rules.HasKey("TurretAnim")) { string turretName = Rules.ReadString("TurretAnim"); IniFile.IniSection turretArt = OwnerCollection.Art.GetOrCreateSection(turretName); if (turretArt.HasKey("Image")) { turretName = turretArt.ReadString("Image"); } // NewTheater/generic image fallback support for turrets. string turretNameShp = NewTheater ? OwnerCollection.ApplyNewTheaterIfNeeded(turretName, turretName + ".shp") : turretName + ".shp"; Drawable turret = Rules.ReadBool("TurretAnimIsVoxel") ? (Drawable) new VoxelDrawable(_config, _vfs.Open <VxlFile>(turretName + ".vxl"), _vfs.Open <HvaFile>(turretName + ".hva")) : (Drawable) new ShpDrawable(new ShpRenderer(_config, _vfs), _vfs.Open <ShpFile>(turretNameShp)); turret.Props.Offset = Props.Offset + new Size(Rules.ReadInt("TurretAnimX"), Rules.ReadInt("TurretAnimY")); turret.Props.HasShadow = Rules.ReadBool("UseTurretShadow"); turret.Props.FrameDecider = FrameDeciders.TurretFrameDecider; turret.Props.ZAdjust = Rules.ReadInt("TurretAnimZAdjust"); turret.Props.Cloakable = Props.Cloakable; SubDrawables.Add(turret); if (turret is VoxelDrawable && turretName.ToUpper().Contains("TUR")) { string barrelName = turretName.Replace("TUR", "BARL"); if (_vfs.FileExists(barrelName + ".vxl")) { var barrel = new VoxelDrawable(_config, _vfs.Open <VxlFile>(barrelName + ".vxl"), _vfs.Open <HvaFile>(barrelName + ".hva")); SubDrawables.Add(barrel); barrel.Props = turret.Props; } } } // Bib if (Art.HasKey("BibShape")) { var bibImg = Art.ReadString("BibShape") + ".shp"; if (NewTheater) { bibImg = OwnerCollection.ApplyNewTheaterIfNeeded(bibImg, bibImg); } var bibShp = _vfs.Open <ShpFile>(bibImg); if (bibShp != null) { var bib = new ShpDrawable(new ShpRenderer(_config, _vfs), bibShp); bib.Props = this.Props.Clone(); bib.Flat = true; SubDrawables.Add(bib); } } // Powerup slots, at most 3 for (int i = 1; i <= 3; i++) { _powerupSlots.Add(new PowerupSlot { X = Art.ReadInt(String.Format("PowerUp{0}LocXX", i), 0), Y = Art.ReadInt(String.Format("PowerUp{0}LocYY", i), 0), Z = Art.ReadInt(String.Format("PowerUp{0}LocZZ", i), 0), YSort = Art.ReadInt(String.Format("PowerUp{0}LocYSort", i), 0), }); } if (IsWall && _baseShp.Shp != null) { _baseShp.Shp.Initialize(); if (_baseShp.Shp.NumImages >= 32) { IsActualWall = true; } } }
public void DrawPowerup(GameObject obj, Drawable powerup, int slot, DrawingSurface ds) { if (slot >= _powerupSlots.Count) throw new InvalidOperationException("Building does not have requested slot "); var powerupOffset = new Point(_powerupSlots[slot].X, _powerupSlots[slot].Y); powerup.Props.Offset.Offset(powerupOffset); powerup.Draw(obj, ds); // undo offset powerup.Props.Offset.Offset(-powerupOffset.X, -powerupOffset.Y); }