/// <summary> /// Replace the sprites within the atlas. /// </summary> static void ReplaceSprites(NGUIAtlas atlas, List <SpriteEntry> sprites) { // Get the list of sprites we'll be updating List <NGUIAtlas.Sprite> spriteList = atlas.spriteList; List <NGUIAtlas.Sprite> kept = new List <NGUIAtlas.Sprite>(); // The atlas must be in pixels atlas.coordinates = NGUIAtlas.Coordinates.Pixels; // Run through all the textures we added and add them as sprites to the atlas for (int i = 0; i < sprites.Count; ++i) { SpriteEntry se = sprites[i]; NGUIAtlas.Sprite sprite = AddSprite(spriteList, se); kept.Add(sprite); } // Remove unused sprites for (int i = spriteList.Count; i > 0;) { NGUIAtlas.Sprite sp = spriteList[--i]; if (!kept.Contains(sp)) { spriteList.RemoveAt(i); } } atlas.MarkAsDirty(); }
/// <summary> /// Visibly highlight the specified transform by moving the highlight sprite to be over it. /// </summary> void Highlight(NGUILabel lbl, bool instant) { if (mHighlight != null) { // Don't allow highlighting while the label is animating to its intended position TweenPosition tp = lbl.GetComponent <TweenPosition>(); if (tp != null && tp.enabled) { return; } mHighlightedLabel = lbl; NGUIAtlas.Sprite sp = mHighlight.GetAtlasSprite(); if (sp == null) { return; } float offsetX = sp.inner.xMin - sp.outer.xMin; float offsetY = sp.inner.yMin - sp.outer.yMin; Vector3 pos = lbl.cachedTransform.localPosition + new Vector3(-offsetX, offsetY, 0f); if (instant || !isAnimated) { mHighlight.cachedTransform.localPosition = pos; } else { TweenPosition.Begin(mHighlight.gameObject, 0.1f, pos).method = NGUITweener.Method.EaseOut; } } }
/// <summary> /// Add a sprite appropriate for the specified atlas sprite. /// It will be sliced if the sprite has an inner rect, and a regular sprite otherwise. /// </summary> static public NGUISprite AddSprite(GameObject go, NGUIAtlas atlas, string spriteName) { NGUIAtlas.Sprite sp = (atlas != null) ? atlas.GetSprite(spriteName) : null; NGUISprite sprite = AddWidget <NGUISprite>(go); sprite.type = (sp == null || sp.inner == sp.outer) ? NGUISprite.Type.Simple : NGUISprite.Type.Sliced; sprite.atlas = atlas; sprite.spriteName = spriteName; return(sprite); }
/// <summary> /// Validate this symbol, given the specified atlas. /// </summary> public bool Validate(NGUIAtlas atlas) { if (atlas == null) { return(false); } #if UNITY_EDITOR if (!Application.isPlaying || !mIsValid) #else if (!mIsValid) #endif { if (string.IsNullOrEmpty(spriteName)) { return(false); } mSprite = (atlas != null) ? atlas.GetSprite(spriteName) : null; if (mSprite != null) { Texture tex = atlas.texture; if (tex == null) { mSprite = null; } else { Rect outer = mSprite.outer; mUV = outer; if (atlas.coordinates == NGUIAtlas.Coordinates.Pixels) { mUV = NGUIMath.ConvertToTexCoords(mUV, tex.width, tex.height); } else { outer = NGUIMath.ConvertToPixels(outer, tex.width, tex.height, true); } mOffsetX = Mathf.RoundToInt(mSprite.paddingLeft * outer.width); mOffsetY = Mathf.RoundToInt(mSprite.paddingTop * outer.width); mWidth = Mathf.RoundToInt(outer.width); mHeight = Mathf.RoundToInt(outer.height); mAdvance = Mathf.RoundToInt(outer.width + (mSprite.paddingRight + mSprite.paddingLeft) * outer.width); mIsValid = true; } } } return(mSprite != null); }
/// <summary> /// Update the UV coordinates. /// </summary> override public bool OnUpdate() { if (mChanged || !mSpriteSet) { mSpriteSet = true; mSprite = null; mChanged = true; UpdateUVs(true); return(true); } UpdateUVs(false); return(false); }
/// <summary> /// Convenience function that displays a list of sprites and returns the selected value. /// </summary> static public void AdvancedSpriteField(NGUIAtlas atlas, string spriteName, SpriteSelector.Callback callback, bool editable, params GUILayoutOption[] options) { // Give the user a warning if there are no sprites in the atlas if (atlas.spriteList.Count == 0) { EditorGUILayout.HelpBox("No sprites found", MessageType.Warning); return; } // Sprite selection drop-down list GUILayout.BeginHorizontal(); { if (GUILayout.Button("Sprite", "DropDownButton", GUILayout.Width(76f))) { SpriteSelector.Show(atlas, spriteName, callback); } if (editable) { string sn = GUILayout.TextField(spriteName); if (sn != spriteName) { NGUIAtlas.Sprite sp = atlas.GetSprite(spriteName); if (sp != null) { NGUIEditorTools.RegisterUndo("Edit Sprite Name", atlas); sp.name = sn; spriteName = sn; } } } else { GUILayout.BeginHorizontal(); GUILayout.Label(spriteName, "HelpBox", GUILayout.Height(18f)); GUILayout.Space(18f); GUILayout.EndHorizontal(); if (GUILayout.Button("Edit", GUILayout.Width(40f))) { EditorPrefs.SetString("NGUI Selected Sprite", spriteName); Select(atlas.gameObject); } } } GUILayout.EndHorizontal(); }
/// <summary> /// Add a new sprite to the atlas, given the texture it's coming from and the packed rect within the atlas. /// </summary> static NGUIAtlas.Sprite AddSprite(List<NGUIAtlas.Sprite> sprites, SpriteEntry se) { NGUIAtlas.Sprite sprite = null; // See if this sprite already exists foreach (NGUIAtlas.Sprite sp in sprites) { if (sp.name == se.tex.name) { sprite = sp; break; } } if (sprite != null) { float x0 = sprite.inner.xMin - sprite.outer.xMin; float y0 = sprite.inner.yMin - sprite.outer.yMin; float x1 = sprite.outer.xMax - sprite.inner.xMax; float y1 = sprite.outer.yMax - sprite.inner.yMax; sprite.outer = se.rect; sprite.inner = se.rect; sprite.inner.xMin = Mathf.Max(sprite.inner.xMin + x0, sprite.outer.xMin); sprite.inner.yMin = Mathf.Max(sprite.inner.yMin + y0, sprite.outer.yMin); sprite.inner.xMax = Mathf.Min(sprite.inner.xMax - x1, sprite.outer.xMax); sprite.inner.yMax = Mathf.Min(sprite.inner.yMax - y1, sprite.outer.yMax); } else { sprite = new NGUIAtlas.Sprite(); sprite.name = se.tex.name; sprite.outer = se.rect; sprite.inner = se.rect; sprites.Add(sprite); } float width = Mathf.Max(1f, sprite.outer.width); float height = Mathf.Max(1f, sprite.outer.height); // Sprite's padding values are relative to width and height sprite.paddingLeft = se.minX / width; sprite.paddingRight = se.maxX / width; sprite.paddingTop = se.maxY / height; sprite.paddingBottom = se.minY / height; return sprite; }
/// <summary> /// Add a new sprite to the atlas, given the texture it's coming from and the packed rect within the atlas. /// </summary> static NGUIAtlas.Sprite AddSprite(List <NGUIAtlas.Sprite> sprites, SpriteEntry se) { NGUIAtlas.Sprite sprite = null; // See if this sprite already exists foreach (NGUIAtlas.Sprite sp in sprites) { if (sp.name == se.tex.name) { sprite = sp; break; } } if (sprite != null) { float x0 = sprite.inner.xMin - sprite.outer.xMin; float y0 = sprite.inner.yMin - sprite.outer.yMin; float x1 = sprite.outer.xMax - sprite.inner.xMax; float y1 = sprite.outer.yMax - sprite.inner.yMax; sprite.outer = se.rect; sprite.inner = se.rect; sprite.inner.xMin = Mathf.Max(sprite.inner.xMin + x0, sprite.outer.xMin); sprite.inner.yMin = Mathf.Max(sprite.inner.yMin + y0, sprite.outer.yMin); sprite.inner.xMax = Mathf.Min(sprite.inner.xMax - x1, sprite.outer.xMax); sprite.inner.yMax = Mathf.Min(sprite.inner.yMax - y1, sprite.outer.yMax); } else { sprite = new NGUIAtlas.Sprite(); sprite.name = se.tex.name; sprite.outer = se.rect; sprite.inner = se.rect; sprites.Add(sprite); } float width = Mathf.Max(1f, sprite.outer.width); float height = Mathf.Max(1f, sprite.outer.height); // Sprite's padding values are relative to width and height sprite.paddingLeft = se.minX / width; sprite.paddingRight = se.maxX / width; sprite.paddingTop = se.maxY / height; sprite.paddingBottom = se.minY / height; return(sprite); }
/// <summary> /// Button creation function. /// </summary> void CreateImageButton(GameObject go) { if (NGUISettings.atlas != null) { NGUIEditorTools.SpriteField("Normal", "Normal state sprite", NGUISettings.atlas, mImage0, OnImage0); NGUIEditorTools.SpriteField("Hover", "Hover state sprite", NGUISettings.atlas, mImage1, OnImage1); NGUIEditorTools.SpriteField("Pressed", "Pressed state sprite", NGUISettings.atlas, mImage2, OnImage2); NGUIEditorTools.SpriteField("Disabled", "Disabled state sprite", NGUISettings.atlas, mImage3, OnImage3); } if (ShouldCreate(go, NGUISettings.atlas != null)) { int depth = NGUITools.CalculateNextDepth(go); go = NGUITools.AddChild(go); go.name = "Image Button"; NGUIAtlas.Sprite sp = NGUISettings.atlas.GetSprite(mImage0); NGUISprite sprite = NGUITools.AddWidget <NGUISprite>(go); sprite.type = (sp.inner == sp.outer) ? NGUISprite.Type.Simple : NGUISprite.Type.Sliced; sprite.name = "Background"; sprite.depth = depth; sprite.atlas = NGUISettings.atlas; sprite.spriteName = mImage0; sprite.transform.localScale = new Vector3(150f, 40f, 1f); sprite.MakePixelPerfect(); if (NGUISettings.font != null) { NGUILabel lbl = NGUITools.AddWidget <NGUILabel>(go); lbl.font = NGUISettings.font; lbl.text = go.name; lbl.MakePixelPerfect(); } // Add a collider NGUITools.AddWidgetCollider(go); // Add the scripts NGUIImageButton ib = go.AddComponent <NGUIImageButton>(); ib.target = sprite; ib.normalSprite = mImage0; ib.hoverSprite = mImage1; ib.pressedSprite = mImage2; go.AddComponent <NGUIButtonSound>(); Selection.activeGameObject = go; } }
/// <summary> /// Set the atlas sprite directly. /// </summary> protected void SetAtlasSprite(NGUIAtlas.Sprite sp) { mChanged = true; mSpriteSet = true; if (sp != null) { mSprite = sp; mSpriteName = mSprite.name; } else { mSpriteName = (mSprite != null) ? mSprite.name : ""; mSprite = sp; } }
/// <summary> /// Retrieve the atlas sprite referenced by the spriteName field. /// </summary> public NGUIAtlas.Sprite GetAtlasSprite() { if (!mSpriteSet) { mSprite = null; } if (mSprite == null && mAtlas != null) { if (!string.IsNullOrEmpty(mSpriteName)) { NGUIAtlas.Sprite sp = mAtlas.GetSprite(mSpriteName); if (sp == null) { return(null); } SetAtlasSprite(sp); } if (mSprite == null && mAtlas.spriteList.Count > 0) { NGUIAtlas.Sprite sp = mAtlas.spriteList[0]; if (sp == null) { return(null); } SetAtlasSprite(sp); if (mSprite == null) { Debug.LogError(mAtlas.name + " seems to have a null sprite!"); return(null); } mSpriteName = mSprite.name; } // If the sprite has been set, update the material if (mSprite != null) { material = mAtlas.spriteMaterial; UpdateUVs(true); } } return(mSprite); }
/// <summary> /// Copy the inner rectangle from one sprite to another. /// </summary> static void CopyInnerRect(NGUIAtlas.Sprite oldSprite, NGUIAtlas.Sprite newSprite) { float offsetX = oldSprite.inner.xMin - oldSprite.outer.xMin; float offsetY = oldSprite.inner.yMin - oldSprite.outer.yMin; float sizeX = oldSprite.inner.width; float sizeY = oldSprite.inner.height; if (Mathf.Approximately(newSprite.outer.width, oldSprite.outer.width)) { // The sprite has not been rotated or it's a square newSprite.inner = new Rect(newSprite.outer.xMin + offsetX, newSprite.outer.yMin + offsetY, sizeX, sizeY); } else if (Mathf.Approximately(newSprite.outer.width, oldSprite.outer.height)) { // The sprite was rotated since the last time it was imported newSprite.inner = new Rect(newSprite.outer.xMin + offsetY, newSprite.outer.yMin + offsetX, sizeY, sizeX); } }
/// <summary> /// Rebuild the sprite list after changing the sprite name. /// </summary> void RebuildSpriteList() { if (mSprite == null) { mSprite = GetComponent <NGUISprite>(); } mSpriteNames.Clear(); if (mSprite != null && mSprite.atlas != null) { List <NGUIAtlas.Sprite> sprites = mSprite.atlas.spriteList; for (int i = 0, imax = sprites.Count; i < imax; ++i) { NGUIAtlas.Sprite sprite = sprites[i]; if (string.IsNullOrEmpty(mPrefix) || sprite.name.StartsWith(mPrefix)) { mSpriteNames.Add(sprite.name); } } mSpriteNames.Sort(); } }
static public void AddSprite() { GameObject go = NGUIEditorTools.SelectedRoot(true); if (go != null) { Undo.RegisterSceneUndo("Add a Sprite"); NGUISprite sprite = NGUITools.AddWidget <NGUISprite>(go); sprite.name = "Sprite"; sprite.atlas = NGUISettings.atlas; if (sprite.atlas != null) { string sn = EditorPrefs.GetString("NGUI Sprite", ""); NGUIAtlas.Sprite sp = sprite.atlas.GetSprite(sn); if (sp != null) { sprite.spriteName = sn; if (sp.inner != sp.outer) { sprite.type = NGUISprite.Type.Sliced; } } } sprite.pivot = NGUISettings.pivot; sprite.cachedTransform.localScale = new Vector3(100f, 100f, 1f); sprite.MakePixelPerfect(); Selection.activeGameObject = sprite.gameObject; } else { Debug.Log("You must select a game object first."); } }
/// <summary> /// Create a popup list or a menu. /// </summary> void CreatePopup(GameObject go, bool isDropDown) { if (NGUISettings.atlas != null) { NGUIEditorTools.SpriteField("Foreground", "Foreground sprite (shown on the button)", NGUISettings.atlas, mListFG, OnListFG); NGUIEditorTools.SpriteField("Background", "Background sprite (envelops the options)", NGUISettings.atlas, mListBG, OnListBG); NGUIEditorTools.SpriteField("Highlight", "Sprite used to highlight the selected option", NGUISettings.atlas, mListHL, OnListHL); } if (ShouldCreate(go, NGUISettings.atlas != null && NGUISettings.font != null)) { int depth = NGUITools.CalculateNextDepth(go); go = NGUITools.AddChild(go); go.name = isDropDown ? "Popup List" : "Popup Menu"; NGUIAtlas.Sprite sphl = NGUISettings.atlas.GetSprite(mListHL); NGUIAtlas.Sprite spfg = NGUISettings.atlas.GetSprite(mListFG); Vector2 hlPadding = new Vector2( Mathf.Max(4f, sphl.inner.xMin - sphl.outer.xMin), Mathf.Max(4f, sphl.inner.yMin - sphl.outer.yMin)); Vector2 fgPadding = new Vector2( Mathf.Max(4f, spfg.inner.xMin - spfg.outer.xMin), Mathf.Max(4f, spfg.inner.yMin - spfg.outer.yMin)); // Background sprite NGUISprite sprite = NGUITools.AddSprite(go, NGUISettings.atlas, mListFG); sprite.depth = depth; sprite.atlas = NGUISettings.atlas; sprite.pivot = NGUIWidget.Pivot.Left; sprite.transform.localScale = new Vector3(150f + fgPadding.x * 2f, NGUISettings.font.size + fgPadding.y * 2f, 1f); sprite.transform.localPosition = Vector3.zero; sprite.MakePixelPerfect(); // Text label NGUILabel lbl = NGUITools.AddWidget <NGUILabel>(go); lbl.font = NGUISettings.font; lbl.text = go.name; lbl.pivot = NGUIWidget.Pivot.Left; lbl.cachedTransform.localPosition = new Vector3(fgPadding.x, 0f, 0f); lbl.MakePixelPerfect(); // Add a collider NGUITools.AddWidgetCollider(go); // Add the popup list NGUIPopupList list = go.AddComponent <NGUIPopupList>(); list.atlas = NGUISettings.atlas; list.font = NGUISettings.font; list.backgroundSprite = mListBG; list.highlightSprite = mListHL; list.padding = hlPadding; if (isDropDown) { list.textLabel = lbl; } for (int i = 0; i < 5; ++i) { list.items.Add(isDropDown ? ("List Option " + i) : ("Menu Option " + i)); } // Add the scripts go.AddComponent <NGUIButton>().tweenTarget = sprite.gameObject; go.AddComponent <NGUIButtonSound>(); Selection.activeGameObject = go; } }
/// <summary> /// Progress bar creation function. /// </summary> void CreateSlider(GameObject go, bool slider) { if (NGUISettings.atlas != null) { NGUIEditorTools.SpriteField("Empty", "Sprite for the background (empty bar)", NGUISettings.atlas, mSliderBG, OnSliderBG); NGUIEditorTools.SpriteField("Full", "Sprite for the foreground (full bar)", NGUISettings.atlas, mSliderFG, OnSliderFG); if (slider) { NGUIEditorTools.SpriteField("Thumb", "Sprite for the thumb indicator", NGUISettings.atlas, mSliderTB, OnSliderTB); } } if (ShouldCreate(go, NGUISettings.atlas != null)) { int depth = NGUITools.CalculateNextDepth(go); go = NGUITools.AddChild(go); go.name = slider ? "Slider" : "Progress Bar"; // Background sprite NGUIAtlas.Sprite bgs = NGUISettings.atlas.GetSprite(mSliderBG); NGUISprite back = (NGUISprite)NGUITools.AddWidget <NGUISprite>(go); back.type = (bgs.inner == bgs.outer) ? NGUISprite.Type.Simple : NGUISprite.Type.Sliced; back.name = "Background"; back.depth = depth; back.pivot = NGUIWidget.Pivot.Left; back.atlas = NGUISettings.atlas; back.spriteName = mSliderBG; back.transform.localScale = new Vector3(200f, 30f, 1f); back.transform.localPosition = Vector3.zero; back.MakePixelPerfect(); // Foreground sprite NGUIAtlas.Sprite fgs = NGUISettings.atlas.GetSprite(mSliderFG); NGUISprite front = NGUITools.AddWidget <NGUISprite>(go); front.type = (fgs.inner == fgs.outer) ? NGUISprite.Type.Filled : NGUISprite.Type.Sliced; front.name = "Foreground"; front.pivot = NGUIWidget.Pivot.Left; front.atlas = NGUISettings.atlas; front.spriteName = mSliderFG; front.transform.localScale = new Vector3(200f, 30f, 1f); front.transform.localPosition = Vector3.zero; front.MakePixelPerfect(); // Add a collider if (slider) { NGUITools.AddWidgetCollider(go); } // Add the slider script NGUISlider uiSlider = go.AddComponent <NGUISlider>(); uiSlider.foreground = front.transform; // Thumb sprite if (slider) { NGUIAtlas.Sprite tbs = NGUISettings.atlas.GetSprite(mSliderTB); NGUISprite thb = NGUITools.AddWidget <NGUISprite>(go); thb.type = (tbs.inner == tbs.outer) ? NGUISprite.Type.Simple : NGUISprite.Type.Sliced; thb.name = "Thumb"; thb.atlas = NGUISettings.atlas; thb.spriteName = mSliderTB; thb.transform.localPosition = new Vector3(200f, 0f, 0f); thb.transform.localScale = new Vector3(20f, 40f, 1f); thb.MakePixelPerfect(); NGUITools.AddWidgetCollider(thb.gameObject); thb.gameObject.AddComponent <NGUIButtonColor>(); thb.gameObject.AddComponent <NGUIButtonScale>(); uiSlider.thumb = thb.transform; } uiSlider.sliderValue = 1f; // Select the slider Selection.activeGameObject = go; } }
/// <summary> /// Sprite selection callback. /// </summary> void SelectSprite(string spriteName) { mSprite = mAtlas.GetSprite(spriteName); EditorPrefs.SetString("NGUI Selected Sprite", spriteName); Repaint(); }
/// <summary> /// Draw the inspector widget. /// </summary> public override void OnInspectorGUI() { EditorGUIUtility.LookLikeControls(80f); mAtlas = target as NGUIAtlas; NGUIEditorTools.DrawSeparator(); if (mAtlas.replacement != null) { mType = AtlasType.Reference; mReplacement = mAtlas.replacement; } AtlasType after = (AtlasType)EditorGUILayout.EnumPopup("Atlas Type", mType); if (mType != after) { if (after == AtlasType.Normal) { OnSelectAtlas(null); } else { mType = AtlasType.Reference; } } if (mType == AtlasType.Reference) { ComponentSelector.Draw <NGUIAtlas>(mAtlas.replacement, OnSelectAtlas); NGUIEditorTools.DrawSeparator(); EditorGUILayout.HelpBox("You can have one atlas simply point to " + "another one. This is useful if you want to be " + "able to quickly replace the contents of one " + "atlas with another one, for example for " + "swapping an SD atlas with an HD one, or " + "replacing an English atlas with a Chinese " + "one. All the sprites referencing this atlas " + "will update their references to the new one.", MessageType.Info); if (mReplacement != mAtlas && mAtlas.replacement != mReplacement) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.replacement = mReplacement; UnityEditor.EditorUtility.SetDirty(mAtlas); } return; } if (!mConfirmDelete) { NGUIEditorTools.DrawSeparator(); Material mat = EditorGUILayout.ObjectField("Material", mAtlas.spriteMaterial, typeof(Material), false) as Material; if (mAtlas.spriteMaterial != mat) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.spriteMaterial = mat; // Ensure that this atlas has valid import settings if (mAtlas.texture != null) { NGUIEditorTools.ImportTexture(mAtlas.texture, false, false); } mAtlas.MarkAsDirty(); mConfirmDelete = false; } if (mat != null) { TextAsset ta = EditorGUILayout.ObjectField("TP Import", null, typeof(TextAsset), false) as TextAsset; if (ta != null) { // Ensure that this atlas has valid import settings if (mAtlas.texture != null) { NGUIEditorTools.ImportTexture(mAtlas.texture, false, false); } NGUIEditorTools.RegisterUndo("Import Sprites", mAtlas); NGUIJson.LoadSpriteData(mAtlas, ta); if (mSprite != null) { mSprite = mAtlas.GetSprite(mSprite.name); } mAtlas.MarkAsDirty(); } NGUIAtlas.Coordinates coords = (NGUIAtlas.Coordinates)EditorGUILayout.EnumPopup("Coordinates", mAtlas.coordinates); if (coords != mAtlas.coordinates) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.coordinates = coords; mConfirmDelete = false; } float pixelSize = EditorGUILayout.FloatField("Pixel Size", mAtlas.pixelSize, GUILayout.Width(120f)); if (pixelSize != mAtlas.pixelSize) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.pixelSize = pixelSize; mConfirmDelete = false; } } } if (mAtlas.spriteMaterial != null) { Color blue = new Color(0f, 0.7f, 1f, 1f); Color green = new Color(0.4f, 1f, 0f, 1f); if (mConfirmDelete) { if (mSprite != null) { // Show the confirmation dialog NGUIEditorTools.DrawSeparator(); GUILayout.Label("Are you sure you want to delete '" + mSprite.name + "'?"); NGUIEditorTools.DrawSeparator(); GUILayout.BeginHorizontal(); { GUI.backgroundColor = Color.green; if (GUILayout.Button("Cancel")) { mConfirmDelete = false; } GUI.backgroundColor = Color.red; if (GUILayout.Button("Delete")) { NGUIEditorTools.RegisterUndo("Delete Sprite", mAtlas); mAtlas.spriteList.Remove(mSprite); mConfirmDelete = false; } GUI.backgroundColor = Color.white; } GUILayout.EndHorizontal(); } else { mConfirmDelete = false; } } else { if (mSprite == null && mAtlas.spriteList.Count > 0) { string spriteName = EditorPrefs.GetString("NGUI Selected Sprite"); if (!string.IsNullOrEmpty(spriteName)) { mSprite = mAtlas.GetSprite(spriteName); } if (mSprite == null) { mSprite = mAtlas.spriteList[0]; } } if (!mConfirmDelete && mSprite != null) { NGUIEditorTools.DrawSeparator(); NGUIEditorTools.AdvancedSpriteField(mAtlas, mSprite.name, SelectSprite, true); if (mSprite == null) { return; } Texture2D tex = mAtlas.spriteMaterial.mainTexture as Texture2D; if (tex != null) { Rect inner = mSprite.inner; Rect outer = mSprite.outer; if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { GUI.backgroundColor = green; outer = NGUIEditorTools.IntRect("Dimensions", mSprite.outer); Vector4 border = new Vector4( mSprite.inner.xMin - mSprite.outer.xMin, mSprite.inner.yMin - mSprite.outer.yMin, mSprite.outer.xMax - mSprite.inner.xMax, mSprite.outer.yMax - mSprite.inner.yMax); GUI.backgroundColor = blue; border = NGUIEditorTools.IntPadding("Border", border); GUI.backgroundColor = Color.white; inner.xMin = mSprite.outer.xMin + border.x; inner.yMin = mSprite.outer.yMin + border.y; inner.xMax = mSprite.outer.xMax - border.z; inner.yMax = mSprite.outer.yMax - border.w; } else { // Draw the inner and outer rectangle dimensions GUI.backgroundColor = green; outer = EditorGUILayout.RectField("Outer Rect", mSprite.outer); GUI.backgroundColor = blue; inner = EditorGUILayout.RectField("Inner Rect", mSprite.inner); GUI.backgroundColor = Color.white; } if (outer.xMax < outer.xMin) { outer.xMax = outer.xMin; } if (outer.yMax < outer.yMin) { outer.yMax = outer.yMin; } if (outer != mSprite.outer) { float x = outer.xMin - mSprite.outer.xMin; float y = outer.yMin - mSprite.outer.yMin; inner.x += x; inner.y += y; } // Sanity checks to ensure that the inner rect is always inside the outer inner.xMin = Mathf.Clamp(inner.xMin, outer.xMin, outer.xMax); inner.xMax = Mathf.Clamp(inner.xMax, outer.xMin, outer.xMax); inner.yMin = Mathf.Clamp(inner.yMin, outer.yMin, outer.yMax); inner.yMax = Mathf.Clamp(inner.yMax, outer.yMin, outer.yMax); bool changed = false; if (mSprite.inner != inner || mSprite.outer != outer) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mSprite.inner = inner; mSprite.outer = outer; MarkSpriteAsDirty(); changed = true; } EditorGUILayout.Separator(); if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { int left = Mathf.RoundToInt(mSprite.paddingLeft * mSprite.outer.width); int right = Mathf.RoundToInt(mSprite.paddingRight * mSprite.outer.width); int top = Mathf.RoundToInt(mSprite.paddingTop * mSprite.outer.height); int bottom = Mathf.RoundToInt(mSprite.paddingBottom * mSprite.outer.height); NGUIEditorTools.IntVector a = NGUIEditorTools.IntPair("Padding", "Left", "Top", left, top); NGUIEditorTools.IntVector b = NGUIEditorTools.IntPair(null, "Right", "Bottom", right, bottom); if (changed || a.x != left || a.y != top || b.x != right || b.y != bottom) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mSprite.paddingLeft = a.x / mSprite.outer.width; mSprite.paddingTop = a.y / mSprite.outer.height; mSprite.paddingRight = b.x / mSprite.outer.width; mSprite.paddingBottom = b.y / mSprite.outer.height; MarkSpriteAsDirty(); } } else { // Create a button that can make the coordinates pixel-perfect on click GUILayout.BeginHorizontal(); { GUILayout.Label("Correction", GUILayout.Width(75f)); Rect corrected0 = outer; Rect corrected1 = inner; if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { corrected0 = NGUIMath.MakePixelPerfect(corrected0); corrected1 = NGUIMath.MakePixelPerfect(corrected1); } else { corrected0 = NGUIMath.MakePixelPerfect(corrected0, tex.width, tex.height); corrected1 = NGUIMath.MakePixelPerfect(corrected1, tex.width, tex.height); } if (corrected0 == mSprite.outer && corrected1 == mSprite.inner) { GUI.color = Color.grey; GUILayout.Button("Make Pixel-Perfect"); GUI.color = Color.white; } else if (GUILayout.Button("Make Pixel-Perfect")) { outer = corrected0; inner = corrected1; GUI.changed = true; } } GUILayout.EndHorizontal(); } } // This functionality is no longer used. It became obsolete when the Atlas Maker was added. /*NGUIEditorTools.DrawSeparator(); * * GUILayout.BeginHorizontal(); * { * EditorGUILayout.PrefixLabel("Add/Delete"); * * if (GUILayout.Button("Clone Sprite")) * { * NGUIEditorTools.RegisterUndo("Add Sprite", mAtlas); * NGUIAtlas.Sprite newSprite = new NGUIAtlas.Sprite(); * * if (mSprite != null) * { * newSprite.name = "Copy of " + mSprite.name; * newSprite.outer = mSprite.outer; * newSprite.inner = mSprite.inner; * } * else * { * newSprite.name = "New Sprite"; * } * * mAtlas.spriteList.Add(newSprite); * mSprite = newSprite; * } * * // Show the delete button * GUI.backgroundColor = Color.red; * * if (mSprite != null && GUILayout.Button("Delete", GUILayout.Width(55f))) * { * mConfirmDelete = true; * } * GUI.backgroundColor = Color.white; * } * GUILayout.EndHorizontal();*/ if (NGUIEditorTools.previousSelection != null) { NGUIEditorTools.DrawSeparator(); GUI.backgroundColor = Color.green; if (GUILayout.Button("<< Return to " + NGUIEditorTools.previousSelection.name)) { NGUIEditorTools.SelectPrevious(); } GUI.backgroundColor = Color.white; } } } } }
/// <summary> /// Draw the inspector widget. /// </summary> public override void OnInspectorGUI() { EditorGUIUtility.LookLikeControls(80f); mAtlas = target as NGUIAtlas; NGUIEditorTools.DrawSeparator(); if (mAtlas.replacement != null) { mType = AtlasType.Reference; mReplacement = mAtlas.replacement; } AtlasType after = (AtlasType)EditorGUILayout.EnumPopup("Atlas Type", mType); if (mType != after) { if (after == AtlasType.Normal) { OnSelectAtlas(null); } else { mType = AtlasType.Reference; } } if (mType == AtlasType.Reference) { ComponentSelector.Draw<NGUIAtlas>(mAtlas.replacement, OnSelectAtlas); NGUIEditorTools.DrawSeparator(); EditorGUILayout.HelpBox("You can have one atlas simply point to " + "another one. This is useful if you want to be " + "able to quickly replace the contents of one " + "atlas with another one, for example for " + "swapping an SD atlas with an HD one, or " + "replacing an English atlas with a Chinese " + "one. All the sprites referencing this atlas " + "will update their references to the new one.", MessageType.Info); if (mReplacement != mAtlas && mAtlas.replacement != mReplacement) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.replacement = mReplacement; UnityEditor.EditorUtility.SetDirty(mAtlas); } return; } if (!mConfirmDelete) { NGUIEditorTools.DrawSeparator(); Material mat = EditorGUILayout.ObjectField("Material", mAtlas.spriteMaterial, typeof(Material), false) as Material; if (mAtlas.spriteMaterial != mat) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.spriteMaterial = mat; // Ensure that this atlas has valid import settings if (mAtlas.texture != null) NGUIEditorTools.ImportTexture(mAtlas.texture, false, false); mAtlas.MarkAsDirty(); mConfirmDelete = false; } if (mat != null) { TextAsset ta = EditorGUILayout.ObjectField("TP Import", null, typeof(TextAsset), false) as TextAsset; if (ta != null) { // Ensure that this atlas has valid import settings if (mAtlas.texture != null) NGUIEditorTools.ImportTexture(mAtlas.texture, false, false); NGUIEditorTools.RegisterUndo("Import Sprites", mAtlas); NGUIJson.LoadSpriteData(mAtlas, ta); if (mSprite != null) mSprite = mAtlas.GetSprite(mSprite.name); mAtlas.MarkAsDirty(); } NGUIAtlas.Coordinates coords = (NGUIAtlas.Coordinates)EditorGUILayout.EnumPopup("Coordinates", mAtlas.coordinates); if (coords != mAtlas.coordinates) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.coordinates = coords; mConfirmDelete = false; } float pixelSize = EditorGUILayout.FloatField("Pixel Size", mAtlas.pixelSize, GUILayout.Width(120f)); if (pixelSize != mAtlas.pixelSize) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mAtlas.pixelSize = pixelSize; mConfirmDelete = false; } } } if (mAtlas.spriteMaterial != null) { Color blue = new Color(0f, 0.7f, 1f, 1f); Color green = new Color(0.4f, 1f, 0f, 1f); if (mConfirmDelete) { if (mSprite != null) { // Show the confirmation dialog NGUIEditorTools.DrawSeparator(); GUILayout.Label("Are you sure you want to delete '" + mSprite.name + "'?"); NGUIEditorTools.DrawSeparator(); GUILayout.BeginHorizontal(); { GUI.backgroundColor = Color.green; if (GUILayout.Button("Cancel")) mConfirmDelete = false; GUI.backgroundColor = Color.red; if (GUILayout.Button("Delete")) { NGUIEditorTools.RegisterUndo("Delete Sprite", mAtlas); mAtlas.spriteList.Remove(mSprite); mConfirmDelete = false; } GUI.backgroundColor = Color.white; } GUILayout.EndHorizontal(); } else mConfirmDelete = false; } else { if (mSprite == null && mAtlas.spriteList.Count > 0) { string spriteName = EditorPrefs.GetString("NGUI Selected Sprite"); if (!string.IsNullOrEmpty(spriteName)) mSprite = mAtlas.GetSprite(spriteName); if (mSprite == null) mSprite = mAtlas.spriteList[0]; } if (!mConfirmDelete && mSprite != null) { NGUIEditorTools.DrawSeparator(); NGUIEditorTools.AdvancedSpriteField(mAtlas, mSprite.name, SelectSprite, true); if (mSprite == null) return; Texture2D tex = mAtlas.spriteMaterial.mainTexture as Texture2D; if (tex != null) { Rect inner = mSprite.inner; Rect outer = mSprite.outer; if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { GUI.backgroundColor = green; outer = NGUIEditorTools.IntRect("Dimensions", mSprite.outer); Vector4 border = new Vector4( mSprite.inner.xMin - mSprite.outer.xMin, mSprite.inner.yMin - mSprite.outer.yMin, mSprite.outer.xMax - mSprite.inner.xMax, mSprite.outer.yMax - mSprite.inner.yMax); GUI.backgroundColor = blue; border = NGUIEditorTools.IntPadding("Border", border); GUI.backgroundColor = Color.white; inner.xMin = mSprite.outer.xMin + border.x; inner.yMin = mSprite.outer.yMin + border.y; inner.xMax = mSprite.outer.xMax - border.z; inner.yMax = mSprite.outer.yMax - border.w; } else { // Draw the inner and outer rectangle dimensions GUI.backgroundColor = green; outer = EditorGUILayout.RectField("Outer Rect", mSprite.outer); GUI.backgroundColor = blue; inner = EditorGUILayout.RectField("Inner Rect", mSprite.inner); GUI.backgroundColor = Color.white; } if (outer.xMax < outer.xMin) outer.xMax = outer.xMin; if (outer.yMax < outer.yMin) outer.yMax = outer.yMin; if (outer != mSprite.outer) { float x = outer.xMin - mSprite.outer.xMin; float y = outer.yMin - mSprite.outer.yMin; inner.x += x; inner.y += y; } // Sanity checks to ensure that the inner rect is always inside the outer inner.xMin = Mathf.Clamp(inner.xMin, outer.xMin, outer.xMax); inner.xMax = Mathf.Clamp(inner.xMax, outer.xMin, outer.xMax); inner.yMin = Mathf.Clamp(inner.yMin, outer.yMin, outer.yMax); inner.yMax = Mathf.Clamp(inner.yMax, outer.yMin, outer.yMax); bool changed = false; if (mSprite.inner != inner || mSprite.outer != outer) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mSprite.inner = inner; mSprite.outer = outer; MarkSpriteAsDirty(); changed = true; } EditorGUILayout.Separator(); if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { int left = Mathf.RoundToInt(mSprite.paddingLeft * mSprite.outer.width); int right = Mathf.RoundToInt(mSprite.paddingRight * mSprite.outer.width); int top = Mathf.RoundToInt(mSprite.paddingTop * mSprite.outer.height); int bottom = Mathf.RoundToInt(mSprite.paddingBottom * mSprite.outer.height); NGUIEditorTools.IntVector a = NGUIEditorTools.IntPair("Padding", "Left", "Top", left, top); NGUIEditorTools.IntVector b = NGUIEditorTools.IntPair(null, "Right", "Bottom", right, bottom); if (changed || a.x != left || a.y != top || b.x != right || b.y != bottom) { NGUIEditorTools.RegisterUndo("Atlas Change", mAtlas); mSprite.paddingLeft = a.x / mSprite.outer.width; mSprite.paddingTop = a.y / mSprite.outer.height; mSprite.paddingRight = b.x / mSprite.outer.width; mSprite.paddingBottom = b.y / mSprite.outer.height; MarkSpriteAsDirty(); } } else { // Create a button that can make the coordinates pixel-perfect on click GUILayout.BeginHorizontal(); { GUILayout.Label("Correction", GUILayout.Width(75f)); Rect corrected0 = outer; Rect corrected1 = inner; if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { corrected0 = NGUIMath.MakePixelPerfect(corrected0); corrected1 = NGUIMath.MakePixelPerfect(corrected1); } else { corrected0 = NGUIMath.MakePixelPerfect(corrected0, tex.width, tex.height); corrected1 = NGUIMath.MakePixelPerfect(corrected1, tex.width, tex.height); } if (corrected0 == mSprite.outer && corrected1 == mSprite.inner) { GUI.color = Color.grey; GUILayout.Button("Make Pixel-Perfect"); GUI.color = Color.white; } else if (GUILayout.Button("Make Pixel-Perfect")) { outer = corrected0; inner = corrected1; GUI.changed = true; } } GUILayout.EndHorizontal(); } } // This functionality is no longer used. It became obsolete when the Atlas Maker was added. /*NGUIEditorTools.DrawSeparator(); GUILayout.BeginHorizontal(); { EditorGUILayout.PrefixLabel("Add/Delete"); if (GUILayout.Button("Clone Sprite")) { NGUIEditorTools.RegisterUndo("Add Sprite", mAtlas); NGUIAtlas.Sprite newSprite = new NGUIAtlas.Sprite(); if (mSprite != null) { newSprite.name = "Copy of " + mSprite.name; newSprite.outer = mSprite.outer; newSprite.inner = mSprite.inner; } else { newSprite.name = "New Sprite"; } mAtlas.spriteList.Add(newSprite); mSprite = newSprite; } // Show the delete button GUI.backgroundColor = Color.red; if (mSprite != null && GUILayout.Button("Delete", GUILayout.Width(55f))) { mConfirmDelete = true; } GUI.backgroundColor = Color.white; } GUILayout.EndHorizontal();*/ if (NGUIEditorTools.previousSelection != null) { NGUIEditorTools.DrawSeparator(); GUI.backgroundColor = Color.green; if (GUILayout.Button("<< Return to " + NGUIEditorTools.previousSelection.name)) { NGUIEditorTools.SelectPrevious(); } GUI.backgroundColor = Color.white; } } } } }
/// <summary> /// Parse the specified JSon file, loading sprite information for the specified atlas. /// </summary> public static void LoadSpriteData(NGUIAtlas atlas, TextAsset asset) { if (asset == null || atlas == null) { return; } string jsonString = asset.text; Hashtable decodedHash = jsonDecode(jsonString) as Hashtable; if (decodedHash == null) { Debug.LogWarning("Unable to parse Json file: " + asset.name); return; } atlas.coordinates = NGUIAtlas.Coordinates.Pixels; List <NGUIAtlas.Sprite> oldSprites = atlas.spriteList; atlas.spriteList = new List <NGUIAtlas.Sprite>(); Hashtable frames = (Hashtable)decodedHash["frames"]; foreach (System.Collections.DictionaryEntry item in frames) { NGUIAtlas.Sprite newSprite = new NGUIAtlas.Sprite(); newSprite.name = item.Key.ToString(); bool exists = false; // Check to see if this sprite exists foreach (NGUIAtlas.Sprite oldSprite in oldSprites) { if (oldSprite.name.Equals(newSprite.name, StringComparison.OrdinalIgnoreCase)) { exists = true; break; } } // Get rid of the extension if the sprite doesn't exist // The extension is kept for backwards compatibility so it's still possible to update older atlases. if (!exists) { newSprite.name = newSprite.name.Replace(".png", ""); newSprite.name = newSprite.name.Replace(".tga", ""); } // Extract the info we need from the TexturePacker json file, mainly uvRect and size Hashtable table = (Hashtable)item.Value; Hashtable frame = (Hashtable)table["frame"]; int frameX = int.Parse(frame["x"].ToString()); int frameY = int.Parse(frame["y"].ToString()); int frameW = int.Parse(frame["w"].ToString()); int frameH = int.Parse(frame["h"].ToString()); // Read the rotation value newSprite.rotated = (bool)table["rotated"]; // Fill in the proper values if (newSprite.rotated) { newSprite.outer = new Rect(frameX, frameY, frameH, frameW); newSprite.inner = new Rect(frameX, frameY, frameH, frameW); } else { newSprite.outer = new Rect(frameX, frameY, frameW, frameH); newSprite.inner = new Rect(frameX, frameY, frameW, frameH); } // Support for trimmed sprites Hashtable sourceSize = (Hashtable)table["sourceSize"]; Hashtable spriteSize = (Hashtable)table["spriteSourceSize"]; if (spriteSize != null && sourceSize != null) { // TODO: Account for rotated sprites if (frameW > 0) { float spriteX = int.Parse(spriteSize["x"].ToString()); float spriteW = int.Parse(spriteSize["w"].ToString()); float sourceW = int.Parse(sourceSize["w"].ToString()); newSprite.paddingLeft = spriteX / frameW; newSprite.paddingRight = (sourceW - (spriteX + spriteW)) / frameW; } if (frameH > 0) { float spriteY = int.Parse(spriteSize["y"].ToString()); float spriteH = int.Parse(spriteSize["h"].ToString()); float sourceH = int.Parse(sourceSize["h"].ToString()); newSprite.paddingTop = spriteY / frameH; newSprite.paddingBottom = (sourceH - (spriteY + spriteH)) / frameH; } } // If the sprite was present before, see if we can copy its inner rect foreach (NGUIAtlas.Sprite oldSprite in oldSprites) { if (oldSprite.name.Equals(newSprite.name, StringComparison.OrdinalIgnoreCase)) { CopyInnerRect(oldSprite, newSprite); } } // Add this new sprite atlas.spriteList.Add(newSprite); } // Sort imported sprites alphabetically atlas.spriteList.Sort(CompareSprites); Debug.Log("Imported " + atlas.spriteList.Count + " sprites"); // Unload the asset asset = null; Resources.UnloadUnusedAssets(); }
/// <summary> /// Sprite comparison function for sorting. /// </summary> static int CompareSprites(NGUIAtlas.Sprite a, NGUIAtlas.Sprite b) { return(a.name.CompareTo(b.name)); }
/// <summary> /// Retrieve the atlas sprite referenced by the spriteName field. /// </summary> public NGUIAtlas.Sprite GetAtlasSprite() { if (!mSpriteSet) mSprite = null; if (mSprite == null && mAtlas != null) { if (!string.IsNullOrEmpty(mSpriteName)) { NGUIAtlas.Sprite sp = mAtlas.GetSprite(mSpriteName); if (sp == null) return null; SetAtlasSprite(sp); } if (mSprite == null && mAtlas.spriteList.Count > 0) { NGUIAtlas.Sprite sp = mAtlas.spriteList[0]; if (sp == null) return null; SetAtlasSprite(sp); if (mSprite == null) { Debug.LogError(mAtlas.name + " seems to have a null sprite!"); return null; } mSpriteName = mSprite.name; } // If the sprite has been set, update the material if (mSprite != null) { material = mAtlas.spriteMaterial; UpdateUVs(true); } } return mSprite; }
/// <summary> /// Validate this symbol, given the specified atlas. /// </summary> public bool Validate(NGUIAtlas atlas) { if (atlas == null) return false; #if UNITY_EDITOR if (!Application.isPlaying || !mIsValid) #else if (!mIsValid) #endif { if (string.IsNullOrEmpty(spriteName)) return false; mSprite = (atlas != null) ? atlas.GetSprite(spriteName) : null; if (mSprite != null) { Texture tex = atlas.texture; if (tex == null) { mSprite = null; } else { Rect outer = mSprite.outer; mUV = outer; if (atlas.coordinates == NGUIAtlas.Coordinates.Pixels) { mUV = NGUIMath.ConvertToTexCoords(mUV, tex.width, tex.height); } else { outer = NGUIMath.ConvertToPixels(outer, tex.width, tex.height, true); } mOffsetX = Mathf.RoundToInt(mSprite.paddingLeft * outer.width); mOffsetY = Mathf.RoundToInt(mSprite.paddingTop * outer.width); mWidth = Mathf.RoundToInt(outer.width); mHeight = Mathf.RoundToInt(outer.height); mAdvance = Mathf.RoundToInt(outer.width + (mSprite.paddingRight + mSprite.paddingLeft) * outer.width); mIsValid = true; } } } return (mSprite != null); }
/// <summary> /// Refresh all labels that use this font. /// </summary> public void MarkAsDirty() { #if UNITY_EDITOR UnityEditor.EditorUtility.SetDirty(gameObject); #endif if (mReplacement != null) mReplacement.MarkAsDirty(); if (mDynamicFontOffset == 0f) { RecalculateDynamicOffset(); } mSprite = null; NGUILabel[] labels = NGUITools.FindActive<NGUILabel>(); for (int i = 0, imax = labels.Length; i < imax; ++i) { NGUILabel lbl = labels[i]; /* if (lbl.enabled && NGUITools.GetActive(lbl.gameObject) && CheckIfRelated(this, lbl.font)) { NGUIFont fnt = lbl.font; lbl.font = null; lbl.font = fnt; } */ lbl.MarkAsChanged(); } // Clear all symbols for (int i = 0, imax = mSymbols.Count; i < imax; ++i) symbols[i].MarkAsDirty(); }
/// <summary> /// Draw the custom wizard. /// </summary> void OnGUI() { EditorGUIUtility.LookLikeControls(80f); if (mAtlas == null) { GUILayout.Label("No Atlas selected.", "LODLevelNotifyText"); } else { bool close = false; GUILayout.Label(mAtlas.name + " Sprites", "LODLevelNotifyText"); NGUIEditorTools.DrawSeparator(); GUILayout.BeginHorizontal(); GUILayout.Space(84f); string before = NGUISettings.partialSprite; string after = EditorGUILayout.TextField("", before, "SearchTextField"); NGUISettings.partialSprite = after; if (GUILayout.Button("", "SearchCancelButton", GUILayout.Width(18f))) { NGUISettings.partialSprite = ""; GUIUtility.keyboardControl = 0; } GUILayout.Space(84f); GUILayout.EndHorizontal(); Texture2D tex = mAtlas.texture as Texture2D; if (tex == null) { GUILayout.Label("The atlas doesn't have a texture to work with"); return; } BetterList <string> sprites = mAtlas.GetListOfSprites(NGUISettings.partialSprite); float size = 80f; float padded = size + 10f; int columns = Mathf.FloorToInt(Screen.width / padded); if (columns < 1) { columns = 1; } int offset = 0; Rect rect = new Rect(10f, 0, size, size); GUILayout.Space(10f); mPos = GUILayout.BeginScrollView(mPos); while (offset < sprites.size) { GUILayout.BeginHorizontal(); { int col = 0; rect.x = 10f; for (; offset < sprites.size; ++offset) { NGUIAtlas.Sprite sprite = mAtlas.GetSprite(sprites[offset]); if (sprite == null) { continue; } // Button comes first if (GUI.Button(rect, "")) { float delta = Time.realtimeSinceStartup - mClickTime; mClickTime = Time.realtimeSinceStartup; if (spriteName != sprite.name) { if (mSprite != null) { NGUIEditorTools.RegisterUndo("Atlas Selection", mSprite); mSprite.spriteName = sprite.name; mSprite.MakePixelPerfect(); EditorUtility.SetDirty(mSprite.gameObject); } else if (mCallback != null) { mName = sprite.name; mCallback(sprite.name); } } else if (delta < 0.5f) { close = true; } } if (Event.current.type == EventType.Repaint) { // On top of the button we have a checkboard grid NGUIEditorTools.DrawTiledTexture(rect, NGUIEditorTools.backdropTexture); Rect uv = sprite.outer; if (mAtlas.coordinates == NGUIAtlas.Coordinates.Pixels) { uv = NGUIMath.ConvertToTexCoords(uv, tex.width, tex.height); } // Calculate the texture's scale that's needed to display the sprite in the clipped area float scaleX = rect.width / uv.width; float scaleY = rect.height / uv.height; // Stretch the sprite so that it will appear proper float aspect = (scaleY / scaleX) / ((float)tex.height / tex.width); Rect clipRect = rect; if (aspect != 1f) { if (aspect < 1f) { // The sprite is taller than it is wider float padding = size * (1f - aspect) * 0.5f; clipRect.xMin += padding; clipRect.xMax -= padding; } else { // The sprite is wider than it is taller float padding = size * (1f - 1f / aspect) * 0.5f; clipRect.yMin += padding; clipRect.yMax -= padding; } } GUI.DrawTextureWithTexCoords(clipRect, tex, uv); // Draw the selection if (spriteName == sprite.name) { NGUIEditorTools.DrawOutline(rect, new Color(0.4f, 1f, 0f, 1f)); } } if (++col >= columns) { ++offset; break; } rect.x += padded; } } GUILayout.EndHorizontal(); GUILayout.Space(padded); rect.y += padded; } GUILayout.EndScrollView(); if (close) { Close(); } } }
/// <summary> /// Update the UV coordinates. /// </summary> public override bool OnUpdate() { if (mChanged || !mSpriteSet) { mSpriteSet = true; mSprite = null; mChanged = true; UpdateUVs(true); return true; } UpdateUVs(false); return false; }
/// <summary> /// Display the drop-down list when the game object gets clicked on. /// </summary> void OnClick() { if (mChild == null && atlas != null && font != null && items.Count > 0) { mLabelList.Clear(); // Disable the navigation script handleEvents = true; // Automatically locate the panel responsible for this object if (mPanel == null) { mPanel = NGUIPanel.Find(transform, true); } // Calculate the dimensions of the object triggering the popup list so we can position it below it Transform myTrans = transform; Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(myTrans.parent, myTrans); // Create the root object for the list mChild = new GameObject("Drop-down List"); mChild.layer = gameObject.layer; Transform t = mChild.transform; t.parent = myTrans.parent; t.localPosition = bounds.min; t.localRotation = Quaternion.identity; t.localScale = Vector3.one; // Add a sprite for the background mBackground = NGUITools.AddSprite(mChild, atlas, backgroundSprite); mBackground.pivot = NGUIWidget.Pivot.TopLeft; mBackground.depth = NGUITools.CalculateNextDepth(mPanel.gameObject); mBackground.color = backgroundColor; // We need to know the size of the background sprite for padding purposes Vector4 bgPadding = mBackground.border; mBgBorder = bgPadding.y; mBackground.cachedTransform.localPosition = new Vector3(0f, bgPadding.y, 0f); // Add a sprite used for the selection mHighlight = NGUITools.AddSprite(mChild, atlas, highlightSprite); mHighlight.pivot = NGUIWidget.Pivot.TopLeft; mHighlight.color = highlightColor; NGUIAtlas.Sprite hlsp = mHighlight.GetAtlasSprite(); if (hlsp == null) { return; } float hlspHeight = hlsp.inner.yMin - hlsp.outer.yMin; float fontScale = font.size * font.pixelSize * textScale; float x = 0f, y = -padding.y; List <NGUILabel> labels = new List <NGUILabel>(); // Run through all items and create labels for each one for (int i = 0, imax = items.Count; i < imax; ++i) { string s = items[i]; NGUILabel lbl = NGUITools.AddWidget <NGUILabel>(mChild); lbl.pivot = NGUIWidget.Pivot.TopLeft; lbl.font = font; lbl.text = (isLocalized && Localization.instance != null) ? Localization.instance.Get(s) : s; lbl.color = textColor; lbl.cachedTransform.localPosition = new Vector3(bgPadding.x + padding.x, y, -0.01f); lbl.MakePixelPerfect(); if (textScale != 1f) { Vector3 scale = lbl.cachedTransform.localScale; lbl.cachedTransform.localScale = scale * textScale; } labels.Add(lbl); y -= fontScale; y -= padding.y; x = Mathf.Max(x, lbl.relativeSize.x * fontScale); // Add an event listener NGUIEventListener listener = NGUIEventListener.Get(lbl.gameObject); listener.onHover = OnItemHover; listener.onPress = OnItemPress; listener.parameter = s; // Move the selection here if this is the right label if (mSelectedItem == s) { Highlight(lbl, true); } // Add this label to the list mLabelList.Add(lbl); } // The triggering widget's width should be the minimum allowed width x = Mathf.Max(x, bounds.size.x - (bgPadding.x + padding.x) * 2f); Vector3 bcCenter = new Vector3((x * 0.5f) / fontScale, -0.5f, 0f); Vector3 bcSize = new Vector3(x / fontScale, (fontScale + padding.y) / fontScale, 1f); // Run through all labels and add colliders for (int i = 0, imax = labels.Count; i < imax; ++i) { NGUILabel lbl = labels[i]; BoxCollider bc = NGUITools.AddWidgetCollider(lbl.gameObject); bcCenter.z = bc.center.z; bc.center = bcCenter; bc.size = bcSize; } x += (bgPadding.x + padding.x) * 2f; y -= bgPadding.y; // Scale the background sprite to envelop the entire set of items mBackground.cachedTransform.localScale = new Vector3(x, -y + bgPadding.y, 1f); // Scale the highlight sprite to envelop a single item mHighlight.cachedTransform.localScale = new Vector3( x - (bgPadding.x + padding.x) * 2f + (hlsp.inner.xMin - hlsp.outer.xMin) * 2f, fontScale + hlspHeight * 2f, 1f); bool placeAbove = (position == Position.Above); if (position == Position.Auto) { NGUICamera cam = NGUICamera.FindCameraForLayer(gameObject.layer); if (cam != null) { Vector3 viewPos = cam.cachedCamera.WorldToViewportPoint(myTrans.position); placeAbove = (viewPos.y < 0.5f); } } // If the list should be animated, let's animate it by expanding it if (isAnimated) { float bottom = y + fontScale; Animate(mHighlight, placeAbove, bottom); for (int i = 0, imax = labels.Count; i < imax; ++i) { Animate(labels[i], placeAbove, bottom); } AnimateColor(mBackground); AnimateScale(mBackground, placeAbove, bottom); } // If we need to place the popup list above the item, we need to reposition everything by the size of the list if (placeAbove) { t.localPosition = new Vector3(bounds.min.x, bounds.max.y - y - bgPadding.y, bounds.min.z); } } else { OnSelect(false); } }