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);
                    }
                }
            }
Exemple #6
0
        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);
                }
            }
        }