/// <summary> /// The minimum bounds needed to hold the visible sprites. /// </summary> /// <returns>The bounds.</returns> public PixelBounds GetTrimmedSpriteBounds() { PixelBounds bounds = new PixelBounds(); bounds.x = int.MaxValue; bounds.y = int.MaxValue; int maxX = int.MinValue; int maxY = int.MinValue; // grab the list of visible sprites List <UnitySpriteLayer> spriteLayers = GetSelectedSpriteLayers(); foreach (UnitySpriteLayer spriteLayer in spriteLayers) { PixelBounds layerBounds = spriteLayer.layer.bounds; bounds.x = System.Math.Min(bounds.x, layerBounds.x); bounds.y = System.Math.Min(bounds.y, layerBounds.y); maxX = System.Math.Max(maxX, layerBounds.x + layerBounds.width); maxY = System.Math.Max(maxY, layerBounds.y + layerBounds.height); } bounds.width = maxX - bounds.x; bounds.height = maxY - bounds.y; return(bounds); }
/// <summary> /// Reads some bounds from a dictionary. /// </summary> /// <param name="key">The key to look up</param> /// <param name="dictionary">The dictionary to read from.</param> /// <returns>Bounds or bust.</returns> static PixelBounds ReadBoundsFromDictionary(string key, Dictionary <string, object> dictionary) { // sanity if (dictionary == null || key == null) { return(null); } // missing key if (!dictionary.ContainsKey(key)) { return(null); } // grab the sub dictionary with the bounds info PixelBounds bounds = null; try { Dictionary <string, object> subDictionary = dictionary[key] as Dictionary <string, object>; bounds = new PixelBounds(); bounds.x = ReadIntFromDictionary("left", subDictionary, 0); bounds.y = ReadIntFromDictionary("top", subDictionary, 0); bounds.width = ReadIntFromDictionary("right", subDictionary, 0) - bounds.x; bounds.height = ReadIntFromDictionary("bottom", subDictionary, 0) - bounds.y; } catch { // shrug } return(bounds); }
/// <summary> /// Get the pixel position of the sprite. /// </summary> /// <returns>A Vector3.</returns> public Vector3 GetPixelPosition(float coordinatesScale, PixelBounds fromBounds) { if (!hasSprite) { return(Vector3.zero); } // figure out the placement Vector2 layerCenter = layer.bounds.GetCenter(); float x = (layerCenter.x - fromBounds.x) * coordinatesScale; float y = (fromBounds.height - layerCenter.y + fromBounds.y) * coordinatesScale; float z = this.z; // adjust for pivots (literally a day to figure this out... i fail so hard) Vector3 spriteCenter = bounds.center; Vector3 spriteExtents = bounds.extents; float pivotX = spriteCenter.x / -spriteExtents.x * (layer.bounds.halfWidth * coordinatesScale); float pivotY = spriteCenter.y / -spriteExtents.y * (layer.bounds.halfHeight * coordinatesScale); Vector2 pivotOffset = new Vector2(pivotX, pivotY); x += pivotOffset.x; y += pivotOffset.y; return(new Vector3(x, y, z)); }
/// <summary> /// Add an optional collider to the root. /// </summary> /// <param name="root">The root</param> public void ApplyRootCollider(GameObject root) { // sanity if (layout == null || root == null || layout.rootCollider == ColliderStyle.None) { return; } // are we a sprite? bool isSprite = root.GetComponent <SpriteRenderer>() != null; // grab the size of the collider PixelBounds bounds = layout.trimToSprites ? layout.trimmedSpriteBounds : layout.document.bounds; Vector2 colliderSize = new Vector2(bounds.width * layout.coordinatesScale * (1f / layout.pixelsToUnits), bounds.height * layout.coordinatesScale * (1f / layout.pixelsToUnits)); // grab the center of the collider Vector2 colliderCenter = new Vector2(bounds.width, bounds.height); switch (layout.anchor) { case TextAnchor.LowerCenter: colliderCenter.x = colliderCenter.x * 0f; colliderCenter.y = colliderCenter.y * 0.5f; break; case TextAnchor.LowerLeft: colliderCenter.x = colliderCenter.x * 0.5f; colliderCenter.y = colliderCenter.y * 0.5f; break; case TextAnchor.LowerRight: colliderCenter.x = colliderCenter.x * -0.5f; colliderCenter.y = colliderCenter.y * 0.5f; break; case TextAnchor.MiddleCenter: colliderCenter.x = colliderCenter.x * 0f; colliderCenter.y = colliderCenter.y * 0f; break; case TextAnchor.MiddleLeft: colliderCenter.x = colliderCenter.x * 0.5f; colliderCenter.y = colliderCenter.y * 0f; break; case TextAnchor.MiddleRight: colliderCenter.x = colliderCenter.x * -0.5f; colliderCenter.y = colliderCenter.y * 0f; break; case TextAnchor.UpperCenter: colliderCenter.x = colliderCenter.x * 0f; colliderCenter.y = colliderCenter.y * -0.5f; break; case TextAnchor.UpperLeft: colliderCenter.x = colliderCenter.x * 0.5f; colliderCenter.y = colliderCenter.y * -0.5f; break; case TextAnchor.UpperRight: colliderCenter.x = colliderCenter.x * -0.5f; colliderCenter.y = colliderCenter.y * -0.5f; break; default: break; } colliderCenter = new Vector2(colliderCenter.x * layout.coordinatesScale * (1f / layout.pixelsToUnits), colliderCenter.y * layout.coordinatesScale * (1f / layout.pixelsToUnits)); // check for existing box colliders BoxCollider existingBoxCollider = root.GetComponent <BoxCollider>(); BoxCollider2D existingBoxCollider2D = root.GetComponent <BoxCollider2D>(); // do we have an existing box collider? if (existingBoxCollider != null || existingBoxCollider2D != null) { // refresh the BoxCollider size if (existingBoxCollider != null) { existingBoxCollider.size = new Vector3(colliderSize.x, colliderSize.y, existingBoxCollider.size.z); existingBoxCollider.center = new Vector3(colliderCenter.x, colliderCenter.y, existingBoxCollider.center.z); } // refresh the BoxCollider2D size if (existingBoxCollider2D != null) { existingBoxCollider2D.size = colliderSize; #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 existingBoxCollider2D.center = colliderCenter; #else existingBoxCollider2D.offset = colliderCenter; #endif } // we're done. return; } // check for existing colliders if (root.GetComponent <Collider2D>() != null || root.GetComponent <Collider>() != null) { Debug.LogWarning("Ps2D detected conflicting colliders on the root GameObject. Skipping collider creation."); return; } // check for conflicting rigid bodies bool conflictRigidBody = root.GetComponent <Rigidbody2D>() != null && layout.rootCollider == ColliderStyle.BoxCollider; bool conflictRigidBody2D = root.GetComponent <Rigidbody>() != null && layout.rootCollider == ColliderStyle.BoxCollider2D; // conflict detected if (conflictRigidBody || conflictRigidBody2D) { Debug.LogWarning("Ps2D detected conflicting rigid bodies. Skipping collider creation."); return; } // add the new collider safely try { // 2D collider if (layout.rootCollider == ColliderStyle.BoxCollider2D) { var collider = root.AddComponent <BoxCollider2D>(); // configure this collider unless this is a sprite renderer (in which case we get bounds for free) if (!isSprite) { collider.size = colliderSize; #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 collider.center = colliderCenter; #else collider.offset = colliderCenter; #endif collider.isTrigger = layout.rootColliderTrigger; } } else { // 3D collider var collider = root.AddComponent <BoxCollider>(); // configure this collider unless this is a sprite renderer (in which case we get bounds for free) if (!isSprite) { collider.size = new Vector3(colliderSize.x, colliderSize.y, 0.2f); collider.center = colliderCenter; collider.isTrigger = layout.rootColliderTrigger; } } } catch { Debug.LogWarning("Error setting the collider on Ps2D root object. Perhaps there's a conflicting component?"); } }
/// <summary> /// Create a GameObject for this sprite layer, attached to this parent. /// </summary> /// <param name="parentTransform">The parent to attach to</param> /// <param name="spriteLayer">The sprite layer.</param> public GameObject CreateGameObjectForSpriteLayer(UnitySpriteLayer spriteLayer, Transform parentTransform) { // spawn up the game object GameObject goSprite; if (layout.replicator != null) { goSprite = GameObject.Instantiate(layout.replicator, Vector3.zero, Quaternion.identity) as GameObject; } else { goSprite = new GameObject(); } goSprite.name = spriteLayer.name; // attach the appropriate sprite // do we have a sprite to set? if (spriteLayer.hasSprite) { #if PS2D_TK2D if (spriteLayer.sprite != null) { spriteLayer.AttachUnitySprite(goSprite); } else if (spriteLayer.tk2dSpriteName != null) { spriteLayer.AttachTk2dSprite(goSprite, spriteCollectionData); } #else spriteLayer.AttachUnitySprite(goSprite); #endif } // where should this sprite be? PixelBounds bounds = layout.trimToSprites ? layout.trimmedSpriteBounds : layout.document.bounds; Vector3 position = spriteLayer.GetPixelPosition(layout.coordinatesScale, bounds); float x = position.x; float y = position.y; float z = position.z; // layout the sprite based on the anchor Vector2 offset = new Vector2(bounds.width, bounds.height); switch (layout.anchor) { case TextAnchor.LowerCenter: offset.x = offset.x * 0.5f; offset.y = offset.y * 0f; break; case TextAnchor.LowerLeft: offset.x = offset.x * 0f; offset.y = offset.y * 0f; break; case TextAnchor.LowerRight: offset.x = offset.x * 1f; offset.y = offset.y * 0f; break; case TextAnchor.MiddleCenter: offset.x = offset.x * 0.5f; offset.y = offset.y * 0.5f; break; case TextAnchor.MiddleLeft: offset.x = offset.x * 0f; offset.y = offset.y * 0.5f; break; case TextAnchor.MiddleRight: offset.x = offset.x * 1f; offset.y = offset.y * 0.5f; break; case TextAnchor.UpperCenter: offset.x = offset.x * 0.5f; offset.y = offset.y * 1f; break; case TextAnchor.UpperLeft: offset.x = offset.x * 0f; offset.y = offset.y * 1f; break; case TextAnchor.UpperRight: offset.x = offset.x * 1f; offset.y = offset.y * 1f; break; default: break; } // let's move it! x -= offset.x * layout.coordinatesScale; y -= offset.y * layout.coordinatesScale; // the pixels to units ratio x *= 1f / layout.pixelsToUnits; y *= 1f / layout.pixelsToUnits; // should we create an extra parent for the sprite? if (layout.addExtraParentToSprite) { GameObject goSpriteParent = new GameObject(goSprite.name); goSpriteParent.transform.position = new Vector3(x, y, z); goSpriteParent.transform.parent = parentTransform; goSprite.transform.parent = goSpriteParent.transform; goSprite.transform.localPosition = Vector3.zero; } else { goSprite.transform.position = new Vector3(x, y, z); goSprite.transform.parent = parentTransform; } return(goSprite); }