Commit 3ec40437 by Alisa Jung

added level editor

- prefabs need to be stored in Resources/Prefabs Workflow: - Window --> XmlLevelEditor - Delete - Click "Export..." - Add all Scene objects as Childs to new Export-Object in Hierarchy (every Object needs to have name of prefab) - Click "Export..." again - new Level appears in XmlItemsToExport.xml - copy Level to Levels.xml - Load Level from DeserializedLevelsLoader
parent 8bfb72fc
fileFormatVersion: 2
guid: 2131c9cb584da1947863cc79ce473183
folderAsset: yes
timeCreated: 1433459294
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using UnityEditor;
public class XmlLevelEditor : EditorWindow {
DeserializedLevelsLoader deserializedLevelsLoader;
DeserializedLevelsSaver deserializedLevelsSaver;
DeserializedLevelsCrossChecker deserializedLevelsCrossChecker;
[MenuItem("Window/Xml Level Editor")]
public static void ShowWindow()
{
//Show existing window instance. If one doesn't exist, make one.
EditorWindow.GetWindow(typeof(XmlLevelEditor));
}
void OnGUI()
{
// create one DeserializedLevelsLoader and Saver instance
if (deserializedLevelsLoader == null) deserializedLevelsLoader = new DeserializedLevelsLoader();
if (deserializedLevelsSaver == null) deserializedLevelsSaver = new DeserializedLevelsSaver();
if (deserializedLevelsCrossChecker == null) deserializedLevelsCrossChecker = new DeserializedLevelsCrossChecker();
// Import section
GUILayout.Label ("Import", EditorStyles.boldLabel);
GUILayout.Label ("Import Levels.xml into the scene");
if (GUILayout.Button("Import Levels.xml"))
deserializedLevelsLoader.loadLevel();
// Export section
GUILayout.Label ("Export", EditorStyles.boldLabel);
GUILayout.Label ("Export children of \"" + DeserializedLevelsSaver.xmlItemsToExportGOName +"\" GameObject into " + DeserializedLevelsSaver.xmlItemsToExportGOName +".xml", EditorStyles.wordWrappedLabel);
if (GUILayout.Button("Export " + DeserializedLevelsSaver.xmlItemsToExportGOName))
deserializedLevelsSaver.saveExportItems();
// Delete section
GUILayout.Label ("Delete", EditorStyles.boldLabel);
GUILayout.Label ("Delete " + DeserializedLevelsLoader.xmlItemsGOName + " and " + DeserializedLevelsSaver.xmlItemsToExportGOName + " GameObjects from scene", EditorStyles.wordWrappedLabel);
if (GUILayout.Button("Delete"))
{
DestroyImmediate(GameObject.Find (DeserializedLevelsLoader.xmlItemsGOName));
DestroyImmediate(GameObject.Find (DeserializedLevelsSaver.xmlItemsToExportGOName));
}
// Cross check section
GUILayout.Label ("Cross Check", EditorStyles.boldLabel);
GUILayout.Label ("Cross check /Resources/Prefabs and Levels.xml if there are any item prefabs that exist only in one but not the other", EditorStyles.wordWrappedLabel);
if (GUILayout.Button("Cross Check"))
deserializedLevelsCrossChecker.crossCheck();
}
}
fileFormatVersion: 2
guid: f5f24600eb94b49d18017660a10cbcfd
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
fileFormatVersion: 2
guid: 7b4d58a633f1a024489b22acb0cc1c9e
folderAsset: yes
timeCreated: 1433459295
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="us-ascii"?>
<Levels>
<Developer StartLevel="0" />
<Level>
<Item prefab="Ground" x="3.72" y="-0.81" />
<Item prefab="Trap" x="-1.66" y="-0.57" rot="90" />
<Item prefab="Turret" x="5.11" y="4.23" rot="180" />
</Level>
<Level>
<Item prefab="PlayerStartPosition" x="5.11" y="-0.92" />
<Item prefab="PortableFire" x="6.57" y="-1.3" />
<Item prefab="PortableFire" x="6.41" y="-2.37" />
<Item prefab="PortableFire" x="4.84" y="-1.68" />
</Level>
</Levels>
\ No newline at end of file
fileFormatVersion: 2
guid: 61e3d9c06e35044b7beccd7489a32c2f
TextScriptImporter:
userData:
fileFormatVersion: 2
guid: 39552e740d8a746da8ba7e239efb1d5c
folderAsset: yes
DefaultImporter:
userData:
fileFormatVersion: 2
guid: a720d1b58e59ca74084c57781a005077
timeCreated: 1433457524
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 69decc8e4acc78a45bf93962a8beaba3
timeCreated: 1433440842
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 0f2e1a7fad18752409b6bb2b6c5f799e
timeCreated: 1433442334
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 8d9c84360d70c1b44af690dc244612a0
timeCreated: 1433461451
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 878b78d42ecc7434ca5157b454f442dd
timeCreated: 1433457388
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 6c7143f974db917419cb99f7293335f3
timeCreated: 1433449341
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 10efc7bba27351543ac5bc6c04714acb
timeCreated: 1433449355
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 120c9e6b3ed406645a6db8d9ab9665a0
timeCreated: 1433458310
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 2d46847e7efe09a40b4dd2d7dce7750a
timeCreated: 1433446182
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: e113aff6832965148a32c04b7b9c955b
timeCreated: 1433440862
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: fa4b7c73fa529e2419aa90634f7d4d84
timeCreated: 1433462176
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 3ad7c167097946b408dbef72e2814b8f
timeCreated: 1433446163
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 15c5f4fc50216c7439c59413bbe16dce
timeCreated: 1433442353
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 86acce79cdbb31f44a318df649d81c3b
timeCreated: 1433456037
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
<?xml version="1.0" encoding="Windows-1252"?>
<Levels xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Level>
<Item prefab="Ground" x="3.72" y="-0.81" />
<Item prefab="Trap" x="-1.66" y="-0.57" rot="90" />
<Item prefab="Turret" x="5.11" y="4.23" rot="180" />
</Level>
</Levels>
\ No newline at end of file
fileFormatVersion: 2
guid: 35b793df4d97b407088a52900b7b2e30
TextScriptImporter:
userData:
fileFormatVersion: 2
guid: 03a87a3caf01ee140a7d079480325123
folderAsset: yes
timeCreated: 1433459295
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
[XmlRoot("Levels")]
public class DeserializedLevels
{
[XmlElement ("Developer")]
public Developer developer;
public class Developer
{
[XmlAttribute ("StartLevel")]
public string startLevel;
}
[XmlElement ("Level")]
public Level[] levels;
public class Level
{
[XmlElement("Item")]
public Item[] items;
}
public class PlayerStartPosition
{
[XmlAttribute("x")]
public string x;
[XmlAttribute("y")]
public string y;
}
public class Item
{
[XmlAttribute ("prefab")]
public string prefab;
[XmlAttribute ("x")]
public string x;
[XmlAttribute ("y")]
public string y;
[XmlAttribute ("rot")]
public string rot;
}
}
fileFormatVersion: 2
guid: ef2ecc758c2e143019ae2dac87289034
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Linq;
public class DeserializedLevelsCrossChecker {
//Hallo Tim und Philipp. Die Datei kuckt nur ob irgendwas mit den Prefabs komisch ist.
// cross check /Resources/Prefabs and Levels.xml if there are any item prefabs that exist only in one but not the other
public void crossCheck ()
{
// create a list of /Resources/Prefabs for resources and Levels.Xml
List<string> resPrefabList = new List<string>();
List<string> xmlPrefabList = new List<string>();
// Get prefabs from Levels.xml
DeserializedLevels deserializedLevels = XmlIO.LoadXml<DeserializedLevels>("Levels");
foreach (DeserializedLevels.Level level in deserializedLevels.levels)
{
foreach (DeserializedLevels.Item item in level.items)
if (!xmlPrefabList.Contains(item.prefab))
xmlPrefabList.Add(item.prefab);
}
// Get prefabs from the /Resources/Prefabs folder
// get all child items in the /Resources/Prefabs folder
DirectoryInfo dir = new DirectoryInfo("Assets/Resources/Prefabs");
FileInfo[] fileInfos = dir.GetFiles("*.prefab");
fileInfos.Select(f => f.FullName).ToArray();
// Add each prefab's file name to prefabList and truncate the .prefab extension from the end
foreach (FileInfo fileInfo in fileInfos)
resPrefabList.Add (fileInfo.Name.Substring(0, fileInfo.Name.Length - ".prefab".Length));
// Cross checks
foreach (string prefab in xmlPrefabList.Except(resPrefabList).ToList())
Debug.LogError (prefab + " is missing in the /Resorces/Prefabs folder but used in Levels.xml");
foreach (string prefab in resPrefabList.Except(xmlPrefabList).ToList())
Debug.Log (prefab + " exists in the /Resorces/Prefabs folder but not used in Levels.xml");
Debug.Log ("Cross Check Done");
}
}
fileFormatVersion: 2
guid: f4215606b531a504d9b4e5bad6426639
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;
public class DeserializedLevelsLoader
{
// Levels deserialized
private DeserializedLevels deserializedLevels;
private int currentLevelIndex = 0;
private int currentSegmentIndex = 0;
private const string prefabsFolder = "Prefabs/";
struct ItemStruct
{
public GameObject prefab;
public float x;
public float y;
public float rot;
}
struct PlayerStartPositionStruct
{
public float x;
public float y;
}
// Cache prefabs in prefabDict
Dictionary<string,GameObject> prefabPool;
// Cache all items with locations
List<ItemStruct> sceneItemsList;
Transform parentOfXmlItems;
public const string xmlItemsGOName = "XmlItems";
public void loadLevel (int levelIndex = 0)
{
prefabPool = new Dictionary<string, GameObject>();
sceneItemsList = new List<ItemStruct>();
// if the XmlItems gameobject folder remained in the Hierarcy, then delete it
while (GameObject.Find (xmlItemsGOName) != null)
MonoBehaviour.DestroyImmediate(GameObject.Find (xmlItemsGOName));
parentOfXmlItems = new GameObject(xmlItemsGOName).transform;
deserializedLevels = XmlIO.LoadXml<DeserializedLevels>("Levels");
// if startlevel is in the XML i.e. <Developer StartLevel="3" /> then get level from there
// otherwise start with level 1
currentLevelIndex = (levelIndex > deserializedLevels.levels.Length - 1) ? 0 : levelIndex;
DeserializedLevels.Level currentLevel = deserializedLevels.levels[currentLevelIndex];
sceneItemsList.Clear();
// <Item prefab="Chair" x="1" y="10" rot="90" />
foreach (DeserializedLevels.Item deserializedItem in currentLevel.items)
{
// caching prefabString i.e. "phone"
string prefabString = deserializedItem.prefab;
// if the prefab in the item XmlNode has not been loaded then add it to the prefabsDict dictionary,
if (!prefabPool.ContainsKey(prefabString))
{
// load prefab
GameObject prefabObject = Resources.Load(prefabsFolder + prefabString, typeof(GameObject)) as GameObject;
// if unsuccesful, error message and jump to next in the foreach loop
if (prefabObject == null)
{
Debug.LogError("Prefab \"" + prefabString + "\" does not exists.");
continue;
}
// otherwise add to dictionary
prefabPool.Add(prefabString, prefabObject);
}
ItemStruct item;
item.prefab = prefabPool[prefabString];
item.x = toFloatZeroIfNull(deserializedItem.x);
item.y = toFloatZeroIfNull(deserializedItem.y);
item.rot = toFloatZeroIfNull(deserializedItem.rot);
sceneItemsList.Add(item);
}
// Finally instantiate all items
foreach (ItemStruct item in sceneItemsList)
{
// TODO load height coordinate from a directory
GameObject newGameObject = MonoBehaviour.Instantiate(item.prefab) as GameObject;
// set position
setPos2D(newGameObject, new Vector2(item.x, item.y));
// set rotation
setRot2D(newGameObject, item.rot);
// set parent
newGameObject.transform.parent = parentOfXmlItems;
}
}
// DONE, these are only helper functions below
// if no value then return zero or one, otherwise convert to float
float toFloatZeroIfNull (string value) { return value == null ? 0 : float.Parse(value); }
float toFloatOneIfNull (string value) { return value == null ? 1 : float.Parse(value); }
void setPos2D(GameObject g, Vector2 pos)
{
g.transform.position = new Vector3 (
pos.x,
pos.y,
g.transform.position.z
);
}
void setRot2D(GameObject g, float rot)
{
Debug.Log("Set rotation of " + g.name + " to " + rot);
Quaternion rotation = Quaternion.identity;
rotation.eulerAngles = new Vector3(0, 0, rot);
g.transform.localRotation = rotation;
}
}
fileFormatVersion: 2
guid: a4b2c23daf5504cc9a73df589c143887
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
using UnityEngine;
using System.Collections;
using System.Xml;
public class DeserializedLevelsSaver
{
public const string xmlItemsToExportGOName = "XmlItemsToExport";
public void saveExportItems ()
{
// Create XmlItemsToExport if does not exist yet
if (GameObject.Find (xmlItemsToExportGOName) == null)
new GameObject(xmlItemsToExportGOName);
GameObject xmlItemsToExportGO = GameObject.Find (xmlItemsToExportGOName);
var xmlItemsToExportGOchildren = xmlItemsToExportGO.GetComponentsInChildren<Transform>();
// Check if any children exist
if (xmlItemsToExportGOchildren.Length == 0)
Debug.LogError ("Add the prefabs to " + xmlItemsToExportGOName);
DeserializedLevels.Level levelXml = new DeserializedLevels.Level();
int n = 0;
// count number of children skipping sub-items
foreach (Transform item in xmlItemsToExportGOchildren)
if (item.parent == xmlItemsToExportGO.transform) n++;
// the items array should have that many elements
levelXml.items = new DeserializedLevels.Item[n];
// use i for counting items, i would be equal (one more to be precise) to n at the end of the cycle
int i = 0;
// cycle through the children again and add them to items
foreach (Transform item in xmlItemsToExportGOchildren)
{
// skip sub-items
if (item.parent != xmlItemsToExportGO.transform) continue;
levelXml.items[i] = new DeserializedLevels.Item();
levelXml.items[i].prefab = item.name;
levelXml.items[i].x = toStringNullIfZero(item.transform.position.x);
levelXml.items[i].y = toStringNullIfZero(item.transform.position.y);
levelXml.items[i].rot = toStringNullIfZero(item.localRotation.eulerAngles.z);
// increase i for the next cycle
i++;
}
// Export just one level
DeserializedLevels levelsXmlToExport = new DeserializedLevels();
levelsXmlToExport.levels = new DeserializedLevels.Level[1];
levelsXmlToExport.levels[0] = levelXml;
XmlIO.SaveXml<DeserializedLevels>(levelsXmlToExport, "./Assets/Resources/" + xmlItemsToExportGOName + ".xml");
}
string toStringNullIfZero (float num) { return num == 0 ? null : mathRound(num,2).ToString(); }
string toStringNullIfOne (float num) { return num == 1 ? null : mathRound(num,2).ToString(); }
float mathRound (float round, int decimals)
{
return Mathf.Round(round * Mathf.Pow(10,decimals)) / Mathf.Pow(10,decimals);
}
}
fileFormatVersion: 2
guid: b7816f23e21614e6684de77528fbf66f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
using UnityEngine;
using System.Collections;
public class PlayScript : MonoBehaviour {
DeserializedLevelsLoader d;
void Start ()
{
d = new DeserializedLevelsLoader();
d.loadLevel();
}
}
fileFormatVersion: 2
guid: 01cdeb3258bc3446ba8846c11515fc68
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using UnityEngine; // necessary for TextAsset
public static class XmlIO
{
public static void SaveXml<T> (this object deserializedXml, string path) where T : class
{
using(var stream = new FileStream(path, FileMode.Create))
{
var s = new XmlSerializer(typeof(T));
s.Serialize(stream, deserializedXml);
}
}
public static T LoadXml<T>(string textAssetName) where T : class
{
TextAsset xmlTextAsset = (TextAsset) Resources.Load (textAssetName, typeof(TextAsset));
using(var stream = new StringReader(xmlTextAsset.text))
{
var s = new XmlSerializer(typeof(T));
T deserializedXml = s.Deserialize(stream) as T;
return deserializedXml;
}
}
}
fileFormatVersion: 2
guid: dfdb2c835c402473bb2b1c1c22822cfb
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment