Ejemplo n.º 1
0
        /// <summary>Attempts to add the "remote" atlas location to this atlas.
        /// The original location object is retained.</summary>
        /// <returns>True if this atlas accepted the location.</summary>
        internal bool OptimiseAdd(AtlasLocation location)
        {
            int           fitFactor       = 0;
            int           area            = location.Area;
            AtlasLocation currentAccepted = null;
            AtlasLocation currentEmpty    = FirstEmpty;

            while (currentEmpty != null)
            {
                int factor = currentEmpty.FitFactor(location.Width, location.Height, area);

                if (factor == 0)
                {
                    // Perfect fit - break right now; can't beat that!
                    currentAccepted = currentEmpty;
                    break;
                }
                else if (factor != -1)
                {
                    // We can possibly fit here - is it the current smallest?
                    if (currentAccepted == null || factor < fitFactor)
                    {
                        // Yep! select it.
                        fitFactor       = factor;
                        currentAccepted = currentEmpty;
                    }
                }

                currentEmpty = currentEmpty.EmptyAfter;
            }

            if (currentAccepted == null)
            {
                return(false);
            }

            // We've got a block of space that we'll be "adding" to.
            // Note that we're going to *keep* the original location.
            currentAccepted.OptimiseSelect(location);


            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>Adds the given texture to the atlas if it's not already on it,
        /// taking up a set amount of space on the atlas.</summary>
        /// <param name="texture">The texture to add.</param>
        /// <param name="width">The x amount of space to take up on the atlas.</param>
        /// <param name="height">The y amount of space to take up on the atlas.</param>
        /// <returns>The location of the texture on the atlas.</returns>
        internal AtlasLocation Add(AtlasEntity texture, int entityID, int width, int height)
        {
            // Pad width/height:
            int spacedWidth  = width + RawSpacing;
            int spacedHeight = height + RawSpacing;

            // Look for a spot to park this texture in the set of empty blocks.

            // The aim is to make it fit in the smallest empty block possible to save space.
            // This is done with a 'fitFactor' - this is simply the difference between the blocks area and the textures area.
            // We want this value to be as small as possible.
            AtlasLocation currentAccepted = null;

            int area = spacedWidth * spacedHeight;

            if (Mode == AtlasingMode.Columns)
            {
                // Space in this column?
                int max = ColumnProgressY + spacedHeight;

                if (max <= Dimension)
                {
                    // Yep! Create a location here:
                    currentAccepted = new AtlasLocation(this, ColumnProgressX, ColumnProgressY, spacedWidth, spacedHeight);

                    // Move it:
                    ColumnProgressY += spacedHeight;

                    if (spacedWidth > ColumnWidth)
                    {
                        // Update width:
                        ColumnWidth = spacedWidth;
                    }

                    // As it's a new location, it's empty by default:
                    // (Note that it must be in the empty set, otherwise Select will throw the empty set entirely)
                    currentAccepted.AddToEmptySet();
                }
                else
                {
                    // Space to generate a new column?
                    max = ColumnProgressX + ColumnWidth + spacedWidth;

                    if (max <= Dimension)
                    {
                        // Set Y:
                        ColumnProgressY = spacedHeight;

                        // Move X:
                        ColumnProgressX += ColumnWidth;

                        // Yep! Create a location here:
                        currentAccepted = new AtlasLocation(this, ColumnProgressX, 0, spacedWidth, spacedHeight);

                        // Reset width:
                        ColumnWidth = spacedWidth;

                        // As it's a new location, it's empty by default:
                        // (Note that it must be in the empty set, otherwise Select will throw the empty set entirely)
                        currentAccepted.AddToEmptySet();
                    }

                    // Otherwise, the atlas is practically full.
                    // We're gonna just reject the add (by falling below), and state that it can be optimised.
                    // This triggers another atlas to get created and this one will
                    // be optimised at some point in the near future.
                }
            }
            else
            {
                int fitFactor = 0;

                AtlasLocation currentEmpty = FirstEmpty;

                while (currentEmpty != null)
                {
                    int factor = currentEmpty.FitFactor(spacedWidth, spacedHeight, area);

                    if (factor == 0)
                    {
                        // Perfect fit - break right now; can't beat that!
                        currentAccepted = currentEmpty;
                        break;
                    }
                    else if (factor != -1)
                    {
                        // We can possibly fit here - is it the current smallest?
                        if (currentAccepted == null || factor < fitFactor)
                        {
                            // Yep! select it.
                            fitFactor       = factor;
                            currentAccepted = currentEmpty;
                        }
                    }

                    currentEmpty = currentEmpty.EmptyAfter;
                }
            }

            if (currentAccepted == null)
            {
                // No space in this atlas to fit it in. Stop there.

                if (CanOptimize)
                {
                    // Request an optimise:
                    OptimizeRequested       = true;
                    Stack.OptimizeRequested = true;
                }

                return(null);
            }

            Stack.ActiveImages[entityID] = currentAccepted;

            // And burn in the texture to the location (nb: it internally also writes the pixels to the atlas).
            currentAccepted.Select(texture, width, height, RawSpacing);

            return(currentAccepted);
        }
Ejemplo n.º 3
0
        /// <summary>Adds the given texture to the atlas if it's not already on it,
        /// taking up a set amount of space on the atlas.</summary>
        /// <param name="texture">The texture to add.</param>
        /// <param name="width">The x amount of space to take up on the atlas.</param>
        /// <param name="height">The y amount of space to take up on the atlas.</param>
        /// <returns>The location of the texture on the atlas.</returns>
        internal AtlasLocation Add(AtlasEntity texture, int entityID, int width, int height)
        {
            // Pad width/height:
            int spacedWidth  = width + RawSpacing;
            int spacedHeight = height + RawSpacing;

            // Look for a spot to park this texture in the set of empty blocks.

            // The aim is to make it fit in the smallest empty block possible to save space.
            // This is done with a 'fitFactor' - this is simply the difference between the blocks area and the textures area.
            // We want this value to be as small as possible.
            int           fitFactor       = 0;
            AtlasLocation currentAccepted = null;

            int area = spacedWidth * spacedHeight;

            AtlasLocation currentEmpty = FirstEmpty;

            while (currentEmpty != null)
            {
                int factor = currentEmpty.FitFactor(spacedWidth, spacedHeight, area);

                if (factor == 0)
                {
                    // Perfect fit - break right now; can't beat that!
                    currentAccepted = currentEmpty;
                    break;
                }
                else if (factor != -1)
                {
                    // We can possibly fit here - is it the current smallest?
                    if (currentAccepted == null || factor < fitFactor)
                    {
                        // Yep! select it.
                        fitFactor       = factor;
                        currentAccepted = currentEmpty;
                    }
                }

                currentEmpty = currentEmpty.EmptyAfter;
            }

            if (Mode == AtlasingMode.Columns && currentAccepted == null)
            {
                // Is there any more column space?
                int max = ColumnProgress + spacedWidth;

                if (max <= Dimension)
                {
                    // Yep! Create a location using the remaining space:
                    currentAccepted = new AtlasLocation(this, ColumnProgress, 0, Dimension - ColumnProgress, Dimension);

                    // As it's a new location, it's empty by default:
                    // (Note that it must be in the empty set, otherwise Select will throw the empty set entirely)
                    currentAccepted.AddToEmptySet();
                }
            }

            if (currentAccepted == null)
            {
                // No space in this atlas to fit it in. Stop there.

                if (CanOptimize)
                {
                    // Request an optimise:
                    OptimizeRequested       = true;
                    Stack.OptimizeRequested = true;
                }

                return(null);
            }

            Stack.ActiveImages[entityID] = currentAccepted;

            // And burn in the texture to the location (nb: it internally also writes the pixels to the atlas).
            currentAccepted.Select(texture, width, height, RawSpacing);

            return(currentAccepted);
        }