private void RandomizeNightModeTextures() { // This is called if global texture randomization is disabled, but night-mode randomization is selected. // The main idea is to replace the SkyBox in levels that are now set at night, but this is treated as a // texture category so potentially any other textures could also be targeted. _textureOptions = new Dictionary <TextureCategory, bool>(); foreach (TR23ScriptedLevel lvl in Levels) { LoadLevelInstance(lvl); if (_levelInstance.IsNightMode) { TextureLevelMapping mapping = GetMapping(_levelInstance); using (TextureHolder holder = new TextureHolder(mapping, this)) { foreach (AbstractTextureSource source in holder.Variants.Keys) { if (source.IsInCategory(TextureCategory.NightMode)) { RedrawTargets(holder.Mapping, source, holder.Variants[source], _textureOptions); } } } SaveLevelInstance(); } if (!TriggerProgress()) { break; } } }
private void RedrawTargets(TextureLevelMapping mapping, AbstractTextureSource source, string variant, Dictionary <TextureCategory, bool> options) { lock (_drawLock) { mapping.RedrawTargets(source, variant, options); } }
internal TextureHolder(TextureLevelMapping mapping, TextureRandomizer outer) { Mapping = mapping; Variants = new Dictionary <AbstractTextureSource, string>(); // Check first for any grouped sources List <TextureGrouping> groupingList = mapping.StaticGrouping; List <StaticTextureSource> handledSources = new List <StaticTextureSource>(); foreach (TextureGrouping staticGrouping in groupingList) { // Choose a variant for the leader, then assign this to the followers if they support it string variant = outer.GetSourceVariant(staticGrouping.Leader); Variants.Add(staticGrouping.Leader, variant); handledSources.Add(staticGrouping.Leader); foreach (StaticTextureSource source in staticGrouping.Followers) { if (source.HasVariants) { // Are we enforcing a specific colour for this theme? if (staticGrouping.ThemeAlternatives.ContainsKey(variant) && staticGrouping.ThemeAlternatives[variant].ContainsKey(source)) { Variants.Add(source, staticGrouping.ThemeAlternatives[variant][source]); } // Otherwise, does the grouped source have the same variant available? else if (source.Variants.Contains(variant)) { Variants.Add(source, variant); // If persistent textures are being used, have outer store what has been assigned to this source. outer.StoreVariant(source, variant); } // Otherwise, just add another random value for now (we ignore single variant sources such as FL/DL Spooky theme) else if (source.Variants.Length > 1) { Variants.Add(source, outer.GetSourceVariant(source)); } handledSources.Add(source); } } } foreach (StaticTextureSource source in Mapping.StaticMapping.Keys) { // Only randomize sources that aren't already grouped and that actually have variants if (source.HasVariants && !handledSources.Contains(source)) { Variants.Add(source, outer.GetSourceVariant(source)); } } // Dynamic changes should be made after static (e.g. for overlays) foreach (DynamicTextureSource source in Mapping.DynamicMapping.Keys) { Variants.Add(source, outer.GetSourceVariant(source)); } }
private TextureLevelMapping GetMapping(TR2CombinedLevel level) { lock (_drawLock) { return(TextureLevelMapping.Get ( level.Data, level.JsonID, _textureDatabase, TextureMonitor.GetLevelMapping(level.Name), TextureMonitor.GetIgnoredEntities(level.Name) )); } }
protected override void StartImpl() { // Load the level mapping and variants outwith the processor thread // to ensure the RNG selected for each level/texture remains consistent // between randomization sessions. List <TR2CombinedLevel> levels = new List <TR2CombinedLevel>(_holders.Keys); foreach (TR2CombinedLevel level in levels) { TextureLevelMapping mapping = _outer.GetMapping(level); if (mapping != null) { _holders[level] = new TextureHolder(mapping, _outer); } else { _holders.Remove(level); } } }
public bool Import(TR2CombinedLevel level, TextureLevelMapping mapping) { // Ensure any changes already made are committed to the level mapping.CommitGraphics(); using (TexturePacker packer = new TexturePacker(level.Data)) { List <TRObjectTexture> textures = level.Data.ObjectTextures.ToList(); foreach (StaticTextureSource source in mapping.LandmarkMapping.Keys) { if (textures.Count == _maxTextures) { break; } if (!source.HasVariants) { continue; } List <Rectangle> segments = source.VariantMap[source.Variants[0]]; foreach (int segmentIndex in mapping.LandmarkMapping[source].Keys) { foreach (LandmarkTextureTarget target in mapping.LandmarkMapping[source][segmentIndex]) { IndexedTRObjectTexture texture = CreateTexture(segments[segmentIndex]); target.MappedTextureIndex = textures.Count; textures.Add(texture.Texture); Bitmap image; if (target.BackgroundIndex != -1) { IndexedTRObjectTexture indexedTexture = new IndexedTRObjectTexture { Index = target.BackgroundIndex, Texture = level.Data.ObjectTextures[target.BackgroundIndex] }; BitmapGraphics tile = GetTile(level.Data, indexedTexture.Atlas); BitmapGraphics clip = new BitmapGraphics(tile.Extract(indexedTexture.Bounds)); clip.Overlay(source.Bitmap); image = clip.Bitmap; } else { image = source.Bitmap; } packer.AddRectangle(new TexturedTileSegment(texture, image)); } } } try { packer.Pack(true); // Perform the room data remapping foreach (StaticTextureSource source in mapping.LandmarkMapping.Keys) { if (!source.HasVariants) { continue; } foreach (int segmentIndex in mapping.LandmarkMapping[source].Keys) { foreach (LandmarkTextureTarget target in mapping.LandmarkMapping[source][segmentIndex]) { if (target.MappedTextureIndex == -1) { // There wasn't enough space for this continue; } TR2Room room = level.Data.Rooms[target.RoomNumber]; foreach (int rectIndex in target.RectangleIndices) { room.RoomData.Rectangles[rectIndex].Texture = (ushort)target.MappedTextureIndex; } } } } level.Data.ObjectTextures = textures.ToArray(); level.Data.NumObjectTextures = (uint)textures.Count; return(true); } catch (PackingException) { return(false); } } }