private int SortingOrderGenerate(SVGSpriteAssetFile spriteAsset) { if (spriteAsset != null) { SVGSpriteRef spriteRef = spriteAsset.SpriteRef; SVGSpriteData spriteData = spriteAsset.SpriteData; int svgIndex = this.SvgAssetIndexGet(spriteRef.TxtAsset); if (svgIndex >= 0) { SVGSpritesList spritesList; SVGAssetInput svgAsset = this.m_SvgList[svgIndex]; // if needed, advance in the instances group if (spriteData.InCurrentInstancesGroup) { // get the list of sprites (references) relative to the SVG input asset if (this.m_GeneratedSpritesLists.TryGetValue(svgAsset.TxtAsset.GetInstanceID(), out spritesList)) { // advance instances group, telling that we are going to instantiate one sprite only this.NextInstancesGroup(svgAsset, spritesList, 1); } } return(SVGAtlas.SortingOrderCalc(svgIndex, svgAsset.InstanceBaseIdx, spriteData.ZOrder)); } } return(-1); }
// Constructor. public SVGSpriteAssetFile(string path, SVGSpriteRef spriteRef, SVGSpriteData spriteData) { this.Path = path; this.SpriteRef = spriteRef; this.SpriteData = spriteData; #if UNITY_EDITOR this.InstantiatedWidgetType = SVGUIWidgetType.Button; #endif }
private void SortingOrdersCompact(SVGAssetInput svgAsset) { List <SpriteRenderer> spriteRenderers = new List <SpriteRenderer>(); // get the list of instantiated sprites relative to this atlas generator List <GameObject> spritesInstances = new List <GameObject>(); this.GetSpritesInstances(spritesInstances); foreach (GameObject gameObj in spritesInstances) { SVGSpriteLoaderBehaviour spriteLoader = (SVGSpriteLoaderBehaviour)gameObj.GetComponent <SVGSpriteLoaderBehaviour>(); SVGSpriteRef spriteRef = spriteLoader.SpriteReference; // if the sprite belongs to the specified SVG asset input, keep track of it if (spriteRef.TxtAsset == svgAsset.TxtAsset) { SpriteRenderer renderer = (SpriteRenderer)gameObj.GetComponent <SpriteRenderer>(); if (renderer != null) { spriteRenderers.Add(renderer); } } } if (spriteRenderers.Count > 0) { // order the list by current sorting order spriteRenderers.Sort(delegate(SpriteRenderer renderer1, SpriteRenderer renderer2) { if (renderer1.sortingOrder < renderer2.sortingOrder) { return(-1); } if (renderer1.sortingOrder > renderer2.sortingOrder) { return(1); } return(0); }); int j = spriteRenderers.Count; for (int i = 0; i < j; ++i) { SpriteRenderer renderer = spriteRenderers[i]; int currentOrder = renderer.sortingOrder; // isolate high part int svgIndex = currentOrder & SPRITES_SORTING_DOCUMENTS_MASK; // assign the new order renderer.sortingOrder = SVGAtlas.SortingOrderCalc(svgIndex, i); } svgAsset.InstanceBaseIdx = j; } else { // there are no sprite instances relative to the specified SVG, so we can start from 0 svgAsset.InstanceBaseIdx = 0; } }
public GameObject InstantiateWidget(Canvas canvas, SVGSpriteRef spriteRef, SVGUIWidgetType widgetType) { SVGSpriteAssetFile spriteAsset; if (this.m_GeneratedSpritesFiles.TryGetValue(spriteRef, out spriteAsset)) { return(this.InstantiateWidget(canvas, spriteAsset, widgetType)); } return(null); }
public SVGSpriteAssetFile GetGeneratedSprite(SVGSpriteRef spriteRef) { SVGSpriteAssetFile spriteAsset; if (this.m_GeneratedSpritesFiles.TryGetValue(spriteRef, out spriteAsset)) { return(spriteAsset); } return(null); }
public GameObject InstantiateSprite(SVGSpriteRef spriteRef) { SVGSpriteAssetFile spriteAsset; if (this.m_GeneratedSpritesFiles.TryGetValue(spriteRef, out spriteAsset)) { int sortingOrder = this.SortingOrderGenerate(spriteAsset); return(this.Instantiate(spriteAsset, sortingOrder)); } return(null); }
public bool Equals(SVGSpriteRef other) { if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } // we are referencing the same sprite if the xml text asset is the same and element id matches return((this.TxtAsset == other.TxtAsset && this.ElemIdx == other.ElemIdx) ? true : false); }
public SVGRuntimeSprite GetRuntimeSprite(SVGSpriteRef spriteRef) { if (this.m_RuntimeGenerationScale > 0) { SVGSpriteAssetFile spriteAsset; // get the requested sprite if (this.m_RuntimeSprites.TryGetValue(spriteRef, out spriteAsset)) { return(new SVGRuntimeSprite(spriteAsset.SpriteData.Sprite, this.m_RuntimeGenerationScale, spriteRef)); } } return(null); }
public GameObject InstantiateSprite(SVGSpriteRef spriteRef, Vector3 worldPos) { SVGSpriteAssetFile spriteAsset; if (this.m_GeneratedSpritesFiles.TryGetValue(spriteRef, out spriteAsset)) { int sortingOrder = this.SortingOrderGenerate(spriteAsset); GameObject gameObj = this.Instantiate(spriteAsset, sortingOrder); // assign world position gameObj.transform.position = worldPos; return(gameObj); } return(null); }
private GameObject Instantiate(SVGSpriteAssetFile spriteAsset, int sortingOrder) { SVGSpriteRef spriteRef = spriteAsset.SpriteRef; SVGSpriteData spriteData = spriteAsset.SpriteData; GameObject gameObj = new GameObject(); SpriteRenderer renderer = (SpriteRenderer)gameObj.AddComponent <SpriteRenderer>(); SVGSpriteLoaderBehaviour spriteLoader = (SVGSpriteLoaderBehaviour)gameObj.AddComponent <SVGSpriteLoaderBehaviour>(); renderer.sprite = spriteData.Sprite; renderer.sortingOrder = sortingOrder; spriteLoader.Atlas = this; spriteLoader.SpriteReference = spriteRef; spriteLoader.ResizeOnStart = true; gameObj.name = spriteData.Sprite.name; spriteData.InCurrentInstancesGroup = true; return(gameObj); }
// get all game objects with an attached SVGUISpriteLoaderBehaviour component that refers a specified sprite asset public void GetSpritesInstances(List <GameObject> spritesInstances, SVGSpriteRef spriteRef) { GameObject[] allObjects = GameObject.FindObjectsOfType <GameObject>(); foreach (GameObject gameObj in allObjects) { // check if the game object is an "SVG sprite" instance of this atlas generator if (gameObj.activeInHierarchy) { SVGUISpriteLoaderBehaviour loader = gameObj.GetComponent <SVGUISpriteLoaderBehaviour>(); // we must be sure that the loader component must refer to this atlas if ((loader != null) && (loader.UIAtlas == this) && (loader.SpriteReference.Equals(spriteRef))) { // add this instance to the output lists spritesInstances.Add(gameObj); } } } }
// recalculate sorting orders of instantiated sprites: changing is due only to SVG index, so the lower part (group + zNatural) is left unchanged private void SortingOrdersUpdateSvgIndex() { // get the list of instantiated sprites relative to this atlas generator List <GameObject> spritesInstances = new List <GameObject>(); this.GetSpritesInstances(spritesInstances); foreach (GameObject gameObj in spritesInstances) { SVGSpriteLoaderBehaviour spriteLoader = (SVGSpriteLoaderBehaviour)gameObj.GetComponent <SVGSpriteLoaderBehaviour>(); SpriteRenderer renderer = (SpriteRenderer)gameObj.GetComponent <SpriteRenderer>(); if (renderer != null) { SVGSpriteRef spriteRef = spriteLoader.SpriteReference; int svgIndex = this.SvgAssetIndexGet(spriteRef.TxtAsset); if (svgIndex >= 0) { int instance = renderer.sortingOrder & SPRITES_SORTING_INSTANCES_MASK; renderer.sortingOrder = SVGAtlas.SortingOrderCalc(svgIndex, instance); } } } }
public void UpdatePivot(SVGSpriteAssetFile spriteAsset, Vector2 newPivot) { SVGSpriteRef spriteRef = spriteAsset.SpriteRef; SVGSpriteData spriteData = spriteAsset.SpriteData; Sprite oldSprite = spriteData.Sprite; // keep track of pivot movement Vector2 deltaPivot = newPivot - spriteData.Pivot; Vector2 deltaMovement = (new Vector2(deltaPivot.x * oldSprite.rect.width, deltaPivot.y * oldSprite.rect.height)) / SVGBasicAtlas.SPRITE_PIXELS_PER_UNIT; // create a new sprite (same texture, same rectangle, different pivot) Sprite newSprite = Sprite.Create(oldSprite.texture, oldSprite.rect, newPivot, SVGBasicAtlas.SPRITE_PIXELS_PER_UNIT, 0, SpriteMeshType.FullRect, spriteData.Border); GameObject[] allObjects = GameObject.FindObjectsOfType <GameObject>(); foreach (GameObject gameObj in allObjects) { if (gameObj.activeInHierarchy) { SVGSpriteLoaderBehaviour loader = gameObj.GetComponent <SVGSpriteLoaderBehaviour>(); // we must be sure that the loader component must refer to this atlas if (loader != null && loader.Atlas == this) { // check if the instance uses the specified sprite if (loader.SpriteReference.TxtAsset == spriteRef.TxtAsset && loader.SpriteReference.ElemIdx == spriteRef.ElemIdx) { SVGAtlas.UpdatePivotHierarchy(gameObj, deltaMovement, 0); } } } } spriteData.Pivot = newPivot; newSprite.name = oldSprite.name; EditorUtility.CopySerialized(newSprite, oldSprite); SVGUtils.MarkObjectDirty(oldSprite); // destroy the temporary sprite GameObject.DestroyImmediate(newSprite); }
private void UpdateEditorSprites(float newScale) { // get the list of instantiated SVG sprites List <GameObject> spritesInstances = new List <GameObject>(); this.GetSpritesInstances(spritesInstances); // regenerate the list of sprite locations this.m_GeneratedSpritesLists = new SVGSpritesListDictionary(); if (this.m_SvgList.Count <= 0) { AssetDatabase.StartAssetEditing(); // delete previously generated textures (i.e. get all this.GeneratedTextures entries and delete the relative files) this.DeleteTextures(); // delete previously generated sprites (i.e. get all this.GeneratedSprites entries and delete the relative files) this.DeleteSprites(); if (spritesInstances.Count > 0) { bool remove = EditorUtility.DisplayDialog("Missing sprite!", string.Format("{0} gameobjects reference sprites that do not exist anymore. Would you like to remove them from the scene?", spritesInstances.Count), "Remove", "Keep"); if (remove) { this.DeleteGameObjects(spritesInstances); } } AssetDatabase.StopAssetEditing(); // input SVG list is empty, simply reset both hash this.m_SvgListHashOld = this.m_SvgListHashCurrent = ""; return; } // generate textures and sprites List <Texture2D> textures = new List <Texture2D>(); List <KeyValuePair <SVGSpriteRef, SVGSpriteData> > sprites = new List <KeyValuePair <SVGSpriteRef, SVGSpriteData> >(); if (SVGRuntimeGenerator.GenerateSprites(// input this.m_SvgList, this.m_MaxTexturesDimension, this.m_SpritesBorder, this.m_Pow2Textures, newScale, this.m_ClearColor, this.m_FastUpload, this.m_GeneratedSpritesFiles, // output textures, sprites, this.m_GeneratedSpritesLists)) { int i, j; if ((this.m_EditorGenerationScale > 0) && (newScale != this.m_EditorGenerationScale)) { // calculate how much we have to scale (relative) positions float deltaScale = newScale / this.m_EditorGenerationScale; // fix objects positions and animations foreach (GameObject gameObj in spritesInstances) { this.FixPositions(gameObj, deltaScale, deltaScale); } } // keep track of the new generation scale this.m_EditorGenerationScale = newScale; AssetDatabase.StartAssetEditing(); // delete previously generated textures (i.e. get all this.GeneratedTextures entries and delete the relative files) this.DeleteTextures(); // delete previously generated sprites (i.e. get all this.GeneratedSprites entries and delete the relative files) this.DeleteSprites(); // ensure the presence of needed subdirectories string atlasesPath = this.CreateOutputFolders(); string texturesDir = atlasesPath + "/Textures/"; string spritesDir = atlasesPath + "/Sprites/"; // save new texture assets i = 0; foreach (Texture2D texture in textures) { string textureFileName = texturesDir + "texture" + i + ".asset"; // save texture AssetDatabase.CreateAsset(texture, textureFileName); // DEBUG STUFF //byte[] pngData = texture.EncodeToPNG(); //if (pngData != null) // System.IO.File.WriteAllBytes(texturesDir + "texture" + i + ".png", pngData); // keep track of the saved texture this.m_GeneratedTexturesFiles.Add(new AssetFile(textureFileName, texture)); i++; } // save sprite assets j = sprites.Count; for (i = 0; i < j; ++i) { // get sprite reference and its pivot SVGSpriteRef spriteRef = sprites[i].Key; SVGSpriteData spriteData = sprites[i].Value; // build sprite file name string spriteFileName = spritesDir + spriteData.Sprite.name + ".asset"; // save sprite asset AssetDatabase.CreateAsset(spriteData.Sprite, spriteFileName); // keep track of the saved sprite and its pivot this.m_GeneratedSpritesFiles.Add(spriteRef, new SVGSpriteAssetFile(spriteFileName, spriteRef, spriteData)); } AssetDatabase.StopAssetEditing(); // for already instantiated (SVG) game object, set the new sprites // in the same loop we keep track of those game objects that reference missing sprites (i.e. sprites that do not exist anymore) List <GameObject> missingSpriteObjs = new List <GameObject>(); foreach (GameObject gameObj in spritesInstances) { SVGSpriteAssetFile spriteAsset; SVGSpriteLoaderBehaviour spriteLoader = (SVGSpriteLoaderBehaviour)gameObj.GetComponent <SVGSpriteLoaderBehaviour>(); if (spriteLoader.SpriteReference.TxtAsset != null) { if (this.m_GeneratedSpritesFiles.TryGetValue(spriteLoader.SpriteReference, out spriteAsset)) { // link the new sprite to the renderer SpriteRenderer renderer = (SpriteRenderer)gameObj.GetComponent <SpriteRenderer>(); if (renderer != null) { SVGSpriteData spriteData = spriteAsset.SpriteData; // assign the new sprite renderer.sprite = spriteData.Sprite; // NB: existing instances do not change sorting order! } } else { missingSpriteObjs.Add(gameObj); } } } if (missingSpriteObjs.Count > 0) { bool remove = EditorUtility.DisplayDialog("Missing sprite!", string.Format("{0} gameobjects reference sprites that do not exist anymore. Would you like to remove them from the scene?", missingSpriteObjs.Count), "Remove", "Keep"); if (remove) { this.DeleteGameObjects(missingSpriteObjs); } } // now SVG documents are instantiable foreach (SVGAssetInput svgAsset in this.m_SvgList) { svgAsset.Instantiable = true; } // keep track of the new hash this.m_SvgListHashOld = this.m_SvgListHashCurrent; } }
public SVGRuntimeSprite(Sprite sprite, float generationScale, SVGSpriteRef spriteReference) { this.m_Sprite = sprite; this.m_GenerationScale = generationScale; this.m_SpriteReference = spriteReference; }
private static bool GenerateSpritesFromBins(// input SVGPackedBin[] bins, Dictionary <uint, PackedSvgDocRef> loadedDocuments, float generationScale, Color clearColor, bool fastUpload, SVGSpritesDictionary previousSprites, // output List <Texture2D> textures, List <KeyValuePair <SVGSpriteRef, SVGSpriteData> > sprites, SVGSpritesListDictionary spritesListDict) { if (bins == null || loadedDocuments == null || textures == null || sprites == null) { return(false); } // sprite reference/key used to get pivot SVGSpriteRef tmpRef = new SVGSpriteRef(null, 0); for (int i = 0; i < bins.Length; ++i) { // extract the bin SVGPackedBin bin = bins[i]; // create drawing surface SVGSurface surface = SVGAssets.CreateSurface(bin.Width, bin.Height); if (surface != null) { // draw packed rectangles of the current bin if (surface.Draw(bin, new SVGColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a), SVGRenderingQuality.Better)) { // bin rectangles SVGPackedRectangle[] rectangles = bin.Rectangles; // create a 2D texture compatible with the drawing surface Texture2D texture = surface.CreateCompatibleTexture(true, false); if (texture != null) { // push the created texture textures.Add(texture); for (int j = 0; j < rectangles.Length; ++j) { PackedSvgDocRef svgDocRef; SVGPackedRectangle rect = rectangles[j]; // get access to the referenced SVG document if (loadedDocuments.TryGetValue(rect.DocHandle, out svgDocRef)) { SVGSpriteAssetFile spriteAsset; Vector2 pivot; Vector4 border; bool inCurrentInstancesGroup; // try to see if this sprite was previously generated, and if so get its pivot tmpRef.TxtAsset = svgDocRef.TxtAsset; tmpRef.ElemIdx = (int)rect.ElemIdx; // get the previous pivot if present, else start with a default centered pivot if (previousSprites.TryGetValue(tmpRef, out spriteAsset)) { float deltaScaleRatio = generationScale / spriteAsset.SpriteData.GenerationScale; pivot = spriteAsset.SpriteData.Pivot; border = spriteAsset.SpriteData.Border * deltaScaleRatio; inCurrentInstancesGroup = spriteAsset.SpriteData.InCurrentInstancesGroup; } else { pivot = new Vector2(0.5f, 0.5f); border = Vector4.zero; inCurrentInstancesGroup = false; } // create a new sprite Sprite sprite = Sprite.Create(texture, new Rect((float)rect.X, (float)((int)bin.Height - rect.Y - rect.Height), (float)rect.Width, (float)rect.Height), pivot, SVGBasicAtlas.SPRITE_PIXELS_PER_UNIT, 0, SpriteMeshType.FullRect, border); sprite.name = svgDocRef.Name + "_" + rect.Name; // push the sprite reference SVGSpriteRef key = new SVGSpriteRef(svgDocRef.TxtAsset, (int)rect.ElemIdx); SVGSpriteData value = new SVGSpriteData(sprite, pivot, border, rect.ZOrder, rect.OriginalX, rect.OriginalY, generationScale, inCurrentInstancesGroup); sprites.Add(new KeyValuePair <SVGSpriteRef, SVGSpriteData>(key, value)); // check if we are interested in getting, for each SVG document, the list of its generated sprites if (spritesListDict != null) { SVGSpritesList spritesList; if (!spritesListDict.TryGetValue(svgDocRef.TxtAsset.GetInstanceID(), out spritesList)) { // create the list of sprites location relative to the SVG text asset spritesList = new SVGSpritesList(); spritesListDict.Add(svgDocRef.TxtAsset.GetInstanceID(), spritesList); } // add the new sprite the its list spritesList.Sprites.Add(key); } // decrement document references if (svgDocRef.Dec(1) == 0) { // we can free AmanithSVG native SVG document svgDocRef.Document.Dispose(); } } } // copy the surface content into the texture if (fastUpload && (Application.isPlaying)) { surface.CopyAndDestroy(texture); } else { if (surface.Copy(texture)) { // call Apply() so it's actually uploaded to the GPU texture.Apply(false, false); } } } } // destroy the AmanithSVG rendering surface surface.Dispose(); } } return(true); }
private GameObject InstantiateWidget(Canvas canvas, SVGSpriteAssetFile spriteAsset, SVGUIWidgetType widgetType) { Image uiImage; InputField inputField = null; SVGSpriteRef spriteRef = spriteAsset.SpriteRef; SVGSpriteData spriteData = spriteAsset.SpriteData; GameObject gameObj = new GameObject(); gameObj.layer = LayerMask.NameToLayer("UI"); // add Image component; NB: it will add a RectTransform component too uiImage = gameObj.AddComponent <Image>(); uiImage.fillCenter = true; uiImage.material = null; uiImage.color = new Color(1.0f, 1.0f, 1.0f, 1.0f); uiImage.sprite = spriteData.Sprite; switch (widgetType) { case SVGUIWidgetType.Button: gameObj.AddComponent <Button>(); break; case SVGUIWidgetType.InputField: inputField = gameObj.AddComponent <InputField>(); break; default: break; } // get RectTransform component and set size according to the associated sprite RectTransform rectTransform = gameObj.GetComponent <RectTransform>(); rectTransform.SetParent(canvas.transform); // attach SVGUISpriteLoaderBehaviour component SVGUISpriteLoaderBehaviour spriteLoader = (SVGUISpriteLoaderBehaviour)gameObj.AddComponent <SVGUISpriteLoaderBehaviour>(); spriteLoader.UIAtlas = this; spriteLoader.SpriteReference = spriteRef; spriteLoader.ResizeOnStart = true; // anchor presets if (widgetType == SVGUIWidgetType.Panel) { rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.localPosition = Vector3.zero; rectTransform.sizeDelta = Vector2.zero; } else { rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.sizeDelta = new Vector2(spriteData.Sprite.rect.width, spriteData.Sprite.rect.height); } // set image type uiImage.type = (spriteData.Sprite.border != Vector4.zero) ? Image.Type.Sliced : Image.Type.Simple; if (widgetType == SVGUIWidgetType.InputField) { this.PopulateInputField(canvas, gameObj, inputField); } gameObj.name = spriteData.Sprite.name; gameObj.SetActive(true); return(gameObj); }