public override bool DrawToAtlas(TextureAtlas atlas,AtlasLocation location){
			
			// Only ever called with a static image:
			Color32[] pixelBlock=Image.GetPixels32();
			
			int index=0;
			int atlasIndex=location.BottomLeftPixel();
			// How many pixels must we add on to the end of the row to get to
			// the start of the row above? This is RowPixelDelta:
			int rowDelta=location.RowPixelDelta();
			
			int height=Image.height;
			int width=Image.width;
			
			for(int h=0;h<height;h++){
				
				for(int w=0;w<width;w++){
					atlas.Pixels[atlasIndex++]=pixelBlock[index++];
				}
				
				atlasIndex+=rowDelta;
			}
			
			return true;
			
		}
		/// <summary>Creates a new location on the given atlas with the given size.</summary>
		/// <param name="atlas">The atlas this location refers to.</param>
		/// <param name="x">The x coordinate of the left edge of this location in pixels from the left.</param>
		/// <param name="y">The y coordinate of the bototm edfe of this location in pixels from the bottom.</param>
		/// <param name="width">The width of the location in pixels.</param>
		/// <param name="height">The height of the location in pixels.</param>
		public AtlasLocation(TextureAtlas atlas,int x,int y,int width,int height){
			X=x;
			Y=y;
			Atlas=atlas;
			Width=width;
			Height=height;
			Area=Width*Height;
			
			// BakeUV isn't called here as its results will be always overriden when select calls it.
			// As a result, empty locations have invalid UVs; this is ok.
		}
		/// <summary>Changes the font atlas used by the default material.</summary>
		public void SetFontAtlas(TextureAtlas atlas){
			Texture2D texture;
			
			if(atlas==null){
				texture=null;
			}else{
				texture=atlas.Texture;
			}
			
			Material.SetTexture("_Font",texture);
		}
		/// <summary>Sets the isolated state of this batch.</summary>
		public void IsIsolated(DisplayableProperty property){
			
			if(Isolated && Setup){
				// No change.
				return;
			}
			
			Setup=true;
			Isolated=true;
			FontAtlas=null;
			GraphicsAtlas=null;
			IsolatedProperty=property;
			
		}
		/// <summary>Sets the graphics atlas for this batch.</summary>
		public void SetGraphicsAtlas(TextureAtlas graphics){
			GraphicsAtlas=graphics;
			Mesh.SetGraphicsAtlas(graphics);
		}
		/// <summary>Sets the font atlas for this batch.</summary>
		public void SetFontAtlas(TextureAtlas font,float alias){
			FontAtlas=font;
			Mesh.SetFontAtlas(font);
			
			Mesh.Material.SetFloat("TopFontAlias",Fonts.OutlineLocation+alias);
			Mesh.Material.SetFloat("BottomFontAlias",Fonts.OutlineLocation-alias);
		}
		/// <summary>Sets the isolated state of this batch.</summary>
		public void NotIsolated(TextureAtlas graphics,TextureAtlas font,float alias){
			
			if(!Isolated && Setup){
				return;
			}
			
			Setup=true;
			Isolated=false;
			IsolatedProperty=null;
			
			Mesh.SetGlobalMaterial();
			SetFontAtlas(font,alias);
			SetGraphicsAtlas(graphics);
		}
//--------------------------------------
		/// <summary>Adds the given atlas to the top of this stack.</summary>
		public void Add(TextureAtlas atlas){
			
			atlas.Next=null;
			atlas.Stack=this;
			
			if(First==null){
				atlas.Previous=null;
				First=Last=atlas;
				return;
			}
			
			atlas.Previous=Last;
			Last=Last.Next=atlas;
			
		}
示例#10
0
//--------------------------------------
		public bool DrawToAtlas(TextureAtlas atlas,AtlasLocation location){
			
			// Only ever called with a static image:
			Color32[] pixelBlock=Image.GetPixels32();
			
			int index=0;
			int atlasIndex=location.BottomLeftPixel();
			
			int height=Image.height;
			int width=Image.width;
			
			// How many pixels must we add on to the end of the row to get to
			// the start of the row above? This is simply the dimension of the atlas:
			int rowDelta=atlas.Dimension;
			
			for(int h=0;h<height;h++){
				
				Array.Copy(pixelBlock,index,atlas.Pixels,atlasIndex,width);
				index+=width;
				atlasIndex+=rowDelta;
				
			}
			
			return true;
			
		}
		/// <summary>Sets a default material to this mesh.</summary>
		public void SetGraphicsAtlas(TextureAtlas atlas){
			Texture2D texture;
			
			if(atlas==null){
				texture=null;
			}else{
				texture=atlas.Texture;
			}
			
			Material.SetTexture("_Atlas",texture);
		}
		/// <summary>Sets up the current batch based on the isolation settings requested by a property.</summary>
		/// <param name="property">The displayable property which wants the batch.</param>
		/// <param name="fontTexture">The font texture to use with this batch.</param>
		public void SetupBatch(DisplayableProperty property,TextureAtlas graphics,TextureAtlas font){
			
			if(UI.MainCameraPool!=null && InWorldUI==null){
				// This is the main UI and it also has a camera pool.
				// Are we now attempting to create a batch on top of an inline camera?
				
				// Let the camera pool check:
				if(UI.MainCameraPool.CheckCameraRequired()){
					// Clear the current batch - it can't be shared any further.
					CurrentBatch=null;
				}
				
			}
			
			if(property.Isolated){
				if(property.GotBatchAlready){
					// The property already got a batch on this layout - it doesn't need another.
					return;
				}
				
				// Isolated properties always get a new batch every time.
				CurrentBatch=UIBatchPool.Get(this);
				
				if(CurrentBatch==null){
					CurrentBatch=new UIBatch(this);
				}
				
				property.GotBatchAlready=true;
				
				// And push it to the active stack:
				AddBatch(CurrentBatch);
				
				// Make sure it knows it's isolated:
				CurrentBatch.IsIsolated(property);
				
			}else{
				
				if(CurrentBatch!=null && !CurrentBatch.Isolated){
					// Re-use existing batch?
					
					if(font!=null){
						
						if(CurrentBatch.FontAtlas==null){
							// Didn't have one assigned before. Assign now:
							CurrentBatch.SetFontAtlas(font,FontAliasing);
						}else if(font!=CurrentBatch.FontAtlas){
							// Font atlas changed. Can't share.
							CurrentBatch=null;
						}
						
					}
					
					if(graphics!=null){
						
						if(CurrentBatch.GraphicsAtlas==null){
							// Didn't have one assigned before. Assign now:
							CurrentBatch.SetGraphicsAtlas(graphics);
						}else if(graphics!=CurrentBatch.GraphicsAtlas){
							// Atlas changed. Can't share.
							CurrentBatch=null;
						}
						
					}
					
					if(CurrentBatch!=null){
						// Yep - reuse it.
						return;
					}
					
				}
				
				// Pull a batch from the pool and set it to currentbatch. May need to generate a new one.
				CurrentBatch=UIBatchPool.Get(this);
				
				if(CurrentBatch==null){
					CurrentBatch=new UIBatch(this);
				}
				
				// And push it to the active stack:
				AddBatch(CurrentBatch);
				
				// Make sure it knows it's not isolated:
				CurrentBatch.NotIsolated(graphics,font,FontAliasing);
				
			}
			
			// Finally, prepare it for layout:
			CurrentBatch.PrepareForLayout();
			
		}
		public TextureAtlas Create(){
			
			// Create the atlas:
			TextureAtlas atlas=new TextureAtlas(InitialSize,FilteringMode,Format);
			atlas.Spacing=Spacing;
			atlas.Mode=Mode;
			Add(atlas);
			
			return atlas;
			
		}
        /// <summary>Optimises the frames on this stack if it's needed.</summary>
        public bool OptimiseIfNeeded()
        {
            if (!OptimizeRequested)
            {
                return(false);
            }

            OptimizeRequested = false;

            TextureAtlas requiresOptimise = null;
            TextureAtlas current          = First;

            while (current != null)
            {
                if (current.OptimizeRequested)
                {
                    // Pop it out:
                    current.RemoveFromStack();

                    // And add it to our temp stack:
                    current.Next     = requiresOptimise;
                    requiresOptimise = current;
                }

                current = current.Next;
            }

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

            Dictionary <int, AtlasLocation> allImages = ActiveImages;

            // Next, for each one..
            current = requiresOptimise;

            while (current != null)
            {
                // Grab the next one:
                TextureAtlas next = current.Next;

                // Offload its images into the "remaining" stack. Note that we must retain the actual Location objects so we don't have to re-request/ re-generate all of them.
                // If none fit, we re-add current as the new top of stack and add the images back onto it.

                // Have we re-added current?
                bool added = false;

                // Next up, add them all back in, and that's it!
                // The optimizing comes from them trying to fit in the smallest possible gap they can when added.
                foreach (KeyValuePair <int, AtlasLocation> kvp in allImages)
                {
                    AtlasLocation location = kvp.Value;

                    if (location.Atlas == current)
                    {
                        // Try adding to the stack:
                        TextureAtlas stackAtlas = Last;

                        bool noAdd = true;

                        while (stackAtlas != null)
                        {
                            // Try adding to the current frame:
                            if (stackAtlas.OptimiseAdd(location))
                            {
                                noAdd = false;
                                break;
                            }

                            stackAtlas = stackAtlas.Previous;
                        }

                        if (noAdd && !added)
                        {
                            added = true;

                            // Didn't fit in any of them! We now clear out the current atlas and re-add it like so:
                            Add(current);

                            // Ensure it's cleared:
                            current.Reset();

                            // Add to it instead:
                            current.OptimiseAdd(location);
                        }
                    }
                }

                if (!added)
                {
                    // Destroy it:
                    current.Destroy();
                }

                current = next;
            }

            return(true);
        }
		/// <summary>Draws this image to the given atlas.</summary>
		public virtual bool DrawToAtlas(TextureAtlas atlas,AtlasLocation location){
			return false;
		}
        /// <summary>Require the given image on any atlas. Note that this may reject the requirement if the image is too big and isn't worthwhile on an atlas.</summary>
        public AtlasLocation RequireImage(AtlasEntity image)
        {
            int entityID = image.GetAtlasID();

            AtlasLocation result;

            if (ActiveImages.TryGetValue(entityID, out result))
            {
                // Most calls fall through here.
                return(result);
            }

            int width;
            int height;

            image.GetDimensionsOnAtlas(out width, out height);

            if (width > InitialSize || height > InitialSize)
            {
                // Won't fit or is unsuitable for atlasing anyway.
                return(null);
            }

            if (Last == null)
            {
                Create();
            }
            else
            {
                // Fast check - was this texture recently removed from any atlas?
                // We might have the chance of restoring it.
                // Their added at the back of the empty queue, so naturally, start at the end of the empty set
                // and go back until we hit one with a null texture.

                TextureAtlas currentAtlas = Last;

                while (currentAtlas != null)
                {
                    AtlasLocation currentE = currentAtlas.LastEmpty;

                    while (currentE != null)
                    {
                        if (currentE.Image == null)
                        {
                            // Nope! Shame.
                            break;
                        }
                        else if (currentE.AtlasID == entityID)
                        {
                            // Ace! Time to bring it back from the dead.
                            currentE.Select(image, width, height, Spacing);
                            ActiveImages[entityID] = currentE;

                            return(currentE);
                        }

                        currentE = currentE.EmptyBefore;
                    }

                    currentAtlas = currentAtlas.Previous;
                }
            }

            // Push to top of stack:
            result = Last.Add(image, entityID, width, height);

            if (result != null)
            {
                return(result);
            }

            // Non-fitter - try fitting in lower stack frames:

            TextureAtlas current = Last.Previous;

            while (current != null)
            {
                result = current.Add(image, entityID, width, height);

                if (result != null)
                {
                    return(result);
                }

                current = current.Previous;
            }

            // Still not fitting! Create a new stack frame:
            Create();

            return(Last.Add(image, entityID, width, height));
        }
		/// <summary>Empties this atlas stack.</summary>
		public void Clear(){
			Last=null;
			First=null;
			// Clear all actives:
			ActiveImages.Clear();
		}