Iteration 1, added Kenney art. Also added braking.
Next iteration will be check points and lap times UI. Then need collision of some sort, and some sort of terrain effects (grass slows).
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23aa647f2fb21bf46b850587506ba4a2
|
||||
folderAsset: yes
|
||||
timeCreated: 1430572177
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,281 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class TextureAtlasSlicer : EditorWindow {
|
||||
[MenuItem("CONTEXT/TextureImporter/Slice Sprite Using XML")]
|
||||
public static void SliceUsingXML(MenuCommand command) {
|
||||
var textureImporter = command.context as TextureImporter;
|
||||
|
||||
var window = CreateInstance<TextureAtlasSlicer>();
|
||||
|
||||
window.importer = textureImporter;
|
||||
|
||||
window.ShowUtility();
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Slice Sprite Using XML")]
|
||||
public static void TextureAtlasSlicerWindow() {
|
||||
var window = CreateInstance<TextureAtlasSlicer>();
|
||||
|
||||
window.Show();
|
||||
}
|
||||
|
||||
[MenuItem("CONTEXT/TextureImporter/Slice Sprite Using XML", true)]
|
||||
public static bool ValidateSliceUsingXML(MenuCommand command) {
|
||||
var textureImporter = command.context as TextureImporter;
|
||||
|
||||
//valid only if the texture type is 'sprite' or 'advanced'.
|
||||
return textureImporter && textureImporter.textureType == TextureImporterType.Sprite ||
|
||||
textureImporter.textureType == TextureImporterType.Default;
|
||||
}
|
||||
|
||||
public TextureImporter importer;
|
||||
|
||||
public TextureAtlasSlicer() {
|
||||
titleContent = new GUIContent("XML Slicer");
|
||||
}
|
||||
|
||||
|
||||
[SerializeField]
|
||||
private TextAsset xmlAsset;
|
||||
|
||||
public SpriteAlignment spriteAlignment = SpriteAlignment.Center;
|
||||
|
||||
public Vector2 customOffset = new Vector2(0.5f, 0.5f);
|
||||
|
||||
public void OnSelectionChange() {
|
||||
UseSelectedTexture();
|
||||
}
|
||||
|
||||
private Texture2D selectedTexture;
|
||||
|
||||
private void UseSelectedTexture() {
|
||||
if (Selection.objects.Length > 1) {
|
||||
selectedTexture = null;
|
||||
} else {
|
||||
selectedTexture = Selection.activeObject as Texture2D;
|
||||
}
|
||||
|
||||
if (selectedTexture != null) {
|
||||
var assetPath = AssetDatabase.GetAssetPath(selectedTexture);
|
||||
|
||||
importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
||||
|
||||
if (importer) {
|
||||
var extension = Path.GetExtension(assetPath);
|
||||
var pathWithoutExtension = assetPath.Remove(assetPath.Length - extension.Length, extension.Length);
|
||||
|
||||
var xmlPath = pathWithoutExtension + ".xml";
|
||||
|
||||
var textAsset = AssetDatabase.LoadAssetAtPath(xmlPath, typeof (TextAsset));
|
||||
|
||||
if (textAsset != null) {
|
||||
xmlAsset = textAsset as TextAsset;
|
||||
} else {
|
||||
xmlAsset = null;
|
||||
subTextures = null;
|
||||
}
|
||||
|
||||
ParseXML();
|
||||
} else {
|
||||
xmlAsset = null;
|
||||
subTextures = null;
|
||||
}
|
||||
} else {
|
||||
importer = null;
|
||||
xmlAsset = null;
|
||||
subTextures = null;
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private SubTexture[] subTextures;
|
||||
private int wantedWidth, wantedHeight;
|
||||
|
||||
private void ParseXML() {
|
||||
try {
|
||||
var document = new XmlDocument();
|
||||
document.LoadXml(xmlAsset.text);
|
||||
|
||||
var root = document.DocumentElement;
|
||||
if (root == null || root.Name != "TextureAtlas") {
|
||||
return;
|
||||
}
|
||||
|
||||
subTextures = root.ChildNodes
|
||||
.Cast<XmlNode>()
|
||||
.Where(childNode => childNode.Name == "SubTexture")
|
||||
.Select(childNode => new SubTexture {
|
||||
width = Convert.ToInt32(childNode.Attributes["width"].Value),
|
||||
height = Convert.ToInt32(childNode.Attributes["height"].Value),
|
||||
x = Convert.ToInt32(childNode.Attributes["x"].Value),
|
||||
y = Convert.ToInt32(childNode.Attributes["y"].Value),
|
||||
name = childNode.Attributes["name"].Value
|
||||
}).ToArray();
|
||||
|
||||
wantedWidth = 0;
|
||||
wantedHeight = 0;
|
||||
|
||||
foreach (var subTexture in subTextures) {
|
||||
var right = subTexture.x + subTexture.width;
|
||||
var bottom = subTexture.y + subTexture.height;
|
||||
|
||||
wantedWidth = Mathf.Max(wantedWidth, right);
|
||||
wantedHeight = Mathf.Max(wantedHeight, bottom);
|
||||
}
|
||||
} catch (Exception) {
|
||||
subTextures = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEnable() {
|
||||
UseSelectedTexture();
|
||||
}
|
||||
|
||||
public void OnGUI() {
|
||||
if (importer == null) {
|
||||
EditorGUILayout.LabelField("Please select a texture to slice.");
|
||||
return;
|
||||
}
|
||||
EditorGUI.BeginDisabledGroup(focusedWindow != this);
|
||||
{
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.ObjectField("Texture", Selection.activeObject, typeof (Texture), false);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
if (importer.textureType != TextureImporterType.Sprite &&
|
||||
importer.textureType != TextureImporterType.Default) {
|
||||
EditorGUILayout.LabelField("The Texture Type needs to be Sprite or Advanced!");
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup((importer.textureType != TextureImporterType.Sprite &&
|
||||
importer.textureType != TextureImporterType.Default));
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
xmlAsset = EditorGUILayout.ObjectField("XML Source", xmlAsset, typeof (TextAsset), false) as TextAsset;
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
ParseXML();
|
||||
}
|
||||
|
||||
spriteAlignment = (SpriteAlignment) EditorGUILayout.EnumPopup("Pivot", spriteAlignment);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(spriteAlignment != SpriteAlignment.Custom);
|
||||
EditorGUILayout.Vector2Field("Custom Offset", customOffset);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
var needsToResizeTexture = wantedWidth > selectedTexture.width || wantedHeight > selectedTexture.height;
|
||||
|
||||
if (xmlAsset != null && needsToResizeTexture) {
|
||||
EditorGUILayout.LabelField(
|
||||
string.Format("Texture size too small."
|
||||
+ " It needs to be at least {0} by {1} pixels!",
|
||||
wantedWidth,
|
||||
wantedHeight));
|
||||
EditorGUILayout.LabelField("Try changing the Max Size property in the importer.");
|
||||
}
|
||||
|
||||
if (subTextures == null || subTextures.Length == 0) {
|
||||
EditorGUILayout.LabelField("Could not find any SubTextures in XML.");
|
||||
}
|
||||
|
||||
EditorGUI.BeginDisabledGroup(xmlAsset == null || needsToResizeTexture || subTextures == null ||
|
||||
subTextures.Length == 0);
|
||||
if (GUILayout.Button("Slice")) {
|
||||
PerformSlice();
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
private struct SubTexture {
|
||||
public int width;
|
||||
public int height;
|
||||
public int x;
|
||||
public int y;
|
||||
public string name;
|
||||
}
|
||||
|
||||
private void PerformSlice() {
|
||||
if (importer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var textureHeight = selectedTexture.height;
|
||||
|
||||
var needsUpdate = false;
|
||||
|
||||
if (importer.spriteImportMode != SpriteImportMode.Multiple) {
|
||||
needsUpdate = true;
|
||||
importer.spriteImportMode = SpriteImportMode.Multiple;
|
||||
}
|
||||
|
||||
var wantedSpriteSheet = (from subTexture in subTextures
|
||||
let actualY = textureHeight - (subTexture.y + subTexture.height)
|
||||
select new SpriteMetaData {
|
||||
alignment = (int) spriteAlignment,
|
||||
border = new Vector4(),
|
||||
name = subTexture.name,
|
||||
pivot = GetPivotValue(spriteAlignment, customOffset),
|
||||
rect = new Rect(subTexture.x, actualY, subTexture.width, subTexture.height)
|
||||
}).ToArray();
|
||||
if (!needsUpdate && !importer.spritesheet.SequenceEqual(wantedSpriteSheet)) {
|
||||
needsUpdate = true;
|
||||
importer.spritesheet = wantedSpriteSheet;
|
||||
}
|
||||
|
||||
if (needsUpdate) {
|
||||
EditorUtility.SetDirty(importer);
|
||||
|
||||
try {
|
||||
AssetDatabase.StartAssetEditing();
|
||||
AssetDatabase.ImportAsset(importer.assetPath);
|
||||
|
||||
EditorUtility.DisplayDialog("Success!", "The sprite was sliced successfully.", "OK");
|
||||
} catch (Exception exception) {
|
||||
Debug.LogException(exception);
|
||||
EditorUtility.DisplayDialog("Error", "There was an exception while trying to reimport the image." +
|
||||
"\nPlease check the console log for details.", "OK");
|
||||
} finally {
|
||||
AssetDatabase.StopAssetEditing();
|
||||
}
|
||||
} else {
|
||||
EditorUtility.DisplayDialog("Nope!", "The sprite is already sliced according to this XML file.", "OK");
|
||||
}
|
||||
}
|
||||
|
||||
//SpriteEditorUtility
|
||||
public static Vector2 GetPivotValue(SpriteAlignment alignment, Vector2 customOffset) {
|
||||
switch (alignment) {
|
||||
case SpriteAlignment.Center:
|
||||
return new Vector2(0.5f, 0.5f);
|
||||
case SpriteAlignment.TopLeft:
|
||||
return new Vector2(0.0f, 1f);
|
||||
case SpriteAlignment.TopCenter:
|
||||
return new Vector2(0.5f, 1f);
|
||||
case SpriteAlignment.TopRight:
|
||||
return new Vector2(1f, 1f);
|
||||
case SpriteAlignment.LeftCenter:
|
||||
return new Vector2(0.0f, 0.5f);
|
||||
case SpriteAlignment.RightCenter:
|
||||
return new Vector2(1f, 0.5f);
|
||||
case SpriteAlignment.BottomLeft:
|
||||
return new Vector2(0.0f, 0.0f);
|
||||
case SpriteAlignment.BottomCenter:
|
||||
return new Vector2(0.5f, 0.0f);
|
||||
case SpriteAlignment.BottomRight:
|
||||
return new Vector2(1f, 0.0f);
|
||||
case SpriteAlignment.Custom:
|
||||
return customOffset;
|
||||
default:
|
||||
return Vector2.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2067bd0762faf2c48910fee768c92901
|
||||
timeCreated: 1430572201
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
# Unity3D-TextureAtlasSlicer
|
||||
Simple and fast tool to import XML spritesheets (TextureAtlas) into Unity3D!
|
||||
|
||||

|
||||
|
||||
Works very well to import [Kenney's sprite assets](http://opengameart.org/users/kenney)!
|
||||
|
||||
## Usage
|
||||
- Copy this folder to your project's assets directory, or just use the latest .unitypackage file from the [Github project's releases](https://github.com/toxicFork/Unity3D-TextureAtlasSlicer/releases), or the [Unity3D asset store](https://www.assetstore.unity3d.com/en/#!/content/36103)!
|
||||
- You can now use the Assets/Slice Sprite Using XML button!
|
||||
- This will open a window.
|
||||
- Select any sprite asset in your Project window
|
||||
- If it has a XML file with the same name next to it, that XML file will automatically be selected
|
||||
- Otherwise, drag-drop the XML file reference onto the XML Source field in the Texture Atlas Slicer window
|
||||
- Configure the pivot settings
|
||||
- Hit Slice!
|
||||
- Enjoy! :D
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 463e84607d141d645b70834aa062a0d1
|
||||
timeCreated: 1430859603
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user