导入es3插件
This commit is contained in:
parent
14d97fc5d7
commit
eec4eb20c3
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c62843c57c147904b9ebffefca974d04
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3115cc2dd2d49d742b3cfe0b237788ce
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,98 @@
|
|||
3.3.2f5
|
||||
- Resolved issue where scripts were not overwritten by Asset Store importer, causing Easy Save to be unstable.
|
||||
|
||||
3.3.2f4
|
||||
- Resolved issue where Save action for PlayMaker could return NullReferenceException due to using the wrong ES3.Save override.
|
||||
- Worked around IL2CPP bug where reflection would not find particular ES3Types on iOS
|
||||
- Resolved issue where trying to store an empty/unassigned PlayMaker object would throw a NulReferenceException.
|
||||
- Keys of a type which no longer exists in the project are now automatically removed
|
||||
- Abstract types used in an ES3Type will now work as intended
|
||||
|
||||
3.3.2f3
|
||||
- Added GameObject variables to Auto Save
|
||||
- Resolved issue where Sprites would be loaded with the incorrect pivot.
|
||||
- Resolved issue where Stacks were loaded in reverse.
|
||||
- Added a 'quality' field to the ES3.SaveImage method to allow the quality to be specified when saving JPEGs.
|
||||
|
||||
3.3.2f2
|
||||
- Added method which allows raw bytes to be uploaded via ES3Cloud.
|
||||
- Worked around issue where File IO was called on platforms which don't support it
|
||||
- Accounted for situations where Component should evaluate to null but doesn't
|
||||
- Updated PlayMaker actions to work around issue where global variables sometimes go missing
|
||||
- Objects with the NotEditable hideFlags can now be stored by reference
|
||||
- Worked around Unity bug where it fails to deserialize data when Prefab mode is open
|
||||
- Resolved issue where global 'Save GameObject Children' settings can take precedence over Auto Save settings
|
||||
- 'Enable Easy Save for Prefab' context menu item now works when multiple objects are selected.
|
||||
|
||||
3.3.2f1
|
||||
- Resolved issue where Components on prefabs would sometimes not be added to the reference manager.
|
||||
- Resolved issue where reference ID was read unnecesserily, causing format exception.
|
||||
- Resolved issue where child prefabs would not be recognised by manager.
|
||||
|
||||
3.3.1p12
|
||||
- Resolved case where certain references would not be added to manager.
|
||||
|
||||
3.3.1f11
|
||||
- Fixed issue where using ES3.CacheFile with an encrypted file could fail.
|
||||
- Fixed issue where Directory.GetFiles cannot process a full path on certain configurations.
|
||||
- Accounted for case where HideFlags are changed during build process.
|
||||
- Added a timeout parameter to the ES3Cloud constructor.
|
||||
- ES3.Serialize and ES3.Deserialize now work with encryption and compression
|
||||
|
||||
3.3.1f10
|
||||
- Full support for projects which use multiple scenes at once.
|
||||
- Added ES3.Encrypt and ES3.Decrypt methods.
|
||||
- Supported saving the active state and FsmVariables of PlayMaker FSMs.
|
||||
- Added edge case for SkinnedMeshRenderers which use LODs to ensure that all meshes and Materials are added to the reference manager.
|
||||
- Ensured that Auto Update References setting is ackowledged when first adding manager to scene.
|
||||
- Moved menu items into Tools/Easy Save 3 menu.
|
||||
- Using LoadInto will now assign the loaded reference ID to the object you're loading into.
|
||||
|
||||
3.3.1f9
|
||||
- It's not possible to add an ES3ReferenceMgr to your scene directly, ensuring that initialisation code is performed.
|
||||
- Compressed files can now be cached.
|
||||
- Ability to only add prefabs directly referenced by your scene to the manager.
|
||||
|
||||
3.3.1f8
|
||||
- Caching is now enabled by default for Auto Save, significantly improving performance.
|
||||
- Added ES3.LoadString method so you do not need to provide all parameters to use the defaultValue overload.
|
||||
- Resolved case where SaveAll would not correctly save some types of array.
|
||||
- Resolved case where global references would not be acknowledged.
|
||||
|
||||
3.3.1f7
|
||||
- Serialization depth limit has been raised to account for projects with deep hierearchies
|
||||
- Fixed issue where Easy Save 3 Manager could not be found for scenes which had not been saved.
|
||||
- Resolved issue where Add Reference(s) to Manager would not dirty scene when Auto Update References was disabled.
|
||||
- Improved Editor performance by accounting for situations where post-processing events would be called multiple times.
|
||||
|
||||
3.3.1f6
|
||||
- Internal fields of the UnityEngine.Object class are hidden in the Types pane as they are not serialisable.
|
||||
- Accounted for edge case where unassigned script is returned by GameObject.GetComponents().
|
||||
- ES3Settings constructor now accepts any settings enum (e.g. ES3.Location).
|
||||
- No longer throws warning when multiple scenes are open.
|
||||
|
||||
3.3.1f5
|
||||
- Updated PlayMaker actions.
|
||||
- Provided workaround for issue where IL2CPP stripper removes methods which are marked to not be stripped.
|
||||
- Performance updates.
|
||||
|
||||
3.3.1f4
|
||||
- Improved performance when gathering references for reference manager.
|
||||
|
||||
3.3.1f3
|
||||
- Added Cache as a storage location, providing a much simpler way of caching data.
|
||||
- References can now be added by right-clicking the object and going to Easy Save 3 > Add Reference to Manager.
|
||||
- Floats and doubles are now stored with full precision.
|
||||
- Assorted bug fixes.
|
||||
|
||||
3.3.1f2
|
||||
- Added compression, reducing file size by 85% on average when enabled
|
||||
- JSON is now pretty printed (formatted) by default
|
||||
- Added attributes to control serialisation
|
||||
- Private fields in inherited classes are now stored
|
||||
- Added search capabilities to the Auto Save window
|
||||
- The way in which GameObjects is saved is now more flexible
|
||||
- The reference manager is now updated whenever playmode is entered
|
||||
- Null values in the global manager are now automatically removed
|
||||
- Fixed issue where default settings were not applied properly
|
||||
- Fixed issue where ES3Types would be stored in Easy Save root rather than in Assets/Easy Save 3/
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 48fdb523e0bb47f479a18f9b236df644
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 600dbc665993148f7b59ae7356fe862e
|
||||
folderAsset: yes
|
||||
timeCreated: 1474041532
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,61 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using ES3Internal;
|
||||
using System.Linq;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class AddES3Prefab : Editor
|
||||
{
|
||||
[MenuItem("GameObject/Easy Save 3/Enable Easy Save for Prefab(s)", false, 1001)]
|
||||
[MenuItem("Assets/Easy Save 3/Enable Easy Save for Prefab(s)", false, 1001)]
|
||||
public static void Enable()
|
||||
{
|
||||
if (Selection.gameObjects == null || Selection.gameObjects.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (var obj in Selection.gameObjects)
|
||||
{
|
||||
// Don't add the Component to a GameObject which already has it.
|
||||
if (obj == null || (obj.GetComponent<ES3Prefab>() != null))
|
||||
continue;
|
||||
|
||||
var go = obj;
|
||||
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
if (PrefabUtility.GetPrefabInstanceStatus(go) != PrefabInstanceStatus.NotAPrefab)
|
||||
{
|
||||
go = (GameObject)PrefabUtility.GetCorrespondingObjectFromSource(go);
|
||||
if (go == null)
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
if(PrefabUtility.GetPrefabType(go) != PrefabType.Prefab)
|
||||
{
|
||||
go = (GameObject)PrefabUtility.GetPrefabParent(go);
|
||||
if(go == null)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
var es3Prefab = Undo.AddComponent<ES3Prefab>(go);
|
||||
es3Prefab.GeneratePrefabReferences();
|
||||
|
||||
if (ES3ReferenceMgr.Current != null)
|
||||
{
|
||||
ES3ReferenceMgr.Current.AddPrefab(es3Prefab);
|
||||
EditorUtility.SetDirty(ES3ReferenceMgr.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Easy Save 3/Enable Easy Save for Prefab", true, 1001)]
|
||||
[MenuItem("Assets/Easy Save 3/Enable Easy Save for Prefab", true, 1001)]
|
||||
public static bool Validate()
|
||||
{
|
||||
return Selection.gameObjects != null && Selection.gameObjects.Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 337c3be705d1942b3bf318b5b29aa7cb
|
||||
timeCreated: 1519132282
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,308 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using ES3Internal;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
[System.Serializable]
|
||||
public class AutoSaveWindow : SubWindow
|
||||
{
|
||||
public bool showAdvancedSettings = false;
|
||||
|
||||
public ES3AutoSaveMgr mgr = null;
|
||||
|
||||
private HierarchyItem[] hierarchy = null;
|
||||
public HierarchyItem selected = null;
|
||||
|
||||
private Vector2 hierarchyScrollPosition = Vector2.zero;
|
||||
|
||||
private bool sceneOpen = true;
|
||||
|
||||
private string searchTerm = "";
|
||||
|
||||
public AutoSaveWindow(EditorWindow window) : base("Auto Save", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
Init();
|
||||
|
||||
if(mgr == null)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("Enable Auto Save for this scene"))
|
||||
mgr = ES3Postprocessor.AddManagerToScene().GetComponent<ES3AutoSaveMgr>();
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
using (var changeCheck = new EditorGUI.ChangeCheckScope())
|
||||
{
|
||||
using (var vertical = new EditorGUILayout.VerticalScope(style.areaPadded))
|
||||
{
|
||||
//GUILayout.Label("Settings for current scene", style.heading);
|
||||
mgr.saveEvent = (ES3AutoSaveMgr.SaveEvent)EditorGUILayout.EnumPopup("Save Event", mgr.saveEvent);
|
||||
mgr.loadEvent = (ES3AutoSaveMgr.LoadEvent)EditorGUILayout.EnumPopup("Load Event", mgr.loadEvent);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
showAdvancedSettings = EditorGUILayout.Foldout(showAdvancedSettings, "Show Advanced Settings");
|
||||
if (showAdvancedSettings)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
mgr.key = EditorGUILayout.TextField("Key", mgr.key);
|
||||
ES3SettingsEditor.Draw(mgr.settings);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
// Display the menu.
|
||||
using (var horizontal = new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Scene", sceneOpen ? style.menuButtonSelected : style.menuButton))
|
||||
{
|
||||
sceneOpen = true;
|
||||
OnFocus();
|
||||
}
|
||||
if (GUILayout.Button("Prefabs", sceneOpen ? style.menuButton : style.menuButtonSelected))
|
||||
{
|
||||
sceneOpen = false;
|
||||
OnFocus();
|
||||
}
|
||||
}
|
||||
|
||||
//EditorGUILayout.HelpBox("Select the Components you want to be saved.\nTo maximise performance, only select the Components with variables which need persisting.", MessageType.None, true);
|
||||
|
||||
if (hierarchy == null || hierarchy.Length == 0)
|
||||
{
|
||||
EditorGUILayout.LabelField("Right-click a prefab and select 'Easy Save 3 > Enable Easy Save for Scene' to enable Auto Save for it.\n\nYour scene will also need to reference this prefab for it to be recognised.", style.area);
|
||||
return;
|
||||
}
|
||||
|
||||
using (var scrollView = new EditorGUILayout.ScrollViewScope(hierarchyScrollPosition, style.areaPadded))
|
||||
{
|
||||
hierarchyScrollPosition = scrollView.scrollPosition;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.Width(200)))
|
||||
{
|
||||
searchTerm = GUILayout.TextField(searchTerm, GUI.skin.FindStyle("ToolbarSeachTextField"));
|
||||
if (GUILayout.Button("", GUI.skin.FindStyle("ToolbarSeachCancelButton")))
|
||||
{
|
||||
// Remove focus if cleared
|
||||
searchTerm = "";
|
||||
GUI.FocusControl(null);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
foreach (var go in hierarchy)
|
||||
if (go != null)
|
||||
go.DrawHierarchy(searchTerm.ToLowerInvariant());
|
||||
}
|
||||
if (changeCheck.changed)
|
||||
EditorUtility.SetDirty(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (mgr == null)
|
||||
{
|
||||
var mgrs = Resources.FindObjectsOfTypeAll<ES3AutoSaveMgr>();
|
||||
if (mgrs.Length > 0)
|
||||
mgr = mgrs[0];
|
||||
}
|
||||
|
||||
if (hierarchy == null)
|
||||
OnFocus();
|
||||
}
|
||||
|
||||
public override void OnFocus()
|
||||
{
|
||||
|
||||
GameObject[] parentObjects;
|
||||
if (sceneOpen)
|
||||
parentObjects = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects();
|
||||
else // Prefabs
|
||||
{
|
||||
var prefabs = ES3ReferenceMgr.Current.prefabs;
|
||||
parentObjects = new GameObject[prefabs.Count];
|
||||
for (int i = 0; i < prefabs.Count; i++)
|
||||
if(prefabs[i] != null)
|
||||
parentObjects[i] = prefabs[i].gameObject;
|
||||
}
|
||||
hierarchy = new HierarchyItem[parentObjects.Length];
|
||||
for (int i = 0; i < parentObjects.Length; i++)
|
||||
if(parentObjects[i] != null)
|
||||
hierarchy[i] = new HierarchyItem(parentObjects[i].transform, null, this);
|
||||
}
|
||||
|
||||
public class HierarchyItem
|
||||
{
|
||||
private ES3AutoSave autoSave;
|
||||
private Transform t;
|
||||
private Component[] components = null;
|
||||
// Immediate children of this GameObject
|
||||
private HierarchyItem[] children = new HierarchyItem[0];
|
||||
private bool showComponents = false;
|
||||
//private AutoSaveWindow window;
|
||||
|
||||
public HierarchyItem(Transform t, HierarchyItem parent, AutoSaveWindow window)
|
||||
{
|
||||
this.autoSave = t.GetComponent<ES3AutoSave>();
|
||||
this.t = t;
|
||||
this.components = t.GetComponents<Component>();
|
||||
|
||||
children = new HierarchyItem[t.childCount];
|
||||
for (int i = 0; i < t.childCount; i++)
|
||||
children[i] = new HierarchyItem(t.GetChild(i), this, window);
|
||||
|
||||
//this.window = window;
|
||||
}
|
||||
|
||||
public void MergeDown(ES3AutoSave autoSave)
|
||||
{
|
||||
if (this.autoSave != autoSave)
|
||||
{
|
||||
if (this.autoSave != null)
|
||||
{
|
||||
autoSave.componentsToSave.AddRange(autoSave.componentsToSave);
|
||||
Object.DestroyImmediate(this.autoSave);
|
||||
}
|
||||
this.autoSave = autoSave;
|
||||
}
|
||||
|
||||
foreach (var child in children)
|
||||
MergeDown(autoSave);
|
||||
}
|
||||
|
||||
public void DrawHierarchy(string searchTerm)
|
||||
{
|
||||
bool containsSearchTerm = false;
|
||||
if (t != null)
|
||||
{
|
||||
if (containsSearchTerm = t.name.ToLowerInvariant().Contains(searchTerm))
|
||||
{
|
||||
GUIContent saveIcon;
|
||||
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
|
||||
if (HasSelectedComponents())
|
||||
saveIcon = new GUIContent(t.name, EditorStyle.Get.saveIconSelected, "There are Components on this GameObject which will be saved.");
|
||||
else
|
||||
saveIcon = new GUIContent(t.name, EditorStyle.Get.saveIconUnselected, "No Components on this GameObject will be saved");
|
||||
|
||||
GUIStyle style = GUI.skin.GetStyle("Foldout");
|
||||
if (Selection.activeTransform == t)
|
||||
{
|
||||
style = new GUIStyle(style);
|
||||
style.fontStyle = FontStyle.Bold;
|
||||
}
|
||||
|
||||
var open = EditorGUILayout.Foldout(showComponents, saveIcon, style);
|
||||
if (open)
|
||||
{
|
||||
// Ping the GameObject if this was previously closed
|
||||
if (showComponents != open)
|
||||
EditorGUIUtility.PingObject(t.gameObject);
|
||||
DrawComponents();
|
||||
}
|
||||
showComponents = open;
|
||||
|
||||
EditorGUI.indentLevel += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw children
|
||||
if(children != null)
|
||||
foreach (var child in children)
|
||||
if(child != null)
|
||||
child.DrawHierarchy(searchTerm);
|
||||
|
||||
if(containsSearchTerm)
|
||||
EditorGUI.indentLevel-=1;
|
||||
}
|
||||
|
||||
public void DrawComponents()
|
||||
{
|
||||
EditorGUI.indentLevel+=3;
|
||||
using (var scope = new EditorGUILayout.VerticalScope())
|
||||
{
|
||||
bool toggle;
|
||||
toggle = EditorGUILayout.ToggleLeft("active", autoSave != null ? autoSave.saveActive : false);
|
||||
if((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent<ES3AutoSave>() : autoSave) != null)
|
||||
autoSave.saveActive = toggle;
|
||||
|
||||
toggle = EditorGUILayout.ToggleLeft("hideFlags", autoSave != null ? autoSave.saveHideFlags : false);
|
||||
if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent<ES3AutoSave>() : autoSave) != null)
|
||||
autoSave.saveHideFlags = toggle;
|
||||
|
||||
toggle = EditorGUILayout.ToggleLeft("layer", autoSave != null ? autoSave.saveLayer : false);
|
||||
if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent<ES3AutoSave>() : autoSave) != null)
|
||||
autoSave.saveLayer = toggle;
|
||||
|
||||
toggle = EditorGUILayout.ToggleLeft("name", autoSave != null ? autoSave.saveName : false);
|
||||
if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent<ES3AutoSave>() : autoSave) != null)
|
||||
autoSave.saveName = toggle;
|
||||
|
||||
toggle = EditorGUILayout.ToggleLeft("tag", autoSave != null ? autoSave.saveTag : false);
|
||||
if ((autoSave = (toggle && autoSave == null) ? t.gameObject.AddComponent<ES3AutoSave>() : autoSave) != null)
|
||||
autoSave.saveTag = toggle;
|
||||
|
||||
foreach (var component in components)
|
||||
{
|
||||
if (component == null)
|
||||
continue;
|
||||
|
||||
using (var horizontalScope = new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
bool saveComponent = false;
|
||||
if (autoSave != null)
|
||||
saveComponent = autoSave.componentsToSave.Contains(component);
|
||||
|
||||
var newValue = EditorGUILayout.ToggleLeft(EditorGUIUtility.ObjectContent(component, component.GetType()), saveComponent);
|
||||
// If the checkbox has changed, we want to save or not save a Component
|
||||
if (newValue != saveComponent)
|
||||
{
|
||||
if (autoSave == null)
|
||||
{
|
||||
autoSave = t.gameObject.AddComponent<ES3AutoSave>();
|
||||
autoSave.saveChildren = false;
|
||||
}
|
||||
// If we've unchecked the box, remove the Component from the array.
|
||||
if (newValue == false)
|
||||
autoSave.componentsToSave.Remove(component);
|
||||
// Else, add it to the array.
|
||||
else
|
||||
autoSave.componentsToSave.Add(component);
|
||||
}
|
||||
if(GUILayout.Button(EditorGUIUtility.IconContent("_Popup"), new GUIStyle("Label")))
|
||||
ES3Window.InitAndShowTypes(component.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(autoSave != null && (autoSave.componentsToSave == null || autoSave.componentsToSave.Count == 0) && !autoSave.saveActive && !autoSave.saveChildren && !autoSave.saveHideFlags && !autoSave.saveLayer && !autoSave.saveName && !autoSave.saveTag)
|
||||
{
|
||||
Undo.DestroyObjectImmediate(autoSave);
|
||||
autoSave = null;
|
||||
}
|
||||
EditorGUI.indentLevel-=3;
|
||||
}
|
||||
|
||||
public bool HasSelectedComponents()
|
||||
{
|
||||
if (autoSave != null)
|
||||
foreach (var component in components)
|
||||
if (component != null && autoSave.componentsToSave.Contains(component))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6065cc5492e9f49728674de9a0c1fe84
|
||||
timeCreated: 1519132286
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
[CustomEditor(typeof(ES3AutoSave))]
|
||||
public class ES3AutoSaveEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
DrawDefaultInspector();
|
||||
|
||||
if (GUILayout.Button("Manage Auto Save Settings"))
|
||||
ES3Editor.ES3Window.InitAndShowAutoSave();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 54ded3aeb20a94008a877da330bfc45f
|
||||
timeCreated: 1519132285
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
[CustomEditor(typeof(ES3AutoSaveMgr))]
|
||||
public class ES3AutoSaveMgrEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox("This manages the saving and loading of GameObjects which have the Auto Save component attached to them.\n\nIf there are no Auto Save components in your scene, this component will do nothing.", MessageType.Info);
|
||||
if(GUILayout.Button("Settings..."))
|
||||
ES3Editor.ES3Window.InitAndShowAutoSave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f440317f3fd444daf83c27a3381af17c
|
||||
timeCreated: 1519132300
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
[ES3PropertiesAttribute([propertyNames])]
|
||||
public class ES3UserType_[es3TypeSuffix] : ES3ObjectType
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]() : base(typeof([fullType])){ Instance = this; priority = 1; }
|
||||
|
||||
|
||||
protected override void WriteObject(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
[writes]
|
||||
}
|
||||
|
||||
protected override void ReadObject<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
foreach(string propertyName in reader.Properties)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override object ReadObject<T>(ES3Reader reader)
|
||||
{
|
||||
var instance = new [fullType]();
|
||||
ReadObject<T>(reader, instance);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ES3UserType_[es3TypeSuffix]Array : ES3ArrayType
|
||||
{
|
||||
public static ES3Type Instance;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]Array() : base(typeof([fullType][]), ES3UserType_[es3TypeSuffix].Instance)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cc3cada215f0d417a8fa879651f22f84
|
||||
timeCreated: 1483698819
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
[ES3PropertiesAttribute([propertyNames])]
|
||||
public class ES3UserType_[es3TypeSuffix] : ES3ComponentType
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]() : base(typeof([fullType])){ Instance = this; priority = 1;}
|
||||
|
||||
|
||||
protected override void WriteComponent(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
[writes]
|
||||
}
|
||||
|
||||
protected override void ReadComponent<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
foreach(string propertyName in reader.Properties)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ES3UserType_[es3TypeSuffix]Array : ES3ArrayType
|
||||
{
|
||||
public static ES3Type Instance;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]Array() : base(typeof([fullType][]), ES3UserType_[es3TypeSuffix].Instance)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b74f7ff5e731846249f9e22ab7afedfb
|
||||
timeCreated: 1483698819
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,84 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class EditorStyle
|
||||
{
|
||||
private static EditorStyle style = null;
|
||||
|
||||
public GUIStyle area;
|
||||
public GUIStyle areaPadded;
|
||||
|
||||
public GUIStyle menuButton;
|
||||
public GUIStyle menuButtonSelected;
|
||||
public GUIStyle smallSquareButton;
|
||||
|
||||
public GUIStyle heading;
|
||||
public GUIStyle subheading;
|
||||
public GUIStyle subheading2;
|
||||
|
||||
public GUIStyle boldLabelNoStretch;
|
||||
|
||||
public GUIStyle link;
|
||||
|
||||
public GUIStyle toggle;
|
||||
|
||||
public Texture2D saveIconSelected;
|
||||
public Texture2D saveIconUnselected;
|
||||
|
||||
public static EditorStyle Get { get{ if(style == null) style = new EditorStyle(); return style; } }
|
||||
|
||||
public EditorStyle()
|
||||
{
|
||||
// An area with padding.
|
||||
area = new GUIStyle();
|
||||
area.padding = new RectOffset(10, 10, 10, 10);
|
||||
area.wordWrap = true;
|
||||
|
||||
// An area with more padding.
|
||||
areaPadded = new GUIStyle();
|
||||
areaPadded.padding = new RectOffset(20, 20, 20, 20);
|
||||
areaPadded.wordWrap = true;
|
||||
|
||||
// Unselected menu button.
|
||||
menuButton = new GUIStyle(EditorStyles.toolbarButton);
|
||||
menuButton.fontStyle = FontStyle.Normal;
|
||||
menuButton.fontSize = 14;
|
||||
menuButton.fixedHeight = 24;
|
||||
|
||||
// Selected menu button.
|
||||
menuButtonSelected = new GUIStyle(menuButton);
|
||||
menuButtonSelected.fontStyle = FontStyle.Bold;
|
||||
|
||||
// Main Headings
|
||||
heading = new GUIStyle(EditorStyles.label);
|
||||
heading.fontStyle = FontStyle.Bold;
|
||||
heading.fontSize = 24;
|
||||
|
||||
subheading = new GUIStyle(heading);
|
||||
subheading.fontSize = 18;
|
||||
|
||||
subheading2 = new GUIStyle(heading);
|
||||
subheading2.fontSize = 14;
|
||||
|
||||
boldLabelNoStretch = new GUIStyle(EditorStyles.label);
|
||||
boldLabelNoStretch.stretchWidth = false;
|
||||
boldLabelNoStretch.fontStyle = FontStyle.Bold;
|
||||
|
||||
link = new GUIStyle();
|
||||
link.fontSize = 16;
|
||||
if(EditorGUIUtility.isProSkin)
|
||||
link.normal.textColor = new Color (0.262f, 0.670f, 0.788f);
|
||||
else
|
||||
link.normal.textColor = new Color (0.129f, 0.129f, 0.8f);
|
||||
|
||||
toggle = new GUIStyle(EditorStyles.toggle);
|
||||
toggle.stretchWidth = false;
|
||||
|
||||
saveIconSelected = AssetDatabase.LoadAssetAtPath<Texture2D>(ES3Settings.PathToEasySaveFolder() + "Editor/es3Logo16x16.png");
|
||||
saveIconUnselected = AssetDatabase.LoadAssetAtPath<Texture2D>(ES3Settings.PathToEasySaveFolder() + "Editor/es3Logo16x16-bw.png");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f556addc6753344019137cbc45d2c4ff
|
||||
timeCreated: 1519132301
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,60 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ES3Internal;
|
||||
|
||||
public class ES3EditorUtility : Editor
|
||||
{
|
||||
public static void DisplayLink(string label, string url)
|
||||
{
|
||||
var style = ES3Editor.EditorStyle.Get;
|
||||
if(GUILayout.Button(label, style.link))
|
||||
Application.OpenURL(url);
|
||||
|
||||
var buttonRect = GUILayoutUtility.GetLastRect();
|
||||
buttonRect.width = style.link.CalcSize(new GUIContent(label)).x;
|
||||
|
||||
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
|
||||
}
|
||||
|
||||
public static bool IsPrefabInAssets(UnityEngine.Object obj)
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
return PrefabUtility.IsPartOfPrefabAsset(obj);
|
||||
#else
|
||||
return (PrefabUtility.GetPrefabType(obj) == PrefabType.Prefab);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets all children and components from a GameObject or GameObjects.
|
||||
* We create our own method for this because EditorUtility.CollectDeepHierarchy isn't thread safe in the Editor.
|
||||
*/
|
||||
public static IEnumerable<UnityEngine.Object> CollectDeepHierarchy(IEnumerable<GameObject> gos)
|
||||
{
|
||||
var deepHierarchy = new HashSet<UnityEngine.Object>();
|
||||
foreach (var go in gos)
|
||||
{
|
||||
deepHierarchy.Add(go);
|
||||
deepHierarchy.UnionWith(go.GetComponents<Component>());
|
||||
foreach (Transform t in go.transform)
|
||||
deepHierarchy.UnionWith( CollectDeepHierarchy( new GameObject[] { t.gameObject } ) );
|
||||
}
|
||||
return deepHierarchy;
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Getting Started...", false, 0)]
|
||||
public static void DisplayGettingStarted()
|
||||
{
|
||||
Application.OpenURL("https://docs.moodkie.com/easy-save-3/getting-started/");
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Manual...", false, 0)]
|
||||
public static void DisplayManual()
|
||||
{
|
||||
Application.OpenURL("https://docs.moodkie.com/product/easy-save-3/");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 501719249e8124990973182985feaeb8
|
||||
timeCreated: 1519132285
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,91 @@
|
|||
#if !ES3GLOBAL_DISABLED
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
[CustomEditor(typeof(ES3Internal.ES3GlobalReferences))]
|
||||
[System.Serializable]
|
||||
public class ES3GlobalReferencesEditor : Editor
|
||||
{
|
||||
private bool isDraggingOver = false;
|
||||
private bool openReferences = false;
|
||||
|
||||
private ES3Internal.ES3GlobalReferences _globalRefs = null;
|
||||
private ES3Internal.ES3GlobalReferences globalRefs
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_globalRefs == null)
|
||||
_globalRefs = (ES3Internal.ES3GlobalReferences)serializedObject.targetObject;
|
||||
return _globalRefs;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox("This stores references to objects in Assets, allowing them to be referenced with the same ID between scenes.", MessageType.Info);
|
||||
|
||||
if (EditorGUILayout.Foldout(openReferences, "References") != openReferences)
|
||||
{
|
||||
openReferences = !openReferences;
|
||||
if (openReferences == true)
|
||||
openReferences = EditorUtility.DisplayDialog("Are you sure?", "Opening this list will display every reference in the manager, which for larger projects can cause the Editor to freeze\n\nIt is strongly recommended that you save your project before continuing.", "Open References", "Cancel");
|
||||
}
|
||||
|
||||
// Make foldout drag-and-drop enabled for objects.
|
||||
if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
|
||||
{
|
||||
Event evt = Event.current;
|
||||
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
isDraggingOver = true;
|
||||
break;
|
||||
case EventType.DragExited:
|
||||
isDraggingOver = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isDraggingOver)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
|
||||
if (evt.type == EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
Undo.RecordObject(globalRefs, "Add References to Easy Save 3 Reference List");
|
||||
foreach (UnityEngine.Object obj in DragAndDrop.objectReferences)
|
||||
globalRefs.GetOrAdd(obj);
|
||||
// Return now because otherwise we'll change the GUI during an event which doesn't allow it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openReferences)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
foreach (var kvp in globalRefs.refId)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUILayout.ObjectField(kvp.Key, typeof(UnityEngine.Object), true);
|
||||
EditorGUILayout.LongField(kvp.Value);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 286fb0c3863779e4d96bc682edb324ce
|
||||
timeCreated: 1519132283
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
[CustomEditor(typeof(ES3InspectorInfo))]
|
||||
public class ES3InspectorInfoEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox(((ES3InspectorInfo)target).message, MessageType.Info);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b344d685b614044aebf5285c5f59f52d
|
||||
timeCreated: 1519132294
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,781 @@
|
|||
#if PLAYMAKER_1_8_OR_NEWER
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using HutongGames.PlayMaker;
|
||||
using HutongGames.PlayMaker.Actions;
|
||||
using HutongGames.PlayMakerEditor;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ES3PlayMaker
|
||||
{
|
||||
#region Base Actions
|
||||
|
||||
public abstract class BaseEditor : CustomActionEditor
|
||||
{
|
||||
bool showErrorHandling = false;
|
||||
|
||||
public abstract void DrawGUI();
|
||||
|
||||
public override bool OnGUI()
|
||||
{
|
||||
DrawGUI();
|
||||
|
||||
EditorGUILayout.Separator();
|
||||
|
||||
showErrorHandling = EditorGUILayout.Foldout(showErrorHandling, "Error Handling");
|
||||
if (showErrorHandling)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditField("errorEvent");
|
||||
EditField("errorMessage");
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
return GUI.changed;
|
||||
}
|
||||
|
||||
// Displays the FsmVar field without the unnecessary Type field.
|
||||
protected void FsmVarField(string fieldName)
|
||||
{
|
||||
if (target == null || target.State == null)
|
||||
return;
|
||||
|
||||
var fsmVar = (FsmVar)ES3Internal.ES3Reflection.GetField(target.GetType(), fieldName).GetValue(target);
|
||||
|
||||
if (fsmVar == null)
|
||||
{
|
||||
fsmVar = new FsmVar();
|
||||
ES3Internal.ES3Reflection.GetField(target.GetType(), fieldName).SetValue(target, fsmVar);
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
var label = Regex.Replace(fieldName, @"\p{Lu}", m => " " + m.Value.ToLowerInvariant());
|
||||
EditorGUILayout.PrefixLabel(char.ToUpperInvariant(label[0]) + label.Substring(1));
|
||||
|
||||
var localVariables = target.Fsm.Variables.GetAllNamedVariablesSorted();
|
||||
var globalVariables = FsmVariables.GlobalVariables.GetAllNamedVariablesSorted();
|
||||
|
||||
var variableNames = new string[localVariables.Length + globalVariables.Length];
|
||||
int selected = -1;
|
||||
|
||||
for(int i=0; i<variableNames.Length; i++)
|
||||
{
|
||||
var variable = i >= localVariables.Length ? globalVariables[i - localVariables.Length] : localVariables[i];
|
||||
variableNames[i] = i >= localVariables.Length ? "Globals/"+variable.Name : variable.Name;
|
||||
if (fsmVar.NamedVar == variable)
|
||||
selected = i;
|
||||
}
|
||||
|
||||
var newSelected = EditorGUILayout.Popup(selected, variableNames);
|
||||
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (newSelected == -1)
|
||||
return;
|
||||
|
||||
if (selected != newSelected)
|
||||
{
|
||||
if (newSelected >= localVariables.Length)
|
||||
fsmVar.NamedVar = globalVariables[newSelected - localVariables.Length];
|
||||
else
|
||||
fsmVar.NamedVar = localVariables[newSelected];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SettingsEditor : BaseEditor
|
||||
{
|
||||
public override bool OnGUI()
|
||||
{
|
||||
base.OnGUI();
|
||||
|
||||
var action = target as ES3PlayMaker.SettingsAction;
|
||||
if(action == null)
|
||||
return false;
|
||||
action.overrideDefaultSettings.Value = EditorGUILayout.ToggleLeft("Override Default Settings", action.overrideDefaultSettings.Value);
|
||||
|
||||
if(action.overrideDefaultSettings.Value)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditField("path");
|
||||
EditField("location");
|
||||
EditField("encryptionType");
|
||||
EditField("encryptionPassword");
|
||||
EditField("compressionType");
|
||||
EditField("directory");
|
||||
EditField("format");
|
||||
EditField("bufferSize");
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
return GUI.changed;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class KeyValueSettingsEditor : SettingsEditor
|
||||
{
|
||||
public override bool OnGUI()
|
||||
{
|
||||
EditField("key");
|
||||
EditField("value");
|
||||
|
||||
base.OnGUI();
|
||||
|
||||
return GUI.changed;
|
||||
}
|
||||
|
||||
public override void DrawGUI(){}
|
||||
}
|
||||
|
||||
public abstract class ES3FileActionEditor : BaseEditor
|
||||
{
|
||||
public override bool OnGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
|
||||
base.OnGUI();
|
||||
|
||||
var action = target as ES3PlayMaker.ES3FileAction;
|
||||
if (action == null)
|
||||
return false;
|
||||
|
||||
return GUI.changed;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.Save))]
|
||||
public class SaveEditor : KeyValueSettingsEditor{}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.SaveAll))]
|
||||
public class SaveAllEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("key");
|
||||
EditField("saveFsmVariables");
|
||||
EditField("saveGlobalVariables");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.SaveRaw))]
|
||||
public class SaveRawEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("str");
|
||||
EditField("useBase64Encoding");
|
||||
EditField("appendNewline");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.AppendRaw))]
|
||||
public class AppendRawEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("str");
|
||||
EditField("useBase64Encoding");
|
||||
EditField("appendNewline");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.SaveImage))]
|
||||
public class SaveImageEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("imagePath");
|
||||
EditField("texture2D");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.Load))]
|
||||
public class LoadEditor : KeyValueSettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditField("defaultValue");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.LoadInto))]
|
||||
public class LoadIntoEditor : KeyValueSettingsEditor{}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.LoadAll))]
|
||||
public class LoadAllEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("key");
|
||||
EditField("loadFsmVariables");
|
||||
EditField("loadGlobalVariables");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.LoadAudio))]
|
||||
public class LoadAudioEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("audioFilePath");
|
||||
EditField("audioClip");
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
EditField("audioType");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.LoadImage))]
|
||||
public class LoadImageEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("imagePath");
|
||||
EditField("texture2D");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.LoadRawString))]
|
||||
public class LoadRawStringEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("str");
|
||||
EditField("useBase64Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exists Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.KeyExists))]
|
||||
public class KeyExistsEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("key");
|
||||
EditField("exists");
|
||||
EditorGUILayout.Separator();
|
||||
EditField("existsEvent");
|
||||
EditField("doesNotExistEvent");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.FileExists))]
|
||||
public class FileExistsEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
EditField("exists");
|
||||
EditorGUILayout.Separator();
|
||||
EditField("existsEvent");
|
||||
EditField("doesNotExistEvent");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.DirectoryExists))]
|
||||
public class DirectoryExistsEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("directoryPath");
|
||||
EditField("exists");
|
||||
EditorGUILayout.Separator();
|
||||
EditField("existsEvent");
|
||||
EditField("doesNotExistEvent");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.DeleteKey))]
|
||||
public class DeleteKeyEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("key");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.DeleteFile))]
|
||||
public class DeleteFileEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.DeleteDirectory))]
|
||||
public class DeleteDirectoryEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("directoryPath");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Backup Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.CreateBackup))]
|
||||
public class CreateBackupEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.RestoreBackup))]
|
||||
public class RestoreBackupEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
EditField("backupWasRestored");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Key, File and Directory methods
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.RenameFile))]
|
||||
public class RenameFileEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("oldFilePath");
|
||||
EditField("newFilePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.CopyFile))]
|
||||
public class CopyFileEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("oldFilePath");
|
||||
EditField("newFilePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.CopyDirectory))]
|
||||
public class CopyDirectoryEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("oldDirectoryPath");
|
||||
EditField("newDirectoryPath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.GetKeys))]
|
||||
public class GetKeysEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
EditField("keys");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.GetKeyCount))]
|
||||
public class GetKeyCountEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
EditField("keyCount");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.GetFiles))]
|
||||
public class GetFilesEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("directoryPath");
|
||||
EditField("files");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.GetDirectories))]
|
||||
public class GetDirectoriesEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("directoryPath");
|
||||
EditField("directories");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ES3File Actions
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileCreate))]
|
||||
public class ES3FileCreateEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
EditField("filePath");
|
||||
EditField("syncWithFile");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileSync))]
|
||||
public class ES3FileSyncEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileSave))]
|
||||
public class ES3FileSaveEditor : SaveEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
base.DrawGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileLoad))]
|
||||
public class ES3FileLoadEditor : LoadEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
base.DrawGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileLoadInto))]
|
||||
public class ES3FileLoadIntoEditor : LoadIntoEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
base.DrawGUI();
|
||||
EditField("fsmES3File");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileDeleteKey))]
|
||||
public class ES3FileDeleteKeyEditor : DeleteKeyEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
base.DrawGUI();
|
||||
EditField("fsmES3File");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileKeyExists))]
|
||||
public class ES3FileKeyExistsEditor : KeyExistsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
base.DrawGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileGetKeys))]
|
||||
public class ES3FileGetKeysEditor : ES3FileActionEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("keys");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileClear))]
|
||||
public class ES3FileClearEditor : BaseEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3FileSize))]
|
||||
public class ES3FileSizeEditor : BaseEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("size");
|
||||
EditField("fsmES3File");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ES3Cloud Actions
|
||||
#if !DISABLE_WEB
|
||||
|
||||
public abstract class ES3CloudEditor : SettingsEditor
|
||||
{
|
||||
protected abstract void DrawChildGUI();
|
||||
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("url");
|
||||
EditField("apiKey");
|
||||
EditorGUILayout.Space();
|
||||
DrawChildGUI();
|
||||
EditorGUILayout.Space();
|
||||
EditField("errorCode");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ES3CloudUserEditor : ES3CloudEditor
|
||||
{
|
||||
public bool showUser = false;
|
||||
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
if((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditField("user");
|
||||
EditField("password");
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudSync))]
|
||||
public class ES3CloudSyncEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("path");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadFile))]
|
||||
public class ES3CloudDownloadFileEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("path");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadES3File))]
|
||||
public class ES3CloudDownloadES3FileEditor : BaseEditor
|
||||
{
|
||||
public bool showUser = false;
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
EditField("url");
|
||||
EditField("apiKey");
|
||||
EditField("errorCode");
|
||||
if ((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditField("user");
|
||||
EditField("password");
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudUploadFile))]
|
||||
public class ES3CloudUploadFileEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("path");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudUploadES3File))]
|
||||
public class ES3CloudUploadES3FileEditor : BaseEditor
|
||||
{
|
||||
public bool showUser = false;
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3File");
|
||||
EditField("url");
|
||||
EditField("apiKey");
|
||||
EditField("errorCode");
|
||||
if((showUser = EditorGUILayout.Foldout(showUser, "User (optional)")))
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditField("user");
|
||||
EditField("password");
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDeleteFile))]
|
||||
public class ES3CloudDeleteFileEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("path");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudRenameFile))]
|
||||
public class ES3CloudRenameFileEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("path");
|
||||
EditField("newFilename");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadFilenames))]
|
||||
public class ES3CloudDownloadFilenamesEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("filenames");
|
||||
EditField("searchPattern");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudSearchFilenames))]
|
||||
public class ES3CloudSearchFilenamesEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("filenames");
|
||||
EditField("searchPattern");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3CloudDownloadTimestamp))]
|
||||
public class ES3CloudDownloadTimestampEditor : ES3CloudUserEditor
|
||||
{
|
||||
protected override void DrawChildGUI()
|
||||
{
|
||||
EditField("timestamp");
|
||||
base.DrawChildGUI();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#region ES3SpreadsheetActions
|
||||
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetCreate))]
|
||||
public class ES3SpreadsheetCreateEditor : BaseEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3Spreadsheet");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetSetCell))]
|
||||
public class ES3SpreadsheetSetCellEditor : BaseEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3Spreadsheet");
|
||||
EditField("col");
|
||||
EditField("row");
|
||||
EditField("value");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetGetCell))]
|
||||
public class ES3SpreadsheetGetCellEditor : BaseEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3Spreadsheet");
|
||||
EditField("col");
|
||||
EditField("row");
|
||||
EditField("value");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetLoad))]
|
||||
public class ES3SpreadsheetLoadEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3Spreadsheet");
|
||||
EditField("filePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.ES3SpreadsheetSave))]
|
||||
public class ES3SpreadsheetSaveEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("fsmES3Spreadsheet");
|
||||
EditField("filePath");
|
||||
EditField("append");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Caching
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.CacheFile))]
|
||||
public class CacheFileEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
}
|
||||
}
|
||||
|
||||
[CustomActionEditor(typeof(ES3PlayMaker.StoreCachedFile))]
|
||||
public class StoreCachedFileEditor : SettingsEditor
|
||||
{
|
||||
public override void DrawGUI()
|
||||
{
|
||||
EditField("filePath");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 61838eb75b8164d699b0f54416e0f0bc
|
||||
timeCreated: 1497347459
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,149 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using ES3Internal;
|
||||
|
||||
|
||||
/*
|
||||
* ---- How Postprocessing works for the reference manager ----
|
||||
* - When the manager is first added to the scene, all top-level dependencies are added to the manager (AddManagerToScene).
|
||||
* - When the manager is first added to the scene, all prefabs with ES3Prefab components are added to the manager (AddManagerToScene).
|
||||
* - All GameObjects and Components in the scene are added to the reference manager when we enter Playmode or the scene is saved (PlayModeStateChanged, OnWillSaveAssets -> AddGameObjectsAndComponentstoManager).
|
||||
* - When a UnityEngine.Object field of a Component is modified, the new UnityEngine.Object reference is added to the reference manager (PostProcessModifications)
|
||||
* - All prefabs with ES3Prefab Components are added to the reference manager when we enter Playmode or the scene is saved (PlayModeStateChanged, OnWillSaveAssets -> AddGameObjectsAndComponentstoManager).
|
||||
* - Local references for prefabs are processed whenever a prefab with an ES3Prefab Component is deselected (SelectionChanged -> ProcessGameObject)
|
||||
*/
|
||||
[InitializeOnLoad]
|
||||
public class ES3Postprocessor : UnityEditor.AssetModificationProcessor
|
||||
{
|
||||
private static bool refreshed = false;
|
||||
|
||||
public static ES3ReferenceMgr RefMgr
|
||||
{
|
||||
get { return (ES3ReferenceMgr)ES3ReferenceMgr.Current; }
|
||||
}
|
||||
|
||||
public static GameObject lastSelected = null;
|
||||
|
||||
|
||||
// This constructor is also called once when playmode is activated and whenever recompilation happens
|
||||
// because we have the [InitializeOnLoad] attribute assigned to the class.
|
||||
static ES3Postprocessor()
|
||||
{
|
||||
// Open the Easy Save 3 window the first time ES3 is installed.
|
||||
//ES3Editor.ES3Window.OpenEditorWindowOnStart();
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
EditorApplication.playModeStateChanged += PlayModeStateChanged;
|
||||
#else
|
||||
EditorApplication.playmodeStateChanged += PlaymodeStateChanged;
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Reference Updating
|
||||
|
||||
private static void RefreshReferences(bool isEnteringPlayMode = false)
|
||||
{
|
||||
if (refreshed) // If we've already refreshed, do nothing.
|
||||
return;
|
||||
|
||||
if (RefMgr != null && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
|
||||
{
|
||||
RefMgr.RefreshDependencies(isEnteringPlayMode);
|
||||
}
|
||||
UpdateAssembliesContainingES3Types();
|
||||
refreshed = true;
|
||||
}
|
||||
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
public static void PlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
// Add all GameObjects and Components to the reference manager before we enter play mode.
|
||||
if (state == PlayModeStateChange.ExitingEditMode && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
|
||||
RefreshReferences(true);
|
||||
}
|
||||
#else
|
||||
public static void PlaymodeStateChanged()
|
||||
{
|
||||
// Add all GameObjects and Components to the reference manager before we enter play mode.
|
||||
if (!EditorApplication.isPlaying && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
|
||||
RefreshReferences(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public static string[] OnWillSaveAssets(string[] paths)
|
||||
{
|
||||
// Don't refresh references when the application is playing.
|
||||
if (!EditorApplication.isUpdating && !Application.isPlaying && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
|
||||
RefreshReferences();
|
||||
return paths;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private static void UpdateAssembliesContainingES3Types()
|
||||
{
|
||||
#if UNITY_2017_3_OR_NEWER
|
||||
|
||||
var assemblies = UnityEditor.Compilation.CompilationPipeline.GetAssemblies();
|
||||
var defaults = ES3Settings.defaultSettingsScriptableObject;
|
||||
var currentAssemblyNames = defaults.settings.assemblyNames;
|
||||
|
||||
var assemblyNames = new List<string>();
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
try
|
||||
{
|
||||
var name = assembly.name;
|
||||
var substr = name.Length >= 5 ? name.Substring(0, 5) : "";
|
||||
|
||||
if (substr != "Unity" && substr != "com.u" && !name.Contains("-Editor"))
|
||||
assemblyNames.Add(name);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Only update if the list has changed.
|
||||
for (int i = 0; i < currentAssemblyNames.Length; i++)
|
||||
{
|
||||
if (currentAssemblyNames[i] != assemblyNames[i])
|
||||
{
|
||||
defaults.settings.assemblyNames = assemblyNames.ToArray();
|
||||
EditorUtility.SetDirty(defaults);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static GameObject AddManagerToScene()
|
||||
{
|
||||
GameObject mgr = null;
|
||||
if (RefMgr != null)
|
||||
mgr = RefMgr.gameObject;
|
||||
|
||||
if (mgr == null)
|
||||
mgr = new GameObject("Easy Save 3 Manager");
|
||||
|
||||
if (mgr.GetComponent<ES3ReferenceMgr>() == null)
|
||||
{
|
||||
mgr.AddComponent<ES3ReferenceMgr>();
|
||||
|
||||
if (!Application.isPlaying && ES3Settings.defaultSettingsScriptableObject.autoUpdateReferences)
|
||||
RefMgr.RefreshDependencies();
|
||||
}
|
||||
|
||||
if (mgr.GetComponent<ES3AutoSaveMgr>() == null)
|
||||
mgr.AddComponent<ES3AutoSaveMgr>();
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(mgr, "Enabled Easy Save for Scene");
|
||||
return mgr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4256380692bcb4e57bdc0a5e13956389
|
||||
timeCreated: 1474041535
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,50 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using ES3Internal;
|
||||
|
||||
[CustomEditor(typeof(ES3Prefab))]
|
||||
[System.Serializable]
|
||||
public class ES3PrefabEditor : Editor
|
||||
{
|
||||
bool showAdvanced = false;
|
||||
bool openLocalRefs = false;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var es3Prefab = (ES3Prefab)serializedObject.targetObject;
|
||||
EditorGUILayout.HelpBox("Easy Save is enabled for this prefab, and can be saved and loaded with the ES3 methods.", MessageType.None);
|
||||
|
||||
|
||||
showAdvanced = EditorGUILayout.Foldout(showAdvanced, "Advanced Settings");
|
||||
if(showAdvanced)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
es3Prefab.prefabId = EditorGUILayout.LongField("Prefab ID", es3Prefab.prefabId);
|
||||
EditorGUILayout.LabelField("Reference count", es3Prefab.localRefs.Count.ToString());
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
openLocalRefs = EditorGUILayout.Foldout(openLocalRefs, "localRefs");
|
||||
if (openLocalRefs)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditorGUILayout.LabelField("It is not recommended to manually modify these.");
|
||||
|
||||
foreach (var kvp in es3Prefab.localRefs)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUILayout.ObjectField(kvp.Key, typeof(UnityEngine.Object), false);
|
||||
EditorGUILayout.LongField(kvp.Value);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9d25610c9233c4cdfa5a0744c9956f5c
|
||||
timeCreated: 1519132292
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,186 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[CustomEditor(typeof(ES3ReferenceMgr))]
|
||||
[System.Serializable]
|
||||
public class ES3ReferenceMgrEditor : Editor
|
||||
{
|
||||
private bool isDraggingOver = false;
|
||||
private bool openReferences = false;
|
||||
|
||||
private ES3ReferenceMgr _mgr = null;
|
||||
private ES3ReferenceMgr mgr
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mgr == null)
|
||||
_mgr = (ES3ReferenceMgr)serializedObject.targetObject;
|
||||
return _mgr;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox("This allows Easy Save to maintain references to objects in your scene.\n\nIt is automatically updated when you enter Playmode or build your project.", MessageType.Info);
|
||||
|
||||
if (EditorGUILayout.Foldout(openReferences, "References") != openReferences)
|
||||
{
|
||||
openReferences = !openReferences;
|
||||
if (openReferences == true)
|
||||
openReferences = EditorUtility.DisplayDialog("Are you sure?", "Opening this list will display every reference in the manager, which for larger projects can cause the Editor to freeze\n\nIt is strongly recommended that you save your project before continuing.", "Open References", "Cancel");
|
||||
}
|
||||
|
||||
// Make foldout drag-and-drop enabled for objects.
|
||||
if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
|
||||
{
|
||||
Event evt = Event.current;
|
||||
|
||||
switch (evt.type)
|
||||
{
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
isDraggingOver = true;
|
||||
break;
|
||||
case EventType.DragExited:
|
||||
isDraggingOver = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isDraggingOver)
|
||||
{
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
|
||||
if (evt.type == EventType.DragPerform)
|
||||
{
|
||||
DragAndDrop.AcceptDrag();
|
||||
Undo.RecordObject(mgr, "Add References to Easy Save 3 Reference List");
|
||||
foreach (UnityEngine.Object obj in DragAndDrop.objectReferences)
|
||||
mgr.Add(obj);
|
||||
// Return now because otherwise we'll change the GUI during an event which doesn't allow it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openReferences)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
foreach (var kvp in mgr.idRef)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
var value = EditorGUILayout.ObjectField(kvp.Value, typeof(UnityEngine.Object), true);
|
||||
var key = EditorGUILayout.LongField(kvp.Key);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (value != kvp.Value || key != kvp.Key)
|
||||
{
|
||||
Undo.RecordObject(mgr, "Change Easy Save 3 References");
|
||||
// If we're deleting a value, delete it.
|
||||
if (value == null)
|
||||
mgr.Remove(key);
|
||||
// Else, update the ID.
|
||||
else
|
||||
mgr.ChangeId(kvp.Key, key);
|
||||
// Break, as removing or changing Dictionary items will make the foreach out of sync.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
mgr.openPrefabs = EditorGUILayout.Foldout(mgr.openPrefabs, "ES3Prefabs");
|
||||
if (mgr.openPrefabs)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
foreach (var prefab in mgr.prefabs)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUILayout.ObjectField(prefab, typeof(UnityEngine.Object), true);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Reference count", mgr.refId.Count.ToString());
|
||||
EditorGUILayout.LabelField("Prefab count", mgr.prefabs.Count.ToString());
|
||||
|
||||
if (GUILayout.Button("Refresh"))
|
||||
{
|
||||
mgr.RefreshDependencies();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Optimize"))
|
||||
{
|
||||
mgr.Optimize();
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Easy Save 3/Add Reference(s) to Manager", false, 33)]
|
||||
[MenuItem("Assets/Easy Save 3/Add Reference(s) to Manager", false, 33)]
|
||||
public static void AddReferenceToManager()
|
||||
{
|
||||
var mgr = ES3ReferenceMgr.Current;
|
||||
if (mgr == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Could not add reference to manager", "This object could not be added to the reference manager because no reference manager exists in this scene. To create one, go to Assets > Easy Save 3 > Add Manager to Scene", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Selection.objects == null || Selection.objects.Length == 0)
|
||||
return;
|
||||
|
||||
Undo.RecordObject(mgr, "Update Easy Save 3 Reference Manager");
|
||||
|
||||
foreach (var obj in Selection.objects)
|
||||
{
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
if (obj.GetType() == typeof(GameObject))
|
||||
{
|
||||
var go = (GameObject)obj;
|
||||
if (ES3EditorUtility.IsPrefabInAssets(go) && go.GetComponent<ES3Internal.ES3Prefab>() != null)
|
||||
mgr.AddPrefab(go.GetComponent<ES3Internal.ES3Prefab>());
|
||||
}
|
||||
|
||||
((ES3ReferenceMgr)mgr).AddDependencies(obj);
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Easy Save 3/Add Reference(s) to Manager", true, 33)]
|
||||
[MenuItem("Assets/Easy Save 3/Add Reference(s) to Manager", true, 33)]
|
||||
private static bool CanAddReferenceToManager()
|
||||
{
|
||||
return Selection.objects != null && Selection.objects.Length > 0 && ES3ReferenceMgr.Current != null;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Easy Save 3/Add Manager to Scene", false, 33)]
|
||||
[MenuItem("Assets/Easy Save 3/Add Manager to Scene", false, 33)]
|
||||
[MenuItem("Tools/Easy Save 3/Add Manager to Scene", false, 150)]
|
||||
public static void EnableForScene()
|
||||
{
|
||||
if(!SceneManager.GetActiveScene().isLoaded)
|
||||
EditorUtility.DisplayDialog("Could not add manager to scene", "Could not add Easy Save 3 Manager to scene because there is not currently a scene open.", "Ok");
|
||||
Selection.activeObject = ES3Postprocessor.AddManagerToScene();
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/Easy Save 3/Add Manager to Scene", true, 33)]
|
||||
[MenuItem("Assets/Easy Save 3/Add Manager to Scene", true, 33)]
|
||||
[MenuItem("Tools/Easy Save 3/Add Manager to Scene", true, 150)]
|
||||
private static bool CanEnableForScene()
|
||||
{
|
||||
return ES3ReferenceMgr.Current == null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b43d266ed3464dedaa77757645ad61c
|
||||
timeCreated: 1519132283
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
[ES3PropertiesAttribute([propertyNames])]
|
||||
public class ES3UserType_[es3TypeSuffix] : ES3ScriptableObjectType
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]() : base(typeof([fullType])){ Instance = this; priority = 1; }
|
||||
|
||||
|
||||
protected override void WriteScriptableObject(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
[writes]
|
||||
}
|
||||
|
||||
protected override void ReadScriptableObject<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
foreach(string propertyName in reader.Properties)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ES3UserType_[es3TypeSuffix]Array : ES3ArrayType
|
||||
{
|
||||
public static ES3Type Instance;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]Array() : base(typeof([fullType][]), ES3UserType_[es3TypeSuffix].Instance)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3b4ae594e55834c35b197df04c2e81cb
|
||||
timeCreated: 1483698819
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using ES3Internal;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public static class ES3SettingsEditor
|
||||
{
|
||||
public static void Draw(ES3SerializableSettings settings)
|
||||
{
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
settings.location = (ES3.Location)EditorGUILayout.EnumPopup("Location", settings.location);
|
||||
// If the location is File, show the Directory.
|
||||
if(settings.location == ES3.Location.File)
|
||||
settings.directory = (ES3.Directory)EditorGUILayout.EnumPopup("Directory", settings.directory);
|
||||
|
||||
settings.path = EditorGUILayout.TextField("Default File Path", settings.path);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
settings.encryptionType = (ES3.EncryptionType)EditorGUILayout.EnumPopup("Encryption", settings.encryptionType);
|
||||
settings.encryptionPassword = EditorGUILayout.TextField("Encryption Password", settings.encryptionPassword);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
settings.compressionType = (ES3.CompressionType)EditorGUILayout.EnumPopup("Compression", settings.compressionType);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
settings.saveChildren = EditorGUILayout.Toggle("Save GameObject Children", settings.saveChildren);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if(settings.showAdvancedSettings = EditorGUILayout.Foldout(settings.showAdvancedSettings, "Advanced Settings"))
|
||||
{
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
settings.format = (ES3.Format)EditorGUILayout.EnumPopup("Format", settings.format);
|
||||
if (settings.format == ES3.Format.JSON)
|
||||
settings.prettyPrint = EditorGUILayout.Toggle(new GUIContent("Pretty print JSON"), settings.prettyPrint);
|
||||
settings.bufferSize = EditorGUILayout.IntField("Buffer Size", settings.bufferSize);
|
||||
settings.memberReferenceMode = (ES3.ReferenceMode)EditorGUILayout.EnumPopup("Serialise Unity Object fields", settings.memberReferenceMode);
|
||||
settings.serializationDepthLimit = EditorGUILayout.IntField("Serialisation Depth", settings.serializationDepthLimit);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 35659b9a083a341d7bee216c4b71f4bc
|
||||
timeCreated: 1519132282
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
[ES3PropertiesAttribute([propertyNames])]
|
||||
public class ES3UserType_[es3TypeSuffix] : ES3Type
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]() : base(typeof([fullType])){ Instance = this; priority = 1;}
|
||||
|
||||
|
||||
public override void Write(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
[writes]
|
||||
}
|
||||
|
||||
public override object Read<T>(ES3Reader reader)
|
||||
{
|
||||
var instance = new [fullType]();
|
||||
ReadInto<T>(reader, instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public override void ReadInto<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
string propertyName;
|
||||
while((propertyName = reader.ReadPropertyName()) != null)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ES3UserType_[es3TypeSuffix]Array : ES3ArrayType
|
||||
{
|
||||
public static ES3Type Instance;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]Array() : base(typeof([fullType][]), ES3UserType_[es3TypeSuffix].Instance)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e84ec2bd739f543b0a5cd3c13741f744
|
||||
timeCreated: 1483718243
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public class ES3UserType_Material : ES3UnityObjectType
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_Material() : base(typeof(UnityEngine.Material)){ Instance = this; priority = 1; }
|
||||
|
||||
|
||||
protected override void WriteUnityObject(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = (UnityEngine.Material)obj;
|
||||
|
||||
writer.WriteProperty("shader", instance.shader);
|
||||
writer.WriteProperty("renderQueue", instance.renderQueue, ES3Type_int.Instance);
|
||||
writer.WriteProperty("shaderKeywords", instance.shaderKeywords);
|
||||
writer.WriteProperty("globalIlluminationFlags", instance.globalIlluminationFlags);
|
||||
[writes]
|
||||
}
|
||||
|
||||
protected override object ReadUnityObject<T>(ES3Reader reader)
|
||||
{
|
||||
var obj = new Material(Shader.Find("Diffuse"));
|
||||
ReadUnityObject<T>(reader, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected override void ReadUnityObject<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
var instance = (UnityEngine.Material)obj;
|
||||
foreach(string propertyName in reader.Properties)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
case "name":
|
||||
instance.name = reader.Read<string>(ES3Type_string.Instance);
|
||||
break;
|
||||
case "shader":
|
||||
instance.shader = reader.Read<UnityEngine.Shader>(ES3Type_Shader.Instance);
|
||||
break;
|
||||
case "renderQueue":
|
||||
instance.renderQueue = reader.Read<System.Int32>(ES3Type_int.Instance);
|
||||
break;
|
||||
case "shaderKeywords":
|
||||
instance.shaderKeywords = reader.Read<System.String[]>();
|
||||
break;
|
||||
case "globalIlluminationFlags":
|
||||
instance.globalIlluminationFlags = reader.Read<UnityEngine.MaterialGlobalIlluminationFlags>();
|
||||
break;
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f90b0399488ef42e5bc804122fd99c58
|
||||
timeCreated: 1483698819
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
[ES3PropertiesAttribute([propertyNames])]
|
||||
public class ES3UserType_[es3TypeSuffix] : ES3Type
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]() : base(typeof([fullType])){ Instance = this; priority = 1;}
|
||||
|
||||
|
||||
public override void Write(object obj, ES3Writer writer)
|
||||
{
|
||||
var instance = ([fullType])obj;
|
||||
[writes]
|
||||
}
|
||||
|
||||
public override object Read<T>(ES3Reader reader)
|
||||
{
|
||||
var instance = new [fullType]();
|
||||
string propertyName;
|
||||
while((propertyName = reader.ReadPropertyName()) != null)
|
||||
{
|
||||
switch(propertyName)
|
||||
{
|
||||
[reads]
|
||||
default:
|
||||
reader.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ES3UserType_[es3TypeSuffix]Array : ES3ArrayType
|
||||
{
|
||||
public static ES3Type Instance;
|
||||
|
||||
public ES3UserType_[es3TypeSuffix]Array() : base(typeof([fullType][]), ES3UserType_[es3TypeSuffix].Instance)
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f67742ea0c50242f8af16c3f807b723b
|
||||
timeCreated: 1483718243
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,238 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class ES3Window : EditorWindow
|
||||
{
|
||||
private SubWindow[] windows = null;
|
||||
|
||||
public SubWindow currentWindow;
|
||||
|
||||
[MenuItem("Window/Easy Save 3", false, 1000)]
|
||||
[MenuItem("Assets/Easy Save 3/Open Easy Save 3 Window", false, 1000)]
|
||||
public static void Init()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if(window != null)
|
||||
window.Show();
|
||||
}
|
||||
|
||||
public static void InitAndShowHome()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(HomeWindow));
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Auto Save", false, 100)]
|
||||
public static void InitAndShowAutoSave()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(AutoSaveWindow));
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitAndShowReferences()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(ReferencesWindow));
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Types", false, 100)]
|
||||
public static void InitAndShowTypes()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(TypesWindow));
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitAndShowTypes(System.Type type)
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
var typesWindow = (TypesWindow)window.SetCurrentWindow(typeof(TypesWindow));
|
||||
typesWindow.SelectType(type);
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Settings", false, 100)]
|
||||
public static void InitAndShowSettings()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(SettingsWindow));
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Tools", false, 100)]
|
||||
public static void InitAndShowTools()
|
||||
{
|
||||
// Get existing open window or if none, make a new one:
|
||||
ES3Window window = (ES3Window)EditorWindow.GetWindow(typeof(ES3Window));
|
||||
if (window != null)
|
||||
{
|
||||
window.Show();
|
||||
window.SetCurrentWindow(typeof(ToolsWindow));
|
||||
}
|
||||
}
|
||||
|
||||
public void InitSubWindows()
|
||||
{
|
||||
windows = new SubWindow[]{
|
||||
new HomeWindow(this),
|
||||
new SettingsWindow(this),
|
||||
new ToolsWindow(this),
|
||||
new TypesWindow(this),
|
||||
new AutoSaveWindow(this)
|
||||
//, new ReferencesWindow(this)
|
||||
};
|
||||
}
|
||||
|
||||
void OnLostFocus()
|
||||
{
|
||||
if(currentWindow != null)
|
||||
currentWindow.OnLostFocus();
|
||||
}
|
||||
|
||||
private void OnFocus()
|
||||
{
|
||||
if (currentWindow != null)
|
||||
currentWindow.OnFocus();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if(currentWindow != null)
|
||||
currentWindow.OnDestroy();
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if(windows == null)
|
||||
InitSubWindows();
|
||||
// Set the window name and icon.
|
||||
var icon = AssetDatabase.LoadAssetAtPath<Texture2D>(ES3Settings.PathToEasySaveFolder()+"Editor/es3Logo16x16.png");
|
||||
titleContent = new GUIContent("Easy Save", icon);
|
||||
|
||||
// Get the last opened window and open it.
|
||||
if(currentWindow == null)
|
||||
{
|
||||
var currentWindowName = EditorPrefs.GetString("ES3Editor.Window.currentWindow", windows[0].name);
|
||||
for(int i=0; i<windows.Length; i++)
|
||||
{
|
||||
if(windows[i].name == currentWindowName)
|
||||
{
|
||||
currentWindow = windows[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHierarchyChange()
|
||||
{
|
||||
if (currentWindow != null)
|
||||
currentWindow.OnHierarchyChange();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
// Display the menu.
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
for(int i=0; i<windows.Length; i++)
|
||||
{
|
||||
if(GUILayout.Button(windows[i].name, currentWindow == windows[i] ? style.menuButtonSelected : style.menuButton))
|
||||
SetCurrentWindow(windows[i]);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if(currentWindow != null)
|
||||
currentWindow.OnGUI();
|
||||
}
|
||||
|
||||
void SetCurrentWindow(SubWindow window)
|
||||
{
|
||||
if (currentWindow != null)
|
||||
currentWindow.OnLostFocus();
|
||||
currentWindow = window;
|
||||
currentWindow.OnFocus();
|
||||
EditorPrefs.SetString("ES3Editor.Window.currentWindow", window.name);
|
||||
}
|
||||
|
||||
SubWindow SetCurrentWindow(System.Type type)
|
||||
{
|
||||
currentWindow.OnLostFocus();
|
||||
currentWindow = windows.First(w => w.GetType() == type);
|
||||
EditorPrefs.SetString("ES3Editor.Window.currentWindow", currentWindow.name);
|
||||
return currentWindow;
|
||||
}
|
||||
|
||||
// Shows the Easy Save Home window if it's not been disabled.
|
||||
// This method is called from the Postprocessor.
|
||||
public static void OpenEditorWindowOnStart()
|
||||
{
|
||||
if(EditorPrefs.GetBool("Show ES3 Window on Start", true))
|
||||
ES3Window.InitAndShowHome();
|
||||
EditorPrefs.SetBool("Show ES3 Window on Start", false);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SubWindow
|
||||
{
|
||||
public string name;
|
||||
public EditorWindow parent;
|
||||
public abstract void OnGUI();
|
||||
|
||||
public SubWindow(string name, EditorWindow parent)
|
||||
{
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public virtual void OnLostFocus()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnFocus()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnHierarchyChange()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a95d98897f1cf4e7288b53b0fd8036c1
|
||||
timeCreated: 1519132293
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,70 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class HomeWindow : SubWindow
|
||||
{
|
||||
Vector2 scrollPos = Vector2.zero;
|
||||
|
||||
public HomeWindow(EditorWindow window) : base("Home", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
GUILayout.Label("Welcome to Easy Save", style.heading);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
GUILayout.Label("New To Easy Save?", style.subheading);
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
ES3EditorUtility.DisplayLink("• See our Getting Started guide", "http://docs.moodkie.com/easy-save-3/getting-started/");
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUILayout.Label("Support", style.subheading);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
ES3EditorUtility.DisplayLink("• Contact us directly", "http://www.moodkie.com/contact/");
|
||||
ES3EditorUtility.DisplayLink("• Ask a question in our Easy Save 3 forums", "http://moodkie.com/forum/viewforum.php?f=12");
|
||||
ES3EditorUtility.DisplayLink("• Ask a question in the Unity Forum thread","https://forum.unity3d.com/threads/easy-save-the-complete-save-load-asset-for-unity.91040/");
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUILayout.Label("Documentation and Guides", style.subheading);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
ES3EditorUtility.DisplayLink("• Documentation", "http://docs.moodkie.com/product/easy-save-3/");
|
||||
ES3EditorUtility.DisplayLink("• Guides", "http://docs.moodkie.com/product/easy-save-3/es3-guides/");
|
||||
ES3EditorUtility.DisplayLink("• API Scripting Reference", "http://docs.moodkie.com/product/easy-save-3/es3-api/");
|
||||
ES3EditorUtility.DisplayLink("• Supported Types", "http://docs.moodkie.com/easy-save-3/es3-supported-types/");
|
||||
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUILayout.Label("PlayMaker Documentation", style.subheading);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
ES3EditorUtility.DisplayLink("• Actions", "http://docs.moodkie.com/product/easy-save-3/es3-playmaker/es3-playmaker-actions/");
|
||||
ES3EditorUtility.DisplayLink("• Actions Overview", "http://docs.moodkie.com/easy-save-3/es3-playmaker/playmaker-actions-overview/");
|
||||
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 394cc2e77038849709526f44f7efdd22
|
||||
timeCreated: 1519132283
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,21 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using ES3Internal;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class ReferencesWindow : SubWindow
|
||||
{
|
||||
|
||||
|
||||
public ReferencesWindow(EditorWindow window) : base("References", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: af2d805793e784eef87fbcdebb11fa35
|
||||
timeCreated: 1519132291
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,135 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using ES3Internal;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class SettingsWindow : SubWindow
|
||||
{
|
||||
public ES3Defaults editorSettings = null;
|
||||
public ES3SerializableSettings settings = null;
|
||||
public SerializedObject so = null;
|
||||
public SerializedProperty assemblyNamesProperty = null;
|
||||
|
||||
private Vector2 scrollPos = Vector2.zero;
|
||||
|
||||
public SettingsWindow(EditorWindow window) : base("Settings", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
if(settings == null || editorSettings == null || assemblyNamesProperty == null)
|
||||
Init();
|
||||
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
using (var scrollView = new EditorGUILayout.ScrollViewScope(scrollPos, style.area))
|
||||
{
|
||||
scrollPos = scrollView.scrollPosition;
|
||||
|
||||
EditorGUIUtility.labelWidth = 160;
|
||||
|
||||
GUILayout.Label("Runtime Settings", style.heading);
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(style.area))
|
||||
{
|
||||
ES3SettingsEditor.Draw(settings);
|
||||
}
|
||||
|
||||
GUILayout.Label("Debug Settings", style.heading);
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(style.area))
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 100;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Log Info");
|
||||
editorSettings.logDebugInfo = EditorGUILayout.Toggle(editorSettings.logDebugInfo);
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Log Warnings");
|
||||
editorSettings.logWarnings = EditorGUILayout.Toggle(editorSettings.logWarnings);
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Log Errors");
|
||||
editorSettings.logErrors = EditorGUILayout.Toggle(editorSettings.logErrors);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
GUILayout.Label("Editor Settings", style.heading);
|
||||
|
||||
using (new EditorGUILayout.VerticalScope(style.area))
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 170;
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Auto Update References");
|
||||
editorSettings.autoUpdateReferences = EditorGUILayout.Toggle(editorSettings.autoUpdateReferences);
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Use Global References");
|
||||
|
||||
var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
bool useGlobalReferences = !symbols.Contains("ES3GLOBAL_DISABLED");
|
||||
if(EditorGUILayout.Toggle(useGlobalReferences) != useGlobalReferences)
|
||||
{
|
||||
// Remove the existing symbol even if we're disabling global references, just incase it's already in there.
|
||||
symbols = symbols.Replace("ES3GLOBAL_DISABLED;", ""); // With semicolon
|
||||
symbols = symbols.Replace("ES3GLOBAL_DISABLED", ""); // Without semicolon
|
||||
|
||||
// Add the symbol if useGlobalReferences is currently true, meaning that we want to disable it.
|
||||
if (useGlobalReferences)
|
||||
symbols = "ES3GLOBAL_DISABLED;" + symbols;
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols);
|
||||
|
||||
if(useGlobalReferences)
|
||||
EditorUtility.DisplayDialog("Global references disabled for build platform", "This will only disable Global References for this build platform. To disable it for other build platforms, open that platform in the Build Settings and uncheck this box again.", "Ok");
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
EditorGUILayout.PrefixLabel("Add All Prefabs to Manager");
|
||||
editorSettings.addAllPrefabsToManager = EditorGUILayout.Toggle(editorSettings.addAllPrefabsToManager);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
EditorUtility.SetDirty(editorSettings);
|
||||
|
||||
EditorGUIUtility.labelWidth = labelWidth; // Set the label width back to default
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
editorSettings = ES3Settings.defaultSettingsScriptableObject;
|
||||
|
||||
settings = editorSettings.settings;
|
||||
/*so = new SerializedObject(editorSettings);
|
||||
var settingsProperty = so.FindProperty("settings");
|
||||
assemblyNamesProperty = settingsProperty.FindPropertyRelative("assemblyNames");*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 95e7bbc9a5aee44feb088811fb5e7b80
|
||||
timeCreated: 1519132291
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,155 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class ToolsWindow : SubWindow
|
||||
{
|
||||
public ToolsWindow(EditorWindow window) : base("Tools", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
EditorGUILayout.BeginHorizontal(style.area);
|
||||
|
||||
if (GUILayout.Button("Open Persistent Data Path"))
|
||||
OpenPersistentDataPath();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal(style.area);
|
||||
|
||||
if (GUILayout.Button("Clear Persistent Data Path"))
|
||||
ClearPersistentDataPath();
|
||||
|
||||
if (GUILayout.Button("Clear PlayerPrefs"))
|
||||
ClearPlayerPrefs();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Open Persistent Data Path", false, 200)]
|
||||
private static void OpenPersistentDataPath()
|
||||
{
|
||||
OSFileBrowser.Open(Application.persistentDataPath);
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Clear Persistent Data Path", false, 200)]
|
||||
private static void ClearPersistentDataPath()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear Persistent Data Path", "Are you sure you wish to clear the persistent data path?\n This action cannot be reversed.", "Clear", "Cancel"))
|
||||
{
|
||||
System.IO.DirectoryInfo di = new DirectoryInfo(Application.persistentDataPath);
|
||||
|
||||
foreach (FileInfo file in di.GetFiles())
|
||||
file.Delete();
|
||||
foreach (DirectoryInfo dir in di.GetDirectories())
|
||||
dir.Delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
[MenuItem("Tools/Easy Save 3/Clear PlayerPrefs", false, 200)]
|
||||
private static void ClearPlayerPrefs()
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear PlayerPrefs", "Are you sure you wish to clear PlayerPrefs?\nThis action cannot be reversed.", "Clear", "Cancel"))
|
||||
PlayerPrefs.DeleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
public static class OSFileBrowser
|
||||
{
|
||||
public static bool IsInMacOS
|
||||
{
|
||||
get
|
||||
{
|
||||
return UnityEngine.SystemInfo.operatingSystem.IndexOf("Mac OS") != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsInWinOS
|
||||
{
|
||||
get
|
||||
{
|
||||
return UnityEngine.SystemInfo.operatingSystem.IndexOf("Windows") != -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenInMac(string path)
|
||||
{
|
||||
bool openInsidesOfFolder = false;
|
||||
|
||||
// try mac
|
||||
string macPath = path.Replace("\\", "/"); // mac finder doesn't like backward slashes
|
||||
|
||||
if ( System.IO.Directory.Exists(macPath) ) // if path requested is a folder, automatically open insides of that folder
|
||||
{
|
||||
openInsidesOfFolder = true;
|
||||
}
|
||||
|
||||
if ( !macPath.StartsWith("\"") )
|
||||
{
|
||||
macPath = "\"" + macPath;
|
||||
}
|
||||
|
||||
if ( !macPath.EndsWith("\"") )
|
||||
{
|
||||
macPath = macPath + "\"";
|
||||
}
|
||||
|
||||
string arguments = (openInsidesOfFolder ? "" : "-R ") + macPath;
|
||||
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Process.Start("open", arguments);
|
||||
}
|
||||
catch ( System.ComponentModel.Win32Exception e )
|
||||
{
|
||||
// tried to open mac finder in windows
|
||||
// just silently skip error
|
||||
// we currently have no platform define for the current OS we are in, so we resort to this
|
||||
e.HelpLink = ""; // do anything with this variable to silence warning about not using it
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenInWin(string path)
|
||||
{
|
||||
bool openInsidesOfFolder = false;
|
||||
|
||||
// try windows
|
||||
string winPath = path.Replace("/", "\\"); // windows explorer doesn't like forward slashes
|
||||
|
||||
if ( System.IO.Directory.Exists(winPath) ) // if path requested is a folder, automatically open insides of that folder
|
||||
openInsidesOfFolder = true;
|
||||
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Process.Start("explorer.exe", (openInsidesOfFolder ? "/root," : "/select,") + "\"" + winPath + "\"");
|
||||
}
|
||||
catch ( System.ComponentModel.Win32Exception e )
|
||||
{
|
||||
e.HelpLink = "";
|
||||
}
|
||||
}
|
||||
|
||||
public static void Open(string path)
|
||||
{
|
||||
if ( IsInWinOS )
|
||||
{
|
||||
OpenInWin(path);
|
||||
}
|
||||
else if ( IsInMacOS )
|
||||
{
|
||||
OpenInMac(path);
|
||||
}
|
||||
else // couldn't determine OS
|
||||
{
|
||||
OpenInWin(path);
|
||||
OpenInMac(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0d6114c1d40624e9e8575e814c45ac1a
|
||||
timeCreated: 1519132280
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,724 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using ES3Types;
|
||||
using System.IO;
|
||||
using ES3Internal;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ES3Editor
|
||||
{
|
||||
public class TypesWindow : SubWindow
|
||||
{
|
||||
TypeListItem[] types = null;
|
||||
const int recentTypeCount = 5;
|
||||
List<int> recentTypes = new List<int>(recentTypeCount);
|
||||
|
||||
Vector2 typeListScrollPos = Vector2.zero;
|
||||
Vector2 typePaneScrollPos = Vector2.zero;
|
||||
int leftPaneWidth = 300;
|
||||
|
||||
string searchFieldValue = "";
|
||||
|
||||
int selectedType = -1;
|
||||
private ES3Reflection.ES3ReflectedMember[] fields = new ES3Reflection.ES3ReflectedMember[0];
|
||||
private bool[] fieldSelected = new bool[0];
|
||||
|
||||
private Texture2D checkmark;
|
||||
//private Texture2D checkmarkSmall;
|
||||
|
||||
private GUIStyle searchBarStyle;
|
||||
private GUIStyle searchBarCancelButtonStyle;
|
||||
private GUIStyle leftPaneStyle;
|
||||
private GUIStyle typeButtonStyle;
|
||||
private GUIStyle selectedTypeButtonStyle;
|
||||
private GUIStyle selectAllNoneButtonStyle;
|
||||
|
||||
private string valueTemplateFile;
|
||||
private string classTemplateFile;
|
||||
private string componentTemplateFile;
|
||||
private string scriptableObjectTemplateFile;
|
||||
|
||||
private bool unsavedChanges = false;
|
||||
|
||||
public TypesWindow(EditorWindow window) : base("Types", window){}
|
||||
|
||||
public override void OnGUI()
|
||||
{
|
||||
if(types == null)
|
||||
Init();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUILayout.BeginVertical(leftPaneStyle);
|
||||
SearchBar();
|
||||
TypeList();
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.BeginVertical();
|
||||
TypePane();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void SearchBar()
|
||||
{
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
GUILayout.Label("Enter a type name in the field below\n* Type names are case-sensitive *", style.subheading2);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
// Set control name so we can force a Focus reset for it.
|
||||
string currentSearchFieldValue = EditorGUILayout.TextField(searchFieldValue, searchBarStyle);
|
||||
|
||||
if(searchFieldValue != currentSearchFieldValue)
|
||||
{
|
||||
searchFieldValue = currentSearchFieldValue;
|
||||
PerformSearch(currentSearchFieldValue);
|
||||
}
|
||||
|
||||
GUI.SetNextControlName("Clear");
|
||||
|
||||
if(GUILayout.Button("x", searchBarCancelButtonStyle))
|
||||
{
|
||||
searchFieldValue = "";
|
||||
GUI.FocusControl("Clear");
|
||||
PerformSearch("");
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void RecentTypeList()
|
||||
{
|
||||
if(!string.IsNullOrEmpty(searchFieldValue) || recentTypes.Count == 0)
|
||||
return;
|
||||
|
||||
for(int i=recentTypes.Count-1; i>-1; i--)
|
||||
TypeButton(recentTypes[i]);
|
||||
|
||||
EditorGUILayout.TextArea("",GUI.skin.horizontalSlider);
|
||||
|
||||
}
|
||||
|
||||
private void TypeList()
|
||||
{
|
||||
if(!string.IsNullOrEmpty(searchFieldValue))
|
||||
GUILayout.Label("Search Results", EditorStyles.boldLabel);
|
||||
|
||||
typeListScrollPos = EditorGUILayout.BeginScrollView(typeListScrollPos);
|
||||
|
||||
RecentTypeList();
|
||||
|
||||
if(!string.IsNullOrEmpty(searchFieldValue))
|
||||
for(int i = 0; i < types.Length; i++)
|
||||
TypeButton(i);
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void TypePane()
|
||||
{
|
||||
if(selectedType < 0)
|
||||
return;
|
||||
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
var typeListItem = types[selectedType];
|
||||
var type = typeListItem.type;
|
||||
|
||||
typePaneScrollPos = EditorGUILayout.BeginScrollView(typePaneScrollPos, style.area);
|
||||
|
||||
GUILayout.Label(typeListItem.name, style.subheading);
|
||||
GUILayout.Label(typeListItem.namespaceName);
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
bool hasParameterlessConstructor = ES3Reflection.HasParameterlessConstructor(type);
|
||||
bool isComponent = ES3Reflection.IsAssignableFrom(typeof(Component), type);
|
||||
|
||||
string path = GetOutputPath(types[selectedType].type);
|
||||
// An ES3Type file already exists.
|
||||
if(File.Exists(path))
|
||||
{
|
||||
if(hasParameterlessConstructor || isComponent)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if(GUILayout.Button("Reset to Default"))
|
||||
{
|
||||
SelectNone(true, true);
|
||||
AssetDatabase.MoveAssetToTrash("Assets" + path.Remove(0, Application.dataPath.Length));
|
||||
SelectType(selectedType);
|
||||
}
|
||||
if(GUILayout.Button("Edit ES3Type Script"))
|
||||
AssetDatabase.OpenAsset(AssetDatabase.LoadMainAssetAtPath("Assets" + path.Remove(0, Application.dataPath.Length)));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to modify the ES3Type script to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
|
||||
if(GUILayout.Button("Click here to edit the ES3Type script"))
|
||||
AssetDatabase.OpenAsset(AssetDatabase.LoadMainAssetAtPath("Assets" + path.Remove(0, Application.dataPath.Length)));
|
||||
if (GUILayout.Button("Reset to Default"))
|
||||
{
|
||||
SelectAll(true, true);
|
||||
File.Delete(path);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
// No ES3Type file and no fields.
|
||||
else if(fields.Length == 0)
|
||||
{
|
||||
if(!hasParameterlessConstructor && !isComponent)
|
||||
EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to create an ES3Type script and modify it to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
|
||||
|
||||
if(GUILayout.Button("Create ES3Type Script"))
|
||||
Generate();
|
||||
}
|
||||
// No ES3Type file, but fields are selectable.
|
||||
else
|
||||
{
|
||||
if(!hasParameterlessConstructor && !isComponent)
|
||||
{
|
||||
EditorGUILayout.HelpBox("This type has no public parameterless constructors.\n\nTo support this type you will need to select the fields you wish to serialize below, and then modify the generated ES3Type script to use a specific constructor instead of the parameterless constructor.", MessageType.Info);
|
||||
if(GUILayout.Button("Select all fields and generate ES3Type script"))
|
||||
{
|
||||
SelectAll(true, false);
|
||||
Generate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GUILayout.Button("Create ES3Type Script"))
|
||||
Generate();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
PropertyPane();
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void PropertyPane()
|
||||
{
|
||||
var style = EditorStyle.Get;
|
||||
|
||||
EditorGUILayout.BeginVertical(style.area);
|
||||
|
||||
GUILayout.Label("Fields", EditorStyles.boldLabel);
|
||||
|
||||
DisplayFieldsOrProperties(true, false);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
GUILayout.Label("Properties", EditorStyles.boldLabel);
|
||||
|
||||
DisplayFieldsOrProperties(false, true);
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DisplayFieldsOrProperties(bool showFields, bool showProperties)
|
||||
{
|
||||
// Get field and property counts.
|
||||
int fieldCount = 0;
|
||||
int propertyCount = 0;
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
{
|
||||
if(fields[i].isProperty && showProperties)
|
||||
propertyCount++;
|
||||
else if((!fields[i].isProperty) && showFields)
|
||||
fieldCount++;
|
||||
}
|
||||
|
||||
// If there is nothing to display, show message.
|
||||
if(showFields && showProperties && fieldCount == 0 && propertyCount == 0)
|
||||
GUILayout.Label("This type has no serializable fields or properties.");
|
||||
else if(showFields && fieldCount == 0)
|
||||
GUILayout.Label("This type has no serializable fields.");
|
||||
else if(showProperties && propertyCount == 0)
|
||||
GUILayout.Label("This type has no serializable properties.");
|
||||
|
||||
// Display Select All/Select None buttons only if there are fields to display.
|
||||
if(fieldCount > 0 || propertyCount > 0)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if(GUILayout.Button("Select All", selectAllNoneButtonStyle))
|
||||
{
|
||||
SelectAll(showFields, showProperties);
|
||||
Generate();
|
||||
}
|
||||
|
||||
if(GUILayout.Button("Select None", selectAllNoneButtonStyle))
|
||||
{
|
||||
SelectNone(showFields, showProperties);
|
||||
Generate();
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
if((field.isProperty && !showProperties) || ((!field.isProperty) && !showFields))
|
||||
continue;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
var content = new GUIContent(field.Name);
|
||||
|
||||
if(typeof(UnityEngine.Object).IsAssignableFrom(field.MemberType))
|
||||
content.tooltip = field.MemberType.ToString() + "\nSaved by reference";
|
||||
else
|
||||
content.tooltip = field.MemberType.ToString() + "\nSaved by value";
|
||||
|
||||
|
||||
|
||||
bool selected = EditorGUILayout.ToggleLeft(content, fieldSelected[i]);
|
||||
if(selected != fieldSelected[i])
|
||||
{
|
||||
fieldSelected[i] = selected;
|
||||
unsavedChanges = true;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
// Selects all fields, properties or both.
|
||||
private void SelectAll(bool selectFields, bool selectProperties)
|
||||
{
|
||||
for(int i=0; i<fieldSelected.Length; i++)
|
||||
if((fields[i].isProperty && selectProperties) || (!fields[i].isProperty) && selectFields)
|
||||
fieldSelected[i] = true;
|
||||
}
|
||||
|
||||
// Selects all fields, properties or both.
|
||||
private void SelectNone(bool selectFields, bool selectProperties)
|
||||
{
|
||||
for(int i=0; i<fieldSelected.Length; i++)
|
||||
if((fields[i].isProperty && selectProperties) || (!fields[i].isProperty) && selectFields)
|
||||
fieldSelected[i] = false;
|
||||
}
|
||||
|
||||
public override void OnLostFocus()
|
||||
{
|
||||
if(unsavedChanges)
|
||||
Generate();
|
||||
}
|
||||
|
||||
private void TypeButton(int i)
|
||||
{
|
||||
var type = types[i];
|
||||
if(!types[i].showInList)
|
||||
return;
|
||||
|
||||
if(type.hasExplicitES3Type)
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
|
||||
var thisTypeButtonStyle = (i == selectedType) ? selectedTypeButtonStyle : typeButtonStyle;
|
||||
|
||||
if(GUILayout.Button(new GUIContent(type.name, type.namespaceName), thisTypeButtonStyle))
|
||||
SelectType(i);
|
||||
|
||||
// Set the cursor.
|
||||
var buttonRect = GUILayoutUtility.GetLastRect();
|
||||
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
|
||||
|
||||
|
||||
|
||||
if(type.hasExplicitES3Type)
|
||||
{
|
||||
GUILayout.Box(new GUIContent(checkmark, "Type is explicitly supported"), EditorStyles.largeLabel);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
private void PerformSearch(string query)
|
||||
{
|
||||
var lowerCaseQuery = query.ToLowerInvariant();
|
||||
var emptyQuery = string.IsNullOrEmpty(query);
|
||||
|
||||
for(int i=0; i<types.Length; i++)
|
||||
types[i].showInList = (emptyQuery || types[i].lowercaseName.Contains(lowerCaseQuery));
|
||||
}
|
||||
|
||||
public void SelectType(Type type)
|
||||
{
|
||||
Init();
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
if (types[i].type == type)
|
||||
SelectType(i);
|
||||
}
|
||||
|
||||
private void SelectType(int typeIndex)
|
||||
{
|
||||
selectedType = typeIndex;
|
||||
|
||||
if(selectedType == -1)
|
||||
{
|
||||
SaveType("TypesWindowSelectedType", -1);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveType("TypesWindowSelectedType", selectedType);
|
||||
|
||||
if(!recentTypes.Contains(typeIndex))
|
||||
{
|
||||
// If our recent type queue is full, remove an item before adding another.
|
||||
if(recentTypes.Count == recentTypeCount)
|
||||
recentTypes.RemoveAt(0);
|
||||
recentTypes.Add(typeIndex);
|
||||
for(int j=0; j<recentTypes.Count; j++)
|
||||
SaveType("TypesWindowRecentType"+j, recentTypes[j]);
|
||||
}
|
||||
|
||||
var type = types[selectedType].type;
|
||||
|
||||
fields = ES3Reflection.GetSerializableMembers(type, false);
|
||||
fieldSelected = new bool[fields.Length];
|
||||
|
||||
var es3Type = ES3TypeMgr.GetES3Type(type);
|
||||
// If there's no ES3Type for this, only select fields which are supported by reflection.
|
||||
if(es3Type == null)
|
||||
{
|
||||
var safeFields = ES3Reflection.GetSerializableMembers(type, true);
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
fieldSelected[i] = safeFields.Any(item => item.Name == fields[i].Name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get fields and whether they're selected.
|
||||
var selectedFields = new List<string>();
|
||||
var propertyAttributes = es3Type.GetType().GetCustomAttributes(typeof(ES3PropertiesAttribute), false);
|
||||
if(propertyAttributes.Length > 0)
|
||||
selectedFields.AddRange(((ES3PropertiesAttribute)propertyAttributes[0]).members);
|
||||
|
||||
fieldSelected = new bool[fields.Length];
|
||||
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
fieldSelected[i] = selectedFields.Contains(fields[i].Name);
|
||||
}
|
||||
|
||||
private void SaveType(string key, int typeIndex)
|
||||
{
|
||||
if(typeIndex == -1)
|
||||
return;
|
||||
SaveType(key, types[typeIndex].type);
|
||||
}
|
||||
|
||||
private void SaveType(string key, Type type)
|
||||
{
|
||||
EditorPrefs.SetString(key, type.AssemblyQualifiedName);
|
||||
}
|
||||
|
||||
private int LoadTypeIndex(string key)
|
||||
{
|
||||
string selectedTypeName = EditorPrefs.GetString(key, "");
|
||||
if(selectedTypeName != "")
|
||||
{
|
||||
var type = ES3Reflection.GetType(selectedTypeName);
|
||||
if(type != null)
|
||||
{
|
||||
int typeIndex = GetTypeIndex(type);
|
||||
if(typeIndex != -1)
|
||||
return typeIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int GetTypeIndex(Type type)
|
||||
{
|
||||
for(int i=0; i<types.Length; i++)
|
||||
if(types[i].type == type)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
componentTemplateFile = "ES3ComponentTypeTemplate.txt";
|
||||
classTemplateFile = "ES3ClassTypeTemplate.txt";
|
||||
valueTemplateFile = "ES3ValueTypeTemplate.txt";
|
||||
scriptableObjectTemplateFile = "ES3ScriptableObjectTypeTemplate.txt";
|
||||
|
||||
// Init Type List
|
||||
var tempTypes = new List<TypeListItem> ();
|
||||
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(assembly => !assembly.FullName.Contains("Editor") && assembly.FullName != "ES3" && !assembly.FullName.Contains("ES3")).OrderBy(assembly => assembly.GetName().Name).ToArray();
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var assemblyTypes = assembly.GetTypes();
|
||||
|
||||
for(int i = 0; i < assemblyTypes.Length; i++)
|
||||
{
|
||||
var type = assemblyTypes [i];
|
||||
if(type.IsGenericType || type.IsEnum || type.IsNotPublic || type.IsAbstract || type.IsInterface)
|
||||
continue;
|
||||
|
||||
var typeName = type.Name;
|
||||
if(typeName [0] == '$' || typeName [0] == '_' || typeName [0] == '<')
|
||||
continue;
|
||||
|
||||
var typeNamespace = type.Namespace;
|
||||
var namespaceName = typeNamespace == null ? "" : typeNamespace.ToString();
|
||||
|
||||
tempTypes.Add(new TypeListItem (type.Name, namespaceName, type, true, HasExplicitES3Type(type)));
|
||||
}
|
||||
|
||||
}
|
||||
types = tempTypes.OrderBy(type => type.name).ToArray();
|
||||
|
||||
// Load types and recent types.
|
||||
if(Event.current.type == EventType.Layout)
|
||||
{
|
||||
recentTypes = new List<int>();
|
||||
for(int i=0; i<recentTypeCount; i++)
|
||||
{
|
||||
int typeIndex = LoadTypeIndex("TypesWindowRecentType"+i);
|
||||
if(typeIndex != -1)
|
||||
recentTypes.Add(typeIndex);
|
||||
}
|
||||
SelectType(LoadTypeIndex("TypesWindowSelectedType"));
|
||||
}
|
||||
|
||||
PerformSearch(searchFieldValue);
|
||||
|
||||
// Init Assets.
|
||||
string es3FolderPath = ES3Settings.PathToEasySaveFolder();
|
||||
checkmark = AssetDatabase.LoadAssetAtPath<Texture2D>(es3FolderPath + "Editor/checkmark.png");
|
||||
//checkmarkSmall = AssetDatabase.LoadAssetAtPath<Texture2D>(es3FolderPath + "Editor/checkmarkSmall.png");
|
||||
|
||||
// Init Styles.
|
||||
searchBarCancelButtonStyle = new GUIStyle(EditorStyles.miniButton);
|
||||
var cancelButtonSize = EditorStyles.miniTextField.CalcHeight(new GUIContent(""), 20);
|
||||
searchBarCancelButtonStyle.fixedWidth = cancelButtonSize;
|
||||
searchBarCancelButtonStyle.fixedHeight = cancelButtonSize;
|
||||
searchBarCancelButtonStyle.fontSize = 8;
|
||||
searchBarCancelButtonStyle.padding = new RectOffset();
|
||||
searchBarStyle = new GUIStyle(EditorStyles.toolbarTextField);
|
||||
searchBarStyle.stretchWidth = true;
|
||||
|
||||
typeButtonStyle = new GUIStyle(EditorStyles.largeLabel);
|
||||
typeButtonStyle.alignment = TextAnchor.MiddleLeft;
|
||||
typeButtonStyle.stretchWidth = false;
|
||||
selectedTypeButtonStyle = new GUIStyle(typeButtonStyle);
|
||||
selectedTypeButtonStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
leftPaneStyle = new GUIStyle();
|
||||
leftPaneStyle.fixedWidth = leftPaneWidth;
|
||||
leftPaneStyle.clipping = TextClipping.Clip;
|
||||
leftPaneStyle.padding = new RectOffset(10, 10, 10, 10);
|
||||
|
||||
selectAllNoneButtonStyle = new GUIStyle(EditorStyles.miniButton);
|
||||
selectAllNoneButtonStyle.stretchWidth = false;
|
||||
selectAllNoneButtonStyle.margin = new RectOffset(0,0,0,10);
|
||||
}
|
||||
|
||||
private void Generate()
|
||||
{
|
||||
var type = types[selectedType].type;
|
||||
if(type == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Type not selected", "Type not selected. Please ensure you select a type", "Ok");
|
||||
return;
|
||||
}
|
||||
|
||||
unsavedChanges = false;
|
||||
|
||||
// Get the serializable fields of this class.
|
||||
//var fields = ES3Reflection.GetSerializableES3Fields(type);
|
||||
|
||||
// The string that we suffix to the class name. i.e. UnityEngine_UnityEngine_Transform.
|
||||
string es3TypeSuffix = type.Name;
|
||||
// The string for the full C#-safe type name. This name must be suitable for going inside typeof().
|
||||
string fullType = GetFullTypeName(type);
|
||||
// The list of WriteProperty calls to write the properties of this type.
|
||||
string writes = GenerateWrites();
|
||||
// The list of case statements and Read calls to read the properties of this type.
|
||||
string reads = GenerateReads();
|
||||
// A comma-seperated string of fields we've supported in this type.
|
||||
string propertyNames = "";
|
||||
|
||||
bool first = true;
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
{
|
||||
if(!fieldSelected[i])
|
||||
continue;
|
||||
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
propertyNames += ", ";
|
||||
propertyNames += "\"" + fields[i].Name + "\"";
|
||||
}
|
||||
|
||||
var easySaveEditorPath = ES3Settings.PathToEasySaveFolder()+"Editor/";
|
||||
|
||||
// Insert the relevant strings into the template.
|
||||
string template;
|
||||
if(typeof(Component).IsAssignableFrom(type))
|
||||
template = File.ReadAllText(easySaveEditorPath + componentTemplateFile);
|
||||
else if(ES3Reflection.IsValueType(type))
|
||||
template = File.ReadAllText(easySaveEditorPath + valueTemplateFile);
|
||||
else if(typeof(ScriptableObject).IsAssignableFrom(type))
|
||||
template = File.ReadAllText(easySaveEditorPath + scriptableObjectTemplateFile);
|
||||
else
|
||||
template = File.ReadAllText(easySaveEditorPath + classTemplateFile);
|
||||
template = template.Replace("[es3TypeSuffix]", es3TypeSuffix);
|
||||
template = template.Replace("[fullType]", fullType);
|
||||
template = template.Replace("[writes]", writes);
|
||||
template = template.Replace("[reads]", reads);
|
||||
template = template.Replace("[propertyNames]", propertyNames);
|
||||
|
||||
// Create the output file.
|
||||
|
||||
|
||||
string outputFilePath = GetOutputPath(type);
|
||||
var fileInfo = new FileInfo(outputFilePath);
|
||||
fileInfo.Directory.Create();
|
||||
File.WriteAllText(outputFilePath, template);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private string GenerateWrites()
|
||||
{
|
||||
var type = types[selectedType].type;
|
||||
bool isComponent = typeof(Component).IsAssignableFrom(type);
|
||||
string writes = "";
|
||||
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
var selected = fieldSelected[i];
|
||||
var es3Type = ES3TypeMgr.GetES3Type(field.MemberType);
|
||||
|
||||
if(!selected || isComponent && (field.Name == ES3Reflection.componentTagFieldName || field.Name == ES3Reflection.componentNameFieldName))
|
||||
continue;
|
||||
|
||||
string writeByRef = ES3Reflection.IsAssignableFrom(typeof(UnityEngine.Object), field.MemberType) ? "ByRef" : "";
|
||||
string es3TypeParam = HasExplicitES3Type(es3Type) && writeByRef == "" ? ", " + es3Type.GetType().Name + ".Instance" : (writeByRef == "" ? ", ES3Internal.ES3TypeMgr.GetES3Type(typeof(" + GetFullTypeName(field.MemberType) + "))" : "");
|
||||
// If this is static, access the field through the class name rather than through an instance.
|
||||
string instance = (field.IsStatic) ? GetFullTypeName(type) : "instance";
|
||||
|
||||
if(!field.IsPublic)
|
||||
{
|
||||
string memberType = field.isProperty ? "Property" : "Field";
|
||||
writes += String.Format("\r\n\t\t\twriter.WritePrivate{2}{1}(\"{0}\", instance);", field.Name, writeByRef, memberType);
|
||||
}
|
||||
else
|
||||
writes += String.Format("\r\n\t\t\twriter.WriteProperty{1}(\"{0}\", {3}.{0}{2});", field.Name, writeByRef, es3TypeParam, instance);
|
||||
}
|
||||
return writes;
|
||||
}
|
||||
|
||||
private string GenerateReads()
|
||||
{
|
||||
var type = types[selectedType].type;
|
||||
bool isComponent = typeof(Component).IsAssignableFrom(type);
|
||||
string reads = "";
|
||||
|
||||
for(int i=0; i<fields.Length; i++)
|
||||
{
|
||||
var field = fields[i];
|
||||
var selected = fieldSelected[i];
|
||||
|
||||
if(!selected || isComponent && (field.Name == "tag" || field.Name == "name"))
|
||||
continue;
|
||||
|
||||
string fieldTypeName = GetFullTypeName(field.MemberType);
|
||||
string es3TypeParam = HasExplicitES3Type(field.MemberType) ? ES3TypeMgr.GetES3Type(field.MemberType).GetType().Name+".Instance" : "";
|
||||
// If this is static, access the field through the class name rather than through an instance.
|
||||
string instance = (field.IsStatic) ? GetFullTypeName(type) : "instance";
|
||||
|
||||
// If we're writing a private field or property, we need to write it using a different method.
|
||||
if(!field.IsPublic)
|
||||
{
|
||||
es3TypeParam = ", " + es3TypeParam;
|
||||
if(field.isProperty)
|
||||
reads += String.Format("\r\n\t\t\t\t\tcase \"{0}\":\r\n\t\t\t\t\treader.SetPrivateProperty(\"{0}\", reader.Read<{1}>(), instance);\r\n\t\t\t\t\tbreak;", field.Name, fieldTypeName);
|
||||
else
|
||||
reads += String.Format("\r\n\t\t\t\t\tcase \"{0}\":\r\n\t\t\t\t\treader.SetPrivateField(\"{0}\", reader.Read<{1}>(), instance);\r\n\t\t\t\t\tbreak;", field.Name, fieldTypeName);
|
||||
}
|
||||
else
|
||||
reads += String.Format("\r\n\t\t\t\t\tcase \"{0}\":\r\n\t\t\t\t\t\t{3}.{0} = reader.Read<{1}>({2});\r\n\t\t\t\t\t\tbreak;", field.Name, fieldTypeName, es3TypeParam, instance);
|
||||
}
|
||||
return reads;
|
||||
}
|
||||
|
||||
private string GetOutputPath(Type type)
|
||||
{
|
||||
return Application.dataPath + "/Easy Save 3/Types/ES3UserType_"+type.Name+".cs";
|
||||
}
|
||||
|
||||
/* Gets the full Type name, replacing any syntax (such as '+') with a dot to make it a valid type name */
|
||||
private static string GetFullTypeName(Type type)
|
||||
{
|
||||
string typeName = type.ToString();
|
||||
|
||||
if(type.IsNested)
|
||||
typeName = typeName.Replace('+','.');
|
||||
|
||||
// If it's a generic type, replace syntax with angled brackets.
|
||||
int genericArgumentCount = type.GetGenericArguments().Length;
|
||||
if(genericArgumentCount > 0)
|
||||
{
|
||||
return string.Format("{0}<{1}>", type.ToString().Split('`')[0], string.Join(", ", type.GetGenericArguments().Select(x => GetFullTypeName(x)).ToArray()));
|
||||
}
|
||||
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/* Whether this type has an explicit ES3Type. For example, ES3ArrayType would return false, but ES3Vector3ArrayType would return true */
|
||||
private static bool HasExplicitES3Type(Type type)
|
||||
{
|
||||
var es3Type = ES3TypeMgr.GetES3Type(type);
|
||||
if(es3Type == null)
|
||||
return false;
|
||||
// If this ES3Type has a static Instance property, return true.
|
||||
if(es3Type.GetType().GetField("Instance", BindingFlags.Public | BindingFlags.Static) != null)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool HasExplicitES3Type(ES3Type es3Type)
|
||||
{
|
||||
if(es3Type == null)
|
||||
return false;
|
||||
// If this ES3Type has a static Instance property, return true.
|
||||
if(es3Type.GetType().GetField("Instance", BindingFlags.Public | BindingFlags.Static) != null)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public class TypeListItem
|
||||
{
|
||||
public string name;
|
||||
public string lowercaseName;
|
||||
public string namespaceName;
|
||||
public Type type;
|
||||
public bool showInList;
|
||||
public bool hasExplicitES3Type;
|
||||
|
||||
public TypeListItem(string name, string namespaceName, Type type, bool showInList, bool hasExplicitES3Type)
|
||||
{
|
||||
this.name = name;
|
||||
this.lowercaseName = name.ToLowerInvariant();
|
||||
this.namespaceName = namespaceName;
|
||||
this.type = type;
|
||||
this.showInList = showInList;
|
||||
this.hasExplicitES3Type = hasExplicitES3Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 600b987de172f4a82b182077ceb7fffa
|
||||
timeCreated: 1519132286
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 874 B |
|
@ -0,0 +1,124 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9d92f481545af4a45b06e8fe44778d93
|
||||
timeCreated: 1484046036
|
||||
licenseType: Store
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: tvOS
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Tizen
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Samsung TV
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 703 B |
|
@ -0,0 +1,124 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca44f6eb870d244cfb1c83054a69ffc3
|
||||
timeCreated: 1484046036
|
||||
licenseType: Store
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: tvOS
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Tizen
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Samsung TV
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1,104 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ae63f85ae558634d83caaf5a332d1ba
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: -1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 793 B |
|
@ -0,0 +1,124 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4697547d67ec24040b678d7b35835286
|
||||
timeCreated: 1495455081
|
||||
licenseType: Store
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 4
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 0
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
filterMode: -1
|
||||
aniso: 1
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: tvOS
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Tizen
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
- buildTarget: Samsung TV
|
||||
maxTextureSize: 2048
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0a6bee318130749539d0eec8a7b37ccd
|
||||
folderAsset: yes
|
||||
timeCreated: 1497259711
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5989e48214df74e2b9cced724ec2e5c8
|
||||
timeCreated: 1497259720
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 86ef77fdddf9947f290776206b1f23ab
|
||||
folderAsset: yes
|
||||
timeCreated: 1499764821
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3195251321eef445b65f7c8d345e743
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class ES3Serializable : Attribute{}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class ES3NonSerializable : Attribute { }
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e29c69181d1dff642b20c218819fe2e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a01ff460e5e0b4f58bd28b3520b7ff2c
|
||||
folderAsset: yes
|
||||
timeCreated: 1502446431
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ES3AutoSave : MonoBehaviour, ISerializationCallbackReceiver
|
||||
{
|
||||
public bool saveLayer = true;
|
||||
public bool saveTag = true;
|
||||
public bool saveName = true;
|
||||
public bool saveHideFlags = true;
|
||||
public bool saveActive = true;
|
||||
public bool saveChildren = false;
|
||||
|
||||
private bool isQuitting = false;
|
||||
|
||||
//[HideInInspector]
|
||||
public List<Component> componentsToSave = new List<Component>();
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Initialise saveLayer (etc) to false for all new Components.
|
||||
saveLayer = false;
|
||||
saveTag = false;
|
||||
saveName = false;
|
||||
saveHideFlags = false;
|
||||
saveActive = false;
|
||||
saveChildren = false;
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
if (ES3AutoSaveMgr.Current == null)
|
||||
ES3Internal.ES3Debug.LogWarning("<b>No GameObjects in this scene will be autosaved</b> because there is no Easy Save 3 Manager. To add a manager to this scene, exit playmode and go to Assets > Easy Save 3 > Add Manager to Scene.", this);
|
||||
else
|
||||
ES3AutoSaveMgr.AddAutoSave(this);
|
||||
}
|
||||
|
||||
public void OnApplicationQuit()
|
||||
{
|
||||
isQuitting = true;
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
// If this is being destroyed, but not because the application is quitting,
|
||||
// remove the AutoSave from the manager.
|
||||
if (!isQuitting)
|
||||
ES3AutoSaveMgr.RemoveAutoSave(this);
|
||||
}
|
||||
public void OnBeforeSerialize() { }
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
// Remove any null Components
|
||||
componentsToSave.RemoveAll(c => c == null || c.GetType() == typeof(Component));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9cfcc9ceea0bf419cb3bcaf548c2600d
|
||||
timeCreated: 1519132292
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,133 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class ES3AutoSaveMgr : MonoBehaviour
|
||||
{
|
||||
public static ES3AutoSaveMgr _current = null;
|
||||
public static ES3AutoSaveMgr Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_current == null /*|| _current.gameObject.scene != SceneManager.GetActiveScene()*/)
|
||||
{
|
||||
var scene = SceneManager.GetActiveScene();
|
||||
var roots = scene.GetRootGameObjects();
|
||||
|
||||
// First, look for Easy Save 3 Manager in the top-level.
|
||||
foreach (var root in roots)
|
||||
if (root.name == "Easy Save 3 Manager")
|
||||
return _current = root.GetComponent<ES3AutoSaveMgr>();
|
||||
|
||||
// If the user has moved or renamed the Easy Save 3 Manager, we need to perform a deep search.
|
||||
foreach (var root in roots)
|
||||
if ((_current = root.GetComponentInChildren<ES3AutoSaveMgr>()) != null)
|
||||
return _current;
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
|
||||
// Included for backwards compatibility.
|
||||
public static ES3AutoSaveMgr Instance
|
||||
{
|
||||
get { return Current; }
|
||||
}
|
||||
|
||||
public enum LoadEvent { None, Awake, Start }
|
||||
public enum SaveEvent { None, OnApplicationQuit, OnApplicationPause }
|
||||
|
||||
public string key = System.Guid.NewGuid().ToString();
|
||||
public SaveEvent saveEvent = SaveEvent.OnApplicationQuit;
|
||||
public LoadEvent loadEvent = LoadEvent.Awake;
|
||||
public ES3SerializableSettings settings = new ES3SerializableSettings("AutoSave.es3", ES3.Location.Cache);
|
||||
|
||||
public HashSet<ES3AutoSave> autoSaves = new HashSet<ES3AutoSave>();
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (autoSaves == null || autoSaves.Count == 0)
|
||||
return;
|
||||
|
||||
// If we're using caching and we've not already cached this file, cache it.
|
||||
if (settings.location == ES3.Location.Cache && !ES3.FileExists(settings))
|
||||
ES3.CacheFile(settings);
|
||||
|
||||
if (autoSaves == null || autoSaves.Count == 0)
|
||||
{
|
||||
ES3.DeleteKey(key, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
var gameObjects = new List<GameObject>();
|
||||
foreach (var autoSave in autoSaves)
|
||||
// If the ES3AutoSave component is disabled, don't save it.
|
||||
if (autoSave.enabled)
|
||||
gameObjects.Add(autoSave.gameObject);
|
||||
ES3.Save<GameObject[]>(key, gameObjects.ToArray(), settings);
|
||||
}
|
||||
|
||||
if(settings.location == ES3.Location.Cache && ES3.FileExists(settings))
|
||||
ES3.StoreCachedFile(settings);
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we're using caching and we've not already cached this file, cache it.
|
||||
if (settings.location == ES3.Location.Cache && !ES3.FileExists(settings))
|
||||
ES3.CacheFile(settings);
|
||||
}
|
||||
catch { }
|
||||
|
||||
ES3.Load<GameObject[]>(key, new GameObject[0], settings);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
if(loadEvent == LoadEvent.Start)
|
||||
Load();
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
autoSaves = new HashSet<ES3AutoSave>();
|
||||
|
||||
foreach (var go in this.gameObject.scene.GetRootGameObjects())
|
||||
autoSaves.UnionWith(go.GetComponentsInChildren<ES3AutoSave>(true));
|
||||
|
||||
_current = this;
|
||||
|
||||
if (loadEvent == LoadEvent.Awake)
|
||||
Load();
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
if(saveEvent == SaveEvent.OnApplicationQuit)
|
||||
Save();
|
||||
}
|
||||
|
||||
void OnApplicationPause(bool paused)
|
||||
{
|
||||
if( (saveEvent == SaveEvent.OnApplicationPause ||
|
||||
(Application.isMobilePlatform && saveEvent == SaveEvent.OnApplicationQuit)) && paused)
|
||||
Save();
|
||||
}
|
||||
|
||||
/* Register an ES3AutoSave with the ES3AutoSaveMgr, if there is one */
|
||||
public static void AddAutoSave(ES3AutoSave autoSave)
|
||||
{
|
||||
if(ES3AutoSaveMgr.Current != null)
|
||||
ES3AutoSaveMgr.Current.autoSaves.Add(autoSave);
|
||||
}
|
||||
|
||||
/* Remove an ES3AutoSave from the ES3AutoSaveMgr, for example if it's GameObject has been destroyed */
|
||||
public static void RemoveAutoSave(ES3AutoSave autoSave)
|
||||
{
|
||||
if(ES3AutoSaveMgr.Current != null)
|
||||
ES3AutoSaveMgr.Current.autoSaves.Remove(autoSave);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9107aee0ced90422da95f0b31680501f
|
||||
timeCreated: 1519132291
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c00267afddf624bb19ac24ce8076f9e4
|
||||
folderAsset: yes
|
||||
timeCreated: 1518175259
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,52 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
internal static class ES3Debug
|
||||
{
|
||||
private const string disableInfoMsg = "\n<i>To disable these messages from Easy Save, go to Window > Easy Save 3 > Settings, and uncheck 'Log Info'</i>";
|
||||
private const string disableWarningMsg = "\n<i>To disable warnings from Easy Save, go to Window > Easy Save 3 > Settings, and uncheck 'Log Warnings'</i>";
|
||||
private const string disableErrorMsg = "\n<i>To disable these error messages from Easy Save, go to Window > Easy Save 3 > Settings, and uncheck 'Log Errors'</i>";
|
||||
|
||||
private const char indentChar = '-';
|
||||
|
||||
public static void Log(string msg, Object context = null, int indent=0)
|
||||
{
|
||||
if (!ES3Settings.defaultSettingsScriptableObject.logDebugInfo)
|
||||
return;
|
||||
else if (context != null)
|
||||
Debug.LogFormat(context, Indent(indent) + msg + disableInfoMsg);
|
||||
else
|
||||
Debug.LogFormat(context, Indent(indent) + msg);
|
||||
}
|
||||
|
||||
public static void LogWarning(string msg, Object context=null, int indent = 0)
|
||||
{
|
||||
if (!ES3Settings.defaultSettingsScriptableObject.logWarnings)
|
||||
return;
|
||||
else if (context != null)
|
||||
Debug.LogWarningFormat(context, Indent(indent) + msg + disableWarningMsg);
|
||||
else
|
||||
Debug.LogWarningFormat(context, Indent(indent) + msg + disableWarningMsg);
|
||||
}
|
||||
|
||||
public static void LogError(string msg, Object context = null, int indent = 0)
|
||||
{
|
||||
if (!ES3Settings.defaultSettingsScriptableObject.logErrors)
|
||||
return;
|
||||
else if (context != null)
|
||||
Debug.LogErrorFormat(context, Indent(indent) + msg + disableErrorMsg);
|
||||
else
|
||||
Debug.LogErrorFormat(context, Indent(indent) + msg + disableErrorMsg);
|
||||
}
|
||||
|
||||
private static string Indent(int size)
|
||||
{
|
||||
if (size < 0)
|
||||
return "";
|
||||
return new string(indentChar, size);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9f97d288c55524622a117171a19d3225
|
||||
timeCreated: 1518175265
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca1cdcde6d39a44b39ee5f5b86ddfd73
|
||||
timeCreated: 1499764822
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,208 @@
|
|||
#if !DISABLE_ENCRYPTION
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
#if NETFX_CORE
|
||||
using Windows.Security.Cryptography;
|
||||
using Windows.Security.Cryptography.Core;
|
||||
using Windows.Storage.Streams;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
#endif
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
public static class ES3Hash
|
||||
{
|
||||
#if NETFX_CORE
|
||||
public static string SHA1Hash(string input)
|
||||
{
|
||||
return System.Text.Encoding.UTF8.GetString(UnityEngine.Windows.Crypto.ComputeSHA1Hash(System.Text.Encoding.UTF8.GetBytes(input)));
|
||||
}
|
||||
#else
|
||||
public static string SHA1Hash(string input)
|
||||
{
|
||||
using (SHA1Managed sha1 = new SHA1Managed())
|
||||
return System.Text.Encoding.UTF8.GetString(sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public abstract class EncryptionAlgorithm
|
||||
{
|
||||
public abstract byte[] Encrypt(byte[] bytes, string password, int bufferSize);
|
||||
public abstract byte[] Decrypt(byte[] bytes, string password, int bufferSize);
|
||||
public abstract void Encrypt(Stream input, Stream output, string password, int bufferSize);
|
||||
public abstract void Decrypt(Stream input, Stream output, string password, int bufferSize);
|
||||
|
||||
protected static void CopyStream(Stream input, Stream output, int bufferSize)
|
||||
{
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int read;
|
||||
while ((read = input.Read(buffer, 0, bufferSize)) > 0)
|
||||
output.Write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
public class AESEncryptionAlgorithm : EncryptionAlgorithm
|
||||
{
|
||||
private const int ivSize = 16;
|
||||
private const int keySize = 16;
|
||||
private const int pwIterations = 100;
|
||||
|
||||
public override byte[] Encrypt(byte[] bytes, string password, int bufferSize)
|
||||
{
|
||||
using (var input = new MemoryStream(bytes))
|
||||
{
|
||||
using (var output = new MemoryStream())
|
||||
{
|
||||
Encrypt(input, output, password, bufferSize);
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] Decrypt(byte[] bytes, string password, int bufferSize)
|
||||
{
|
||||
using (var input = new MemoryStream(bytes))
|
||||
{
|
||||
using (var output = new MemoryStream())
|
||||
{
|
||||
Decrypt(input, output, password, bufferSize);
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Encrypt(Stream input, Stream output, string password, int bufferSize)
|
||||
{
|
||||
input.Position = 0;
|
||||
|
||||
#if NETFX_CORE
|
||||
// Generate an IV and write it to the output.
|
||||
var iv = CryptographicBuffer.GenerateRandom(ivSize);
|
||||
output.Write(iv.ToArray(), 0, ivSize);
|
||||
|
||||
var pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
|
||||
var keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
|
||||
KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(iv, pwIterations);
|
||||
// Create a key based on original key and derivation parmaters
|
||||
CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
|
||||
IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, keySize);
|
||||
|
||||
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
|
||||
var key = provider.CreateSymmetricKey(keyMaterial);
|
||||
|
||||
// Get the input stream as an IBuffer.
|
||||
IBuffer msg;
|
||||
using(var ms = new MemoryStream())
|
||||
{
|
||||
input.CopyTo(ms);
|
||||
msg = ms.ToArray().AsBuffer();
|
||||
}
|
||||
|
||||
var buffEncrypt = CryptographicEngine.Encrypt(key, msg, iv);
|
||||
|
||||
|
||||
output.Write(buffEncrypt.ToArray(), 0, (int)buffEncrypt.Length);
|
||||
output.Dispose();
|
||||
#else
|
||||
using (var alg = Aes.Create())
|
||||
{
|
||||
alg.Mode = CipherMode.CBC;
|
||||
alg.Padding = PaddingMode.PKCS7;
|
||||
alg.GenerateIV();
|
||||
var key = new Rfc2898DeriveBytes(password, alg.IV, pwIterations);
|
||||
alg.Key = key.GetBytes(keySize);
|
||||
// Write the IV to the output stream.
|
||||
output.Write(alg.IV, 0, ivSize);
|
||||
using(var encryptor = alg.CreateEncryptor())
|
||||
using(var cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
|
||||
CopyStream(input, cs, bufferSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Decrypt(Stream input, Stream output, string password, int bufferSize)
|
||||
{
|
||||
#if NETFX_CORE
|
||||
var thisIV = new byte[ivSize];
|
||||
input.Read(thisIV, 0, ivSize);
|
||||
var iv = thisIV.AsBuffer();
|
||||
|
||||
var pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
|
||||
|
||||
var keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
|
||||
KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(iv, pwIterations);
|
||||
// Create a key based on original key and derivation parameters.
|
||||
CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
|
||||
IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, keySize);
|
||||
|
||||
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
|
||||
var key = provider.CreateSymmetricKey(keyMaterial);
|
||||
|
||||
// Get the input stream as an IBuffer.
|
||||
IBuffer msg;
|
||||
using(var ms = new MemoryStream())
|
||||
{
|
||||
input.CopyTo(ms);
|
||||
msg = ms.ToArray().AsBuffer();
|
||||
}
|
||||
|
||||
var buffDecrypt = CryptographicEngine.Decrypt(key, msg, iv);
|
||||
|
||||
output.Write(buffDecrypt.ToArray(), 0, (int)buffDecrypt.Length);
|
||||
#else
|
||||
using (var alg = Aes.Create())
|
||||
{
|
||||
var thisIV = new byte[ivSize];
|
||||
input.Read(thisIV, 0, ivSize);
|
||||
alg.IV = thisIV;
|
||||
|
||||
var key = new Rfc2898DeriveBytes(password, alg.IV, pwIterations);
|
||||
alg.Key = key.GetBytes(keySize);
|
||||
|
||||
using(var decryptor = alg.CreateDecryptor())
|
||||
using(var cryptoStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
|
||||
CopyStream(cryptoStream, output, bufferSize);
|
||||
|
||||
}
|
||||
#endif
|
||||
output.Position = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class UnbufferedCryptoStream : MemoryStream
|
||||
{
|
||||
private readonly Stream stream;
|
||||
private readonly bool isReadStream;
|
||||
private string password;
|
||||
private int bufferSize;
|
||||
private EncryptionAlgorithm alg;
|
||||
private bool disposed = false;
|
||||
|
||||
public UnbufferedCryptoStream(Stream stream, bool isReadStream, string password, int bufferSize, EncryptionAlgorithm alg) : base()
|
||||
{
|
||||
this.stream = stream;
|
||||
this.isReadStream = isReadStream;
|
||||
this.password = password;
|
||||
this.bufferSize = bufferSize;
|
||||
this.alg = alg;
|
||||
|
||||
|
||||
if (isReadStream)
|
||||
alg.Decrypt(stream, this, password, bufferSize);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
disposed = true;
|
||||
|
||||
if (!isReadStream)
|
||||
alg.Encrypt(this, stream, password, bufferSize);
|
||||
stream.Dispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d2b3b6335276042569261b3e6bed694e
|
||||
timeCreated: 1519132297
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,497 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System;
|
||||
using ES3Types;
|
||||
using UnityEngine;
|
||||
using ES3Internal;
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>Represents a cached file which can be saved to and loaded from, and commited to storage when necessary.</summary>
|
||||
public class ES3File
|
||||
{
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static Dictionary<string, ES3File> cachedFiles = new Dictionary<string, ES3File>();
|
||||
|
||||
public ES3Settings settings;
|
||||
private Dictionary<string, ES3Data> cache = new Dictionary<string, ES3Data>();
|
||||
private bool syncWithFile = false;
|
||||
private DateTime timestamp = DateTime.UtcNow;
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the default file into the ES3File if there is data to load.</summary>
|
||||
public ES3File() : this(new ES3Settings(), true) { }
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the specified file into the ES3File if there is data to load.</summary>
|
||||
/// <param name="filepath">The relative or absolute path of the file in storage our ES3File is associated with.</param>
|
||||
public ES3File(string filePath) : this(new ES3Settings(filePath), true) { }
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the specified file into the ES3File if there is data to load.</summary>
|
||||
/// <param name="filepath">The relative or absolute path of the file in storage our ES3File is associated with.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public ES3File(string filePath, ES3Settings settings) : this(new ES3Settings(filePath, settings), true) { }
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the specified file into the ES3File if there is data to load.</summary>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public ES3File(ES3Settings settings) : this(settings, true) { }
|
||||
|
||||
/// <summary>Creates a new ES3File and only loads the default file into it if syncWithFile is set to true.</summary>
|
||||
/// <param name="syncWithFile">Whether we should sync this ES3File with the one in storage immediately after creating it.</param>
|
||||
public ES3File(bool syncWithFile) : this(new ES3Settings(), syncWithFile) { }
|
||||
/// <summary>Creates a new ES3File and only loads the specified file into it if syncWithFile is set to true.</summary>
|
||||
/// <param name="filepath">The relative or absolute path of the file in storage our ES3File is associated with.</param>
|
||||
/// <param name="syncWithFile">Whether we should sync this ES3File with the one in storage immediately after creating it.</param>
|
||||
public ES3File(string filePath, bool syncWithFile) : this(new ES3Settings(filePath), syncWithFile) { }
|
||||
/// <summary>Creates a new ES3File and only loads the specified file into it if syncWithFile is set to true.</summary>
|
||||
/// <param name="filepath">The relative or absolute path of the file in storage our ES3File is associated with.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
/// <param name="syncWithFile">Whether we should sync this ES3File with the one in storage immediately after creating it.</param>
|
||||
public ES3File(string filePath, ES3Settings settings, bool syncWithFile) : this(new ES3Settings(filePath, settings), syncWithFile) { }
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the specified file into the ES3File if there is data to load.</summary>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
/// <param name="syncWithFile">Whether we should sync this ES3File with the one in storage immediately after creating it.</param>
|
||||
public ES3File(ES3Settings settings, bool syncWithFile)
|
||||
{
|
||||
this.settings = settings;
|
||||
this.syncWithFile = syncWithFile;
|
||||
if (syncWithFile)
|
||||
{
|
||||
// Type checking must be enabled when syncing.
|
||||
var settingsWithTypeChecking = (ES3Settings)settings.Clone();
|
||||
settingsWithTypeChecking.typeChecking = true;
|
||||
|
||||
using (var reader = ES3Reader.Create(settingsWithTypeChecking))
|
||||
{
|
||||
if (reader == null)
|
||||
return;
|
||||
foreach (KeyValuePair<string, ES3Data> kvp in reader.RawEnumerator)
|
||||
cache[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates a new ES3File and loads the bytes into the ES3File. Note the bytes must represent that of a file.</summary>
|
||||
/// <param name="bytes">The bytes representing our file.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
/// <param name="syncWithFile">Whether we should sync this ES3File with the one in storage immediately after creating it.</param>
|
||||
public ES3File(byte[] bytes, ES3Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
this.settings = new ES3Settings();
|
||||
else
|
||||
this.settings = settings;
|
||||
SaveRaw(bytes, settings);
|
||||
}
|
||||
|
||||
/// <summary>Synchronises this ES3File with a file in storage.</summary>
|
||||
public void Sync()
|
||||
{
|
||||
Sync(this.settings);
|
||||
}
|
||||
|
||||
/// <summary>Synchronises this ES3File with a file in storage.</summary>
|
||||
/// <param name="filepath">The relative or absolute path of the file in storage we want to synchronise with.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public void Sync(string filePath, ES3Settings settings = null)
|
||||
{
|
||||
Sync(new ES3Settings(filePath, settings));
|
||||
}
|
||||
|
||||
/// <summary>Synchronises this ES3File with a file in storage.</summary>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public void Sync(ES3Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = new ES3Settings();
|
||||
|
||||
ES3.DeleteFile(settings);
|
||||
|
||||
if (cache.Count == 0)
|
||||
return;
|
||||
|
||||
using (var baseWriter = ES3Writer.Create(settings, true, !syncWithFile, false))
|
||||
{
|
||||
foreach (var kvp in cache)
|
||||
{
|
||||
// If we change the name of a type, the type may be null.
|
||||
// In this case, use System.Object as the type.
|
||||
Type type;
|
||||
if (kvp.Value.type == null)
|
||||
type = typeof(System.Object);
|
||||
else
|
||||
type = kvp.Value.type.type;
|
||||
baseWriter.Write(kvp.Key, type, kvp.Value.bytes);
|
||||
}
|
||||
baseWriter.Save(!syncWithFile);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Removes the data stored in this ES3File. The ES3File will be empty after calling this method.</summary>
|
||||
public void Clear()
|
||||
{
|
||||
cache.Clear();
|
||||
}
|
||||
|
||||
/// <summary>Returns an array of all of the key names in this ES3File.</summary>
|
||||
public string[] GetKeys()
|
||||
{
|
||||
var keyCollection = cache.Keys;
|
||||
var keys = new string[keyCollection.Count];
|
||||
keyCollection.CopyTo(keys, 0);
|
||||
return keys;
|
||||
}
|
||||
|
||||
#region Save Methods
|
||||
|
||||
/// <summary>Saves a value to a key in this ES3File.</summary>
|
||||
/// <param name="key">The key we want to use to identify our value in the file.</param>
|
||||
/// <param name="value">The value we want to save.</param>
|
||||
public void Save<T>(string key, T value)
|
||||
{
|
||||
var unencryptedSettings = (ES3Settings)settings.Clone();
|
||||
unencryptedSettings.encryptionType = ES3.EncryptionType.None;
|
||||
unencryptedSettings.compressionType = ES3.CompressionType.None;
|
||||
|
||||
// If T is object, use the value to get it's type. Otherwise, use T so that it works with inheritence.
|
||||
var type = typeof(T) != typeof(object) ? typeof(T) : (value == null ? typeof(T) : value.GetType());
|
||||
cache[key] = new ES3Data(ES3TypeMgr.GetOrCreateES3Type(type), ES3.Serialize(value, unencryptedSettings));
|
||||
}
|
||||
|
||||
/// <summary>Merges the data specified by the bytes parameter into this ES3File.</summary>
|
||||
/// <param name="bytes">The bytes we want to merge with this ES3File.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public void SaveRaw(byte[] bytes, ES3Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = new ES3Settings();
|
||||
|
||||
// Type checking must be enabled when syncing.
|
||||
var settingsWithTypeChecking = (ES3Settings)settings.Clone();
|
||||
settingsWithTypeChecking.typeChecking = true;
|
||||
|
||||
using (var reader = ES3Reader.Create(bytes, settingsWithTypeChecking))
|
||||
{
|
||||
if (reader == null)
|
||||
return;
|
||||
foreach (KeyValuePair<string, ES3Data> kvp in reader.RawEnumerator)
|
||||
cache[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Merges the data specified by the bytes parameter into this ES3File.</summary>
|
||||
/// <param name="bytes">The bytes we want to merge with this ES3File.</param>
|
||||
/// <param name="settings">The settings we want to use to override the default settings.</param>
|
||||
public void AppendRaw(byte[] bytes, ES3Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = new ES3Settings();
|
||||
// AppendRaw just does the same thing as SaveRaw in ES3File.
|
||||
SaveRaw(bytes, settings);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load Methods
|
||||
|
||||
/* Standard load methods */
|
||||
|
||||
/// <summary>Loads the value from this ES3File with the given key.</summary>
|
||||
/// <param name="key">The key which identifies the value we want to load.</param>
|
||||
public object Load(string key)
|
||||
{
|
||||
return Load<object>(key);
|
||||
}
|
||||
|
||||
/// <summary>Loads the value from this ES3File with the given key.</summary>
|
||||
/// <param name="key">The key which identifies the value we want to load.</param>
|
||||
/// <param name="defaultValue">The value we want to return if the key does not exist in this ES3File.</param>
|
||||
public object Load(string key, object defaultValue)
|
||||
{
|
||||
return Load<object>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <summary>Loads the value from this ES3File with the given key.</summary>
|
||||
/// <param name="key">The key which identifies the value we want to load.</param>
|
||||
public T Load<T>(string key)
|
||||
{
|
||||
ES3Data es3Data;
|
||||
|
||||
if (!cache.TryGetValue(key, out es3Data))
|
||||
throw new KeyNotFoundException("Key \"" + key + "\" was not found in this ES3File. Use Load<T>(key, defaultValue) if you want to return a default value if the key does not exist.");
|
||||
|
||||
var unencryptedSettings = (ES3Settings)this.settings.Clone();
|
||||
unencryptedSettings.encryptionType = ES3.EncryptionType.None;
|
||||
unencryptedSettings.compressionType = ES3.CompressionType.None;
|
||||
|
||||
if (typeof(T) == typeof(object))
|
||||
return (T)ES3.Deserialize(es3Data.type, es3Data.bytes, unencryptedSettings);
|
||||
return ES3.Deserialize<T>(es3Data.bytes, unencryptedSettings);
|
||||
}
|
||||
|
||||
/// <summary>Loads the value from this ES3File with the given key.</summary>
|
||||
/// <param name="key">The key which identifies the value we want to load.</param>
|
||||
/// <param name="defaultValue">The value we want to return if the key does not exist in this ES3File.</param>
|
||||
public T Load<T>(string key, T defaultValue)
|
||||
{
|
||||
ES3Data es3Data;
|
||||
|
||||
if (!cache.TryGetValue(key, out es3Data))
|
||||
return defaultValue;
|
||||
var unencryptedSettings = (ES3Settings)this.settings.Clone();
|
||||
unencryptedSettings.encryptionType = ES3.EncryptionType.None;
|
||||
unencryptedSettings.compressionType = ES3.CompressionType.None;
|
||||
|
||||
if (typeof(T) == typeof(object))
|
||||
return (T)ES3.Deserialize(es3Data.type, es3Data.bytes, unencryptedSettings);
|
||||
return ES3.Deserialize<T>(es3Data.bytes, unencryptedSettings);
|
||||
}
|
||||
|
||||
/// <summary>Loads the value from this ES3File with the given key into an existing object.</summary>
|
||||
/// <param name="key">The key which identifies the value we want to load.</param>
|
||||
/// <param name="obj">The object we want to load the value into.</param>
|
||||
public void LoadInto<T>(string key, T obj) where T : class
|
||||
{
|
||||
ES3Data es3Data;
|
||||
|
||||
if (!cache.TryGetValue(key, out es3Data))
|
||||
throw new KeyNotFoundException("Key \"" + key + "\" was not found in this ES3File. Use Load<T>(key, defaultValue) if you want to return a default value if the key does not exist.");
|
||||
|
||||
var unencryptedSettings = (ES3Settings)this.settings.Clone();
|
||||
unencryptedSettings.encryptionType = ES3.EncryptionType.None;
|
||||
unencryptedSettings.compressionType = ES3.CompressionType.None;
|
||||
|
||||
if (typeof(T) == typeof(object))
|
||||
ES3.DeserializeInto(es3Data.type, es3Data.bytes, obj, unencryptedSettings);
|
||||
else
|
||||
ES3.DeserializeInto(es3Data.bytes, obj, unencryptedSettings);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load Raw Methods
|
||||
|
||||
/// <summary>Loads the ES3File as a raw, unencrypted, uncompressed byte array.</summary>
|
||||
public byte[] LoadRawBytes()
|
||||
{
|
||||
var unencryptedSettings = (ES3Settings)settings.Clone();
|
||||
unencryptedSettings.encryptionType = ES3.EncryptionType.None;
|
||||
unencryptedSettings.compressionType = ES3.CompressionType.None;
|
||||
return GetBytes(unencryptedSettings);
|
||||
}
|
||||
|
||||
/// <summary>Loads the ES3File as a raw, unencrypted, uncompressed string, using the encoding defined in the ES3File's settings variable.</summary>
|
||||
public string LoadRawString()
|
||||
{
|
||||
if (cache.Count == 0)
|
||||
return "";
|
||||
return settings.encoding.GetString(LoadRawBytes());
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as LoadRawString, except it will return an encrypted/compressed file if these are enabled.
|
||||
*/
|
||||
internal byte[] GetBytes(ES3Settings settings = null)
|
||||
{
|
||||
if (cache.Count == 0)
|
||||
return new byte[0];
|
||||
|
||||
if (settings == null)
|
||||
settings = this.settings;
|
||||
|
||||
using (var ms = new System.IO.MemoryStream())
|
||||
{
|
||||
var memorySettings = (ES3Settings)settings.Clone();
|
||||
memorySettings.location = ES3.Location.InternalMS;
|
||||
// Ensure we return unencrypted bytes.
|
||||
memorySettings.encryptionType = ES3.EncryptionType.None;
|
||||
memorySettings.compressionType = ES3.CompressionType.None;
|
||||
|
||||
using (var baseWriter = ES3Writer.Create(ES3Stream.CreateStream(ms, memorySettings, ES3FileMode.Write), memorySettings, true, false))
|
||||
{
|
||||
foreach (var kvp in cache)
|
||||
baseWriter.Write(kvp.Key, kvp.Value.type.type, kvp.Value.bytes);
|
||||
baseWriter.Save(false);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Other ES3 Methods
|
||||
|
||||
/// <summary>Deletes a key from this ES3File.</summary>
|
||||
/// <param name="key">The key we want to delete.</param>
|
||||
public void DeleteKey(string key)
|
||||
{
|
||||
cache.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>Checks whether a key exists in this ES3File.</summary>
|
||||
/// <param name="key">The key we want to check the existence of.</param>
|
||||
/// <returns>True if the key exists, otherwise False.</returns>
|
||||
public bool KeyExists(string key)
|
||||
{
|
||||
return cache.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>Gets the size of the cached data in bytes.</summary>
|
||||
public int Size()
|
||||
{
|
||||
int size = 0;
|
||||
foreach (var kvp in cache)
|
||||
size += kvp.Value.bytes.Length;
|
||||
return size;
|
||||
}
|
||||
|
||||
public Type GetKeyType(string key)
|
||||
{
|
||||
ES3Data es3data;
|
||||
if (!cache.TryGetValue(key, out es3data))
|
||||
throw new KeyNotFoundException("Key \"" + key + "\" was not found in this ES3File. Use Load<T>(key, defaultValue) if you want to return a default value if the key does not exist.");
|
||||
|
||||
return es3data.type.type;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static ES3File GetOrCreateCachedFile(ES3Settings settings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (!cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
{
|
||||
cachedFile = new ES3File(settings, false);
|
||||
cachedFiles.Add(settings.path, cachedFile);
|
||||
}
|
||||
// Settings might refer to the same file, but might have changed.
|
||||
// To account for this, we update the settings of the ES3File each time we access it.
|
||||
cachedFile.settings = settings;
|
||||
return cachedFile;
|
||||
}
|
||||
|
||||
internal static void CacheFile(ES3Settings settings)
|
||||
{
|
||||
// If we're still using cached settings, default to file.
|
||||
if (settings.location == ES3.Location.Cache)
|
||||
{
|
||||
settings = (ES3Settings)settings.Clone();
|
||||
settings.location = ES3.Location.File;
|
||||
}
|
||||
|
||||
if (!ES3.FileExists(settings))
|
||||
return;
|
||||
|
||||
|
||||
// Disable compression and encryption when loading the raw bytes, and the ES3File constructor will expect encrypted/compressed bytes.
|
||||
var loadSettings = (ES3Settings)settings.Clone();
|
||||
loadSettings.compressionType = ES3.CompressionType.None;
|
||||
loadSettings.encryptionType = ES3.EncryptionType.None;
|
||||
|
||||
cachedFiles[settings.path] = new ES3File(ES3.LoadRawBytes(loadSettings), settings);
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static void Store(ES3Settings settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = new ES3Settings(ES3.Location.File);
|
||||
// If we're still using cached settings, default to file.
|
||||
else if (settings.location == ES3.Location.Cache)
|
||||
{
|
||||
settings = (ES3Settings)settings.Clone();
|
||||
settings.location = ES3.Location.File;
|
||||
}
|
||||
|
||||
ES3File cachedFile;
|
||||
if (!cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
throw new FileNotFoundException("The file '" + settings.path + "' could not be stored because it could not be found in the cache.");
|
||||
cachedFile.Sync(settings);
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static void RemoveCachedFile(ES3Settings settings)
|
||||
{
|
||||
cachedFiles.Remove(settings.path);
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static void CopyCachedFile(ES3Settings oldSettings, ES3Settings newSettings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (!cachedFiles.TryGetValue(oldSettings.path, out cachedFile))
|
||||
throw new FileNotFoundException("The file '" + oldSettings.path + "' could not be copied because it could not be found in the cache.");
|
||||
if (cachedFiles.ContainsKey(newSettings.path))
|
||||
throw new InvalidOperationException("Cannot copy file '" + oldSettings.path + "' to '" + newSettings.path + "' because '" + newSettings.path + "' already exists");
|
||||
|
||||
cachedFiles.Add(newSettings.path, (ES3File)cachedFile.MemberwiseClone());
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static void DeleteKey(string key, ES3Settings settings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
cachedFile.DeleteKey(key);
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static bool KeyExists(string key, ES3Settings settings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
return cachedFile.KeyExists(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static bool FileExists(ES3Settings settings)
|
||||
{
|
||||
return cachedFiles.ContainsKey(settings.path);
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static string[] GetKeys(ES3Settings settings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (!cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
throw new FileNotFoundException("Could not get keys from the file '" + settings.path + "' because it could not be found in the cache.");
|
||||
return cachedFile.cache.Keys.ToArray();
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal static string[] GetFiles()
|
||||
{
|
||||
return cachedFiles.Keys.ToArray();
|
||||
}
|
||||
|
||||
internal static DateTime GetTimestamp(ES3Settings settings)
|
||||
{
|
||||
ES3File cachedFile;
|
||||
if (!cachedFiles.TryGetValue(settings.path, out cachedFile))
|
||||
throw new FileNotFoundException("Could not get timestamp from the file '" + settings.path + "' because it could not be found in the cache.");
|
||||
return cachedFile.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
public struct ES3Data
|
||||
{
|
||||
public ES3Type type;
|
||||
public byte[] bytes;
|
||||
|
||||
public ES3Data(Type type, byte[] bytes)
|
||||
{
|
||||
this.type = type == null ? null : ES3TypeMgr.GetOrCreateES3Type(type);
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public ES3Data(ES3Type type, byte[] bytes)
|
||||
{
|
||||
this.type = type;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2cd9723dc51904030be3c30362442d47
|
||||
timeCreated: 1499764821
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,167 @@
|
|||
using System.IO;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
public static class ES3IO
|
||||
{
|
||||
#if UNITY_SWITCH
|
||||
internal static readonly string persistentDataPath = "";
|
||||
#else
|
||||
internal static readonly string persistentDataPath = Application.persistentDataPath;
|
||||
#endif
|
||||
|
||||
internal const string backupFileSuffix = ".bac";
|
||||
internal const string temporaryFileSuffix = ".tmp";
|
||||
|
||||
public enum ES3FileMode { Read, Write, Append }
|
||||
|
||||
public static DateTime GetTimestamp(string filePath)
|
||||
{
|
||||
if (!FileExists(filePath))
|
||||
return new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
|
||||
return File.GetLastWriteTime(filePath).ToUniversalTime();
|
||||
}
|
||||
|
||||
public static string GetExtension(string path)
|
||||
{
|
||||
return Path.GetExtension(path);
|
||||
}
|
||||
|
||||
public static void DeleteFile(string filePath)
|
||||
{
|
||||
if (FileExists(filePath))
|
||||
File.Delete(filePath);
|
||||
}
|
||||
|
||||
public static bool FileExists(string filePath) { return File.Exists(filePath); }
|
||||
public static void MoveFile(string sourcePath, string destPath) { File.Move(sourcePath, destPath); }
|
||||
public static void CopyFile(string sourcePath, string destPath) { File.Copy(sourcePath, destPath); }
|
||||
|
||||
public static void MoveDirectory(string sourcePath, string destPath) { Directory.Move(sourcePath, destPath); }
|
||||
public static void CreateDirectory(string directoryPath) { Directory.CreateDirectory(directoryPath); }
|
||||
public static bool DirectoryExists(string directoryPath) { return Directory.Exists(directoryPath); }
|
||||
|
||||
/*
|
||||
* Given a path, it returns the directory that path points to.
|
||||
* eg. "C:/myFolder/thisFolder/myFile.txt" will return "C:/myFolder/thisFolder".
|
||||
*/
|
||||
public static string GetDirectoryPath(string path, char seperator = '/')
|
||||
{
|
||||
//return Path.GetDirectoryName(path);
|
||||
// Path.GetDirectoryName turns forward slashes to backslashes in some cases on Windows, which is why
|
||||
// Substring is used instead.
|
||||
char slashChar = UsesForwardSlash(path) ? '/' : '\\';
|
||||
|
||||
int slash = path.LastIndexOf(slashChar);
|
||||
// Ignore trailing slash if necessary.
|
||||
if (slash == (path.Length - 1))
|
||||
slash = path.Substring(0, slash).LastIndexOf(slashChar);
|
||||
if (slash == -1)
|
||||
ES3Debug.LogError("Path provided is not a directory path as it contains no slashes.");
|
||||
return path.Substring(0, slash);
|
||||
}
|
||||
|
||||
public static bool UsesForwardSlash(string path)
|
||||
{
|
||||
if (path.Contains("/"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Takes a directory path and a file or directory name and combines them into a single path.
|
||||
public static string CombinePathAndFilename(string directoryPath, string fileOrDirectoryName)
|
||||
{
|
||||
if (directoryPath[directoryPath.Length - 1] != '/' && directoryPath[directoryPath.Length - 1] != '\\')
|
||||
directoryPath += '/';
|
||||
return directoryPath + fileOrDirectoryName;
|
||||
}
|
||||
|
||||
public static string[] GetDirectories(string path, bool getFullPaths = true)
|
||||
{
|
||||
var paths = Directory.GetDirectories(path);
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
{
|
||||
if (!getFullPaths)
|
||||
paths[i] = Path.GetFileName(paths[i]);
|
||||
// GetDirectories sometimes returns backslashes, so we need to convert them to
|
||||
// forward slashes.
|
||||
paths[i].Replace("\\", "/");
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public static void DeleteDirectory(string directoryPath)
|
||||
{
|
||||
if (DirectoryExists(directoryPath))
|
||||
Directory.Delete(directoryPath, true);
|
||||
}
|
||||
|
||||
public static string[] GetFiles(string path, bool getFullPaths = true)
|
||||
{
|
||||
var paths = Directory.GetFiles(path);
|
||||
if (!getFullPaths)
|
||||
{
|
||||
for (int i = 0; i < paths.Length; i++)
|
||||
paths[i] = Path.GetFileName(paths[i]);
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public static byte[] ReadAllBytes(string path)
|
||||
{
|
||||
return File.ReadAllBytes(path);
|
||||
}
|
||||
|
||||
public static void WriteAllBytes(string path, byte[] bytes)
|
||||
{
|
||||
File.WriteAllBytes(path, bytes);
|
||||
}
|
||||
|
||||
public static void CommitBackup(ES3Settings settings)
|
||||
{
|
||||
ES3Debug.Log("Committing backup for " + settings.path + " to storage location " + settings.location);
|
||||
|
||||
var temporaryFilePath = settings.FullPath + temporaryFileSuffix;
|
||||
|
||||
if (settings.location == ES3.Location.File)
|
||||
{
|
||||
var oldFileBackup = settings.FullPath + temporaryFileSuffix + ".bak";
|
||||
|
||||
// If there's existing save data to overwrite ...
|
||||
if (FileExists(settings.FullPath))
|
||||
{
|
||||
// Delete any old backups.
|
||||
DeleteFile(oldFileBackup);
|
||||
// Rename the old file so we can restore it if it fails.
|
||||
MoveFile(settings.FullPath, oldFileBackup);
|
||||
|
||||
try
|
||||
{
|
||||
// Now rename the temporary file to the name of the save file.
|
||||
MoveFile(temporaryFilePath, settings.FullPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// If any exceptions occur, restore the original save file.
|
||||
try { DeleteFile(settings.FullPath); } catch { }
|
||||
MoveFile(oldFileBackup, settings.FullPath);
|
||||
throw e;
|
||||
}
|
||||
|
||||
DeleteFile(oldFileBackup);
|
||||
}
|
||||
// Else just rename the temporary file to the main file.
|
||||
else
|
||||
MoveFile(temporaryFilePath, settings.FullPath);
|
||||
}
|
||||
else if (settings.location == ES3.Location.PlayerPrefs)
|
||||
{
|
||||
PlayerPrefs.SetString(settings.FullPath, PlayerPrefs.GetString(temporaryFilePath));
|
||||
PlayerPrefs.DeleteKey(temporaryFilePath);
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0e3e89d69f37e4fa9b4d60467722ac73
|
||||
timeCreated: 1499764821
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,19 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/*
|
||||
* Displays an info message in the inspector.
|
||||
* Only available in the Editor.
|
||||
*/
|
||||
public class ES3InspectorInfo : MonoBehaviour
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
public string message = "";
|
||||
|
||||
public void SetMessage(string message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8714d999c5ae749538494c1347e5a3ca
|
||||
timeCreated: 1519132290
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,212 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using ES3Internal;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
public class ES3Prefab : MonoBehaviour
|
||||
{
|
||||
public long prefabId = GetNewRefID();
|
||||
/*
|
||||
* We need to store references to all dependencies of the prefab because only supported scripts will be serialised.
|
||||
* This means that although supported scripts have their dependencies added to the reference manager when we load the prefab,
|
||||
* there will not be any dependencies in the reference manager for scripts which are not supported. So it will not be possible to save any reference to these.
|
||||
*/
|
||||
public ES3RefIdDictionary localRefs = new ES3RefIdDictionary();
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
// Add the references to the reference list when this prefab is instantiated.
|
||||
var mgr = ES3ReferenceMgrBase.Current;
|
||||
|
||||
if (mgr == null)
|
||||
return;
|
||||
|
||||
foreach (var kvp in localRefs)
|
||||
if (kvp.Key != null)
|
||||
mgr.Add(kvp.Key);
|
||||
}
|
||||
|
||||
public long Get(UnityEngine.Object obj)
|
||||
{
|
||||
long id;
|
||||
if (localRefs.TryGetValue(obj, out id))
|
||||
return id;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long Add(UnityEngine.Object obj)
|
||||
{
|
||||
long id;
|
||||
if (localRefs.TryGetValue(obj, out id))
|
||||
return id;
|
||||
|
||||
if (!ES3ReferenceMgr.CanBeSaved(obj))
|
||||
return -1;
|
||||
id = GetNewRefID();
|
||||
localRefs.Add(obj, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetReferences()
|
||||
{
|
||||
var localToGlobal = new Dictionary<string, string>();
|
||||
|
||||
var refMgr = ES3ReferenceMgr.Current;
|
||||
|
||||
if (refMgr == null)
|
||||
return localToGlobal;
|
||||
|
||||
foreach (var kvp in localRefs)
|
||||
{
|
||||
long id = refMgr.Add(kvp.Key);
|
||||
localToGlobal.Add(kvp.Value.ToString(), id.ToString());
|
||||
}
|
||||
return localToGlobal;
|
||||
}
|
||||
|
||||
public void ApplyReferences(Dictionary<long, long> localToGlobal)
|
||||
{
|
||||
if (ES3ReferenceMgrBase.Current == null)
|
||||
return;
|
||||
|
||||
foreach (var localRef in localRefs)
|
||||
{
|
||||
long globalId;
|
||||
if (localToGlobal.TryGetValue(localRef.Value, out globalId))
|
||||
ES3ReferenceMgrBase.Current.Add(localRef.Key, globalId);
|
||||
}
|
||||
}
|
||||
|
||||
public static long GetNewRefID()
|
||||
{
|
||||
return ES3ReferenceMgrBase.GetNewRefID();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
public void GeneratePrefabReferences()
|
||||
{
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
if (this.gameObject.scene.name != null || UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null)
|
||||
#else
|
||||
if (this.gameObject.scene.name != null)
|
||||
#endif
|
||||
return;
|
||||
|
||||
// Create a new reference list so that any objects which are no longer dependencies are removed.
|
||||
var tempLocalRefs = new ES3RefIdDictionary();
|
||||
|
||||
// Get dependencies of children also.
|
||||
var transforms = GetComponentsInChildren<Transform>();
|
||||
var gos = new GameObject[transforms.Length];
|
||||
for (int i = 0; i < transforms.Length; i++)
|
||||
gos[i] = transforms[i].gameObject;
|
||||
|
||||
// Add the GameObject's dependencies to the reference list.
|
||||
foreach (var obj in ES3ReferenceMgr.CollectDependencies(gos))
|
||||
{
|
||||
var dependency = (UnityEngine.Object)obj;
|
||||
if (obj == null || !ES3ReferenceMgr.CanBeSaved(dependency))
|
||||
continue;
|
||||
|
||||
var id = Get(dependency);
|
||||
// If we're adding a new reference, do an Undo.RecordObject to ensure it persists.
|
||||
if (id == -1)
|
||||
{
|
||||
Undo.RecordObject(this, "Update Easy Save 3 Prefab");
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
tempLocalRefs.Add(dependency, id == -1 ? GetNewRefID() : id);
|
||||
}
|
||||
|
||||
localRefs = tempLocalRefs;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a blank ES3Type for ES3Prefab as it does not require serialising/deserialising when stored as a Component.
|
||||
*/
|
||||
namespace ES3Types
|
||||
{
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public class ES3Type_ES3Prefab : ES3Type
|
||||
{
|
||||
public static ES3Type Instance = null;
|
||||
|
||||
public ES3Type_ES3Prefab() : base(typeof(ES3Prefab)) { Instance = this; }
|
||||
|
||||
public override void Write(object obj, ES3Writer writer)
|
||||
{
|
||||
}
|
||||
|
||||
public override object Read<T>(ES3Reader reader)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Use this ES3Type to serialise the .
|
||||
*/
|
||||
public class ES3Type_ES3PrefabInternal : ES3Type
|
||||
{
|
||||
public static ES3Type Instance = new ES3Type_ES3PrefabInternal();
|
||||
|
||||
public ES3Type_ES3PrefabInternal() : base(typeof(ES3Type_ES3PrefabInternal)) { Instance = this; }
|
||||
|
||||
public override void Write(object obj, ES3Writer writer)
|
||||
{
|
||||
ES3Prefab es3Prefab = (ES3Prefab)obj;
|
||||
|
||||
writer.WriteProperty("prefabId", es3Prefab.prefabId.ToString(), ES3Type_string.Instance);
|
||||
writer.WriteProperty("refs", es3Prefab.GetReferences());
|
||||
}
|
||||
|
||||
public override object Read<T>(ES3Reader reader)
|
||||
{
|
||||
var prefabId = reader.ReadRefProperty();
|
||||
|
||||
if (ES3ReferenceMgrBase.Current == null)
|
||||
return null;
|
||||
|
||||
var es3Prefab = ES3ReferenceMgrBase.Current.GetPrefab(prefabId);
|
||||
if (es3Prefab == null)
|
||||
throw new MissingReferenceException("Prefab with ID " + prefabId + " could not be found.\nPress the 'Refresh References' button on the ES3ReferenceMgr Component of the Easy Save 3 Manager in the scene to refresh prefabs.");
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Use PrefabUtility.InstantiatePrefab if we're saving in the Editor and the application isn't playing.
|
||||
// This keeps the connection to the prefab, which is useful for Editor scripts saving data outside of runtime.
|
||||
var instance = Application.isPlaying ? GameObject.Instantiate(es3Prefab.gameObject) : PrefabUtility.InstantiatePrefab(es3Prefab.gameObject);
|
||||
#else
|
||||
var instance = GameObject.Instantiate(es3Prefab.gameObject);
|
||||
#endif
|
||||
var instanceES3Prefab = ((GameObject)instance).GetComponent<ES3Prefab>();
|
||||
if (instanceES3Prefab == null)
|
||||
throw new MissingReferenceException("Prefab with ID " + prefabId + " was found, but it does not have an ES3Prefab component attached.");
|
||||
|
||||
ReadInto<T>(reader, instance);
|
||||
|
||||
return instanceES3Prefab.gameObject;
|
||||
}
|
||||
|
||||
public override void ReadInto<T>(ES3Reader reader, object obj)
|
||||
{
|
||||
// Load as ES3Refs and convert to longs.
|
||||
var localToGlobal_refs = reader.ReadProperty<Dictionary<ES3Ref, ES3Ref>>(ES3Type_ES3RefDictionary.Instance);
|
||||
var localToGlobal = new Dictionary<long, long>();
|
||||
foreach (var kvp in localToGlobal_refs)
|
||||
localToGlobal.Add(kvp.Key.id, kvp.Value.id);
|
||||
|
||||
if (ES3ReferenceMgrBase.Current == null)
|
||||
return;
|
||||
|
||||
((GameObject)obj).GetComponent<ES3Prefab>().ApplyReferences(localToGlobal);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: baff8732cd3074ef88b34f9cc487846d
|
||||
timeCreated: 1519132295
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,118 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using ES3Internal;
|
||||
using UnityEngine.SceneManagement;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
#endif
|
||||
|
||||
public class ES3ReferenceMgr : ES3ReferenceMgrBase
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void RefreshDependencies(bool isEnteringPlayMode = false)
|
||||
{
|
||||
ES3ReferenceMgrBase.isEnteringPlayMode = isEnteringPlayMode;
|
||||
|
||||
// If we're not adding all prefabs to the manager, clear the prefabs array each time we refresh the dependencies.
|
||||
if (!ES3Settings.defaultSettingsScriptableObject.addAllPrefabsToManager)
|
||||
prefabs.Clear();
|
||||
|
||||
// This will get the dependencies for all GameObjects and Components from the active scene.
|
||||
AddDependencies(this.gameObject.scene.GetRootGameObjects());
|
||||
AddPrefabsToManager();
|
||||
RemoveNullOrInvalidValues();
|
||||
|
||||
ES3ReferenceMgrBase.isEnteringPlayMode = false;
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void Optimize()
|
||||
{
|
||||
var dependencies = CollectDependencies(this.gameObject.scene.GetRootGameObjects());
|
||||
var notDependenciesOfScene = new HashSet<UnityEngine.Object>();
|
||||
|
||||
foreach (var kvp in idRef)
|
||||
if (!dependencies.Contains(kvp.Value))
|
||||
notDependenciesOfScene.Add(kvp.Value);
|
||||
|
||||
foreach (var obj in notDependenciesOfScene)
|
||||
{
|
||||
Remove(obj);
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void AddDependencies(UnityEngine.Object[] objs)
|
||||
{
|
||||
for (int i = 0; i < objs.Length; i++)
|
||||
{
|
||||
var obj = objs[i];
|
||||
|
||||
if (obj.name == "Easy Save 3 Manager")
|
||||
continue;
|
||||
|
||||
var dependencies = CollectDependencies(obj);
|
||||
|
||||
foreach (var dependency in dependencies)
|
||||
{
|
||||
if (dependency != null)
|
||||
{
|
||||
Add(dependency);
|
||||
|
||||
// Add the prefab if it's referenced by this scene.
|
||||
if (dependency.GetType() == typeof(ES3Prefab))
|
||||
AddPrefabToManager((ES3Prefab)dependency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Undo.RecordObject(this, "Update Easy Save 3 Reference List");
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void AddDependencies(UnityEngine.Object obj)
|
||||
{
|
||||
AddDependencies(new UnityEngine.Object[] { obj });
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void GeneratePrefabReferences()
|
||||
{
|
||||
AddPrefabsToManager();
|
||||
foreach (var es3Prefab in prefabs)
|
||||
es3Prefab.GeneratePrefabReferences();
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void AddPrefabsToManager()
|
||||
{
|
||||
if (ES3Settings.defaultSettingsScriptableObject.addAllPrefabsToManager)
|
||||
{
|
||||
// Clear any null values. This isn't necessary if we're not adding all prefabs to manager as the list is cleared each time.
|
||||
if (this.prefabs.RemoveAll(item => item == null) > 0)
|
||||
Undo.RecordObject(this, "Update Easy Save 3 Reference List");
|
||||
|
||||
foreach (var es3Prefab in Resources.FindObjectsOfTypeAll<ES3Prefab>())
|
||||
AddPrefabToManager(es3Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
private void AddPrefabToManager(ES3Prefab es3Prefab)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (es3Prefab != null && EditorUtility.IsPersistent(es3Prefab))
|
||||
if(AddPrefab(es3Prefab))
|
||||
Undo.RecordObject(this, "Update Easy Save 3 Reference List");
|
||||
es3Prefab.GeneratePrefabReferences();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9a83408fcc9044c4fbc7e5d09a369ab6
|
||||
timeCreated: 1503395115
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,622 @@
|
|||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
[System.Serializable]
|
||||
[DisallowMultipleComponent]
|
||||
public abstract class ES3ReferenceMgrBase : MonoBehaviour
|
||||
{
|
||||
internal object _lock = new object();
|
||||
|
||||
public const string referencePropertyName = "_ES3Ref";
|
||||
private static ES3ReferenceMgrBase _current = null;
|
||||
private static HashSet<ES3ReferenceMgrBase> mgrs = new HashSet<ES3ReferenceMgrBase>();
|
||||
#if UNITY_EDITOR
|
||||
private const int CollectDependenciesDepth = 5;
|
||||
protected static bool isEnteringPlayMode = false;
|
||||
static readonly HideFlags[] invalidHideFlags = new HideFlags[] { HideFlags.DontSave, HideFlags.DontSaveInBuild, HideFlags.DontSaveInEditor, HideFlags.HideAndDontSave };
|
||||
#endif
|
||||
|
||||
private static System.Random rng;
|
||||
|
||||
[HideInInspector]
|
||||
public bool openPrefabs = false; // Whether the prefab list should be open in the Editor.
|
||||
|
||||
public List<ES3Prefab> prefabs = new List<ES3Prefab>();
|
||||
|
||||
public static ES3ReferenceMgrBase Current
|
||||
{
|
||||
get
|
||||
{
|
||||
// If the reference manager hasn't been assigned, or we've got a reference to a manager in a different scene which isn't marked as DontDestroyOnLoad, look for this scene's manager.
|
||||
if (_current == null /*|| (_current.gameObject.scene.buildIndex != -1 && _current.gameObject.scene != SceneManager.GetActiveScene())*/)
|
||||
{
|
||||
var scene = SceneManager.GetActiveScene();
|
||||
var roots = scene.GetRootGameObjects();
|
||||
ES3ReferenceMgr mgr = null;
|
||||
|
||||
// First, look for Easy Save 3 Manager in the top-level.
|
||||
foreach (var root in roots)
|
||||
if (root.name == "Easy Save 3 Manager")
|
||||
mgr = root.GetComponent<ES3ReferenceMgr>();
|
||||
|
||||
// If the user has moved or renamed the Easy Save 3 Manager, we need to perform a deep search.
|
||||
if (mgr == null)
|
||||
foreach (var root in roots)
|
||||
if ((_current = root.GetComponentInChildren<ES3ReferenceMgr>()) != null)
|
||||
return _current;
|
||||
|
||||
mgrs.Add(_current = mgr);
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsInitialised { get { return idRef.Count > 0; } }
|
||||
|
||||
[SerializeField]
|
||||
public ES3IdRefDictionary idRef = new ES3IdRefDictionary();
|
||||
private ES3RefIdDictionary _refId = null;
|
||||
|
||||
public ES3RefIdDictionary refId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_refId == null)
|
||||
{
|
||||
_refId = new ES3RefIdDictionary();
|
||||
// Populate the reverse dictionary with the items from the normal dictionary.
|
||||
foreach (var kvp in idRef)
|
||||
if (kvp.Value != null)
|
||||
_refId[kvp.Value] = kvp.Key;
|
||||
}
|
||||
return _refId;
|
||||
}
|
||||
set
|
||||
{
|
||||
_refId = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ES3GlobalReferences GlobalReferences
|
||||
{
|
||||
get
|
||||
{
|
||||
return ES3GlobalReferences.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_current != null && _current != this)
|
||||
{
|
||||
var existing = _current;
|
||||
|
||||
/* We intentionally use Current rather than _current here, as _current may contain a reference to a manager in another scene,
|
||||
* but Current only returns the Manager for the active scene. */
|
||||
if (Current != null)
|
||||
{
|
||||
existing.Merge(this);
|
||||
if (gameObject.name.Contains("Easy Save 3 Manager"))
|
||||
Destroy(this.gameObject);
|
||||
else
|
||||
Destroy(this);
|
||||
_current = existing; // Undo the call to Current, which may have set it to NULL.
|
||||
}
|
||||
}
|
||||
else
|
||||
_current = this;
|
||||
mgrs.Add(this);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
mgrs.Remove(this);
|
||||
}
|
||||
|
||||
// Merges two managers, not allowing any clashes of IDs
|
||||
public void Merge(ES3ReferenceMgrBase otherMgr)
|
||||
{
|
||||
foreach (var kvp in otherMgr.idRef)
|
||||
Add(kvp.Value, kvp.Key);
|
||||
}
|
||||
|
||||
public long Get(UnityEngine.Object obj)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
if (obj == null)
|
||||
return -1;
|
||||
long id;
|
||||
if (!mgr.refId.TryGetValue(obj, out id))
|
||||
return -1;
|
||||
return id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal UnityEngine.Object Get(long id, Type type, bool suppressWarnings=false)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
if (id == -1)
|
||||
return null;
|
||||
UnityEngine.Object obj;
|
||||
if (!mgr.idRef.TryGetValue(id, out obj))
|
||||
{
|
||||
if (GlobalReferences != null)
|
||||
{
|
||||
var globalRef = GlobalReferences.Get(id);
|
||||
if (globalRef != null)
|
||||
return globalRef;
|
||||
}
|
||||
|
||||
if(type != null)
|
||||
ES3Debug.LogWarning("Reference for " + type + " with ID " + id + " could not be found in Easy Save's reference manager. If you are loading objects dynamically (i.e. objects created at runtime), this warning is expected and can be ignored.", this);
|
||||
else
|
||||
ES3Debug.LogWarning("Reference with ID " + id + " could not be found in Easy Save's reference manager. If you are loading objects dynamically (i.e. objects created at runtime), this warning is expected and can be ignored.", this);
|
||||
return null;
|
||||
}
|
||||
if (obj == null) // If obj has been marked as destroyed but not yet destroyed, don't return it.
|
||||
return null;
|
||||
return obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public UnityEngine.Object Get(long id, bool suppressWarnings = false)
|
||||
{
|
||||
return Get(id, null, suppressWarnings);
|
||||
}
|
||||
|
||||
public ES3Prefab GetPrefab(long id, bool suppressWarnings = false)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
foreach (var prefab in mgr.prefabs)
|
||||
if (prefabs != null && prefab.prefabId == id)
|
||||
return prefab;
|
||||
}
|
||||
if (!suppressWarnings)
|
||||
ES3Debug.LogWarning("Prefab with ID " + id + " could not be found in Easy Save's reference manager. Try pressing the Refresh References button on the ES3ReferenceMgr Component of the Easy Save 3 Manager in your scene.", this);
|
||||
return null;
|
||||
}
|
||||
|
||||
public long GetPrefab(ES3Prefab prefabToFind, bool suppressWarnings = false)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
foreach (var prefab in prefabs)
|
||||
if (prefab == prefabToFind)
|
||||
return prefab.prefabId;
|
||||
}
|
||||
if (!suppressWarnings)
|
||||
ES3Debug.LogWarning("Prefab with name " + prefabToFind.name + " could not be found in Easy Save's reference manager. Try pressing the Refresh References button on the ES3ReferenceMgr Component of the Easy Save 3 Manager in your scene.", prefabToFind);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public long Add(UnityEngine.Object obj)
|
||||
{
|
||||
long id;
|
||||
// If it already exists in the list, do nothing.
|
||||
if (refId.TryGetValue(obj, out id))
|
||||
return id;
|
||||
|
||||
if (GlobalReferences != null)
|
||||
{
|
||||
id = GlobalReferences.GetOrAdd(obj);
|
||||
if (id != -1)
|
||||
{
|
||||
Add(obj, id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
// Add the reference to the Dictionary.
|
||||
id = GetNewRefID();
|
||||
return Add(obj, id);
|
||||
}
|
||||
}
|
||||
|
||||
public long Add(UnityEngine.Object obj, long id)
|
||||
{
|
||||
if (!CanBeSaved(obj))
|
||||
return -1;
|
||||
|
||||
// If the ID is -1, auto-generate an ID.
|
||||
if (id == -1)
|
||||
id = GetNewRefID();
|
||||
// Add the reference to the Dictionary.
|
||||
lock (_lock)
|
||||
{
|
||||
idRef[id] = obj;
|
||||
if(obj != null)
|
||||
refId[obj] = id;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public bool AddPrefab(ES3Prefab prefab)
|
||||
{
|
||||
if (!prefabs.Contains(prefab))
|
||||
{
|
||||
prefabs.Add(prefab);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Remove(UnityEngine.Object obj)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
lock (mgr._lock)
|
||||
{
|
||||
mgr.refId.Remove(obj);
|
||||
// There may be multiple references with the same ID, so remove them all.
|
||||
foreach (var item in mgr.idRef.Where(kvp => kvp.Value == obj).ToList())
|
||||
mgr.idRef.Remove(item.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(long referenceID)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
lock (mgr._lock)
|
||||
{
|
||||
mgr.idRef.Remove(referenceID);
|
||||
// There may be multiple references with the same ID, so remove them all.
|
||||
foreach (var item in mgr.refId.Where(kvp => kvp.Value == referenceID).ToList())
|
||||
mgr.refId.Remove(item.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveNullOrInvalidValues()
|
||||
{
|
||||
var nullKeys = idRef.Where(pair => pair.Value == null || !CanBeSaved(pair.Value))
|
||||
.Select(pair => pair.Key).ToList();
|
||||
foreach (var key in nullKeys)
|
||||
idRef.Remove(key);
|
||||
|
||||
if (GlobalReferences != null)
|
||||
GlobalReferences.RemoveInvalidKeys();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
refId.Clear();
|
||||
idRef.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(UnityEngine.Object obj)
|
||||
{
|
||||
return refId.ContainsKey(obj);
|
||||
}
|
||||
|
||||
public bool Contains(long referenceID)
|
||||
{
|
||||
return idRef.ContainsKey(referenceID);
|
||||
}
|
||||
|
||||
public void ChangeId(long oldId, long newId)
|
||||
{
|
||||
foreach (var mgr in mgrs)
|
||||
{
|
||||
if (mgr == null)
|
||||
continue;
|
||||
|
||||
mgr.idRef.ChangeKey(oldId, newId);
|
||||
// Empty the refId so it has to be refreshed.
|
||||
mgr.refId = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static long GetNewRefID()
|
||||
{
|
||||
if (rng == null)
|
||||
rng = new System.Random();
|
||||
|
||||
byte[] buf = new byte[8];
|
||||
rng.NextBytes(buf);
|
||||
long longRand = BitConverter.ToInt64(buf, 0);
|
||||
|
||||
return (System.Math.Abs(longRand % (long.MaxValue - 0)) + 0);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public static HashSet<UnityEngine.Object> CollectDependencies(UnityEngine.Object obj, HashSet<UnityEngine.Object> dependencies = null, int depth = CollectDependenciesDepth)
|
||||
{
|
||||
return CollectDependencies(new UnityEngine.Object[] { obj }, dependencies, depth);
|
||||
}
|
||||
|
||||
/*
|
||||
* Collects all top-level dependencies of an object.
|
||||
* For GameObjects, it will traverse all children.
|
||||
* For Components or ScriptableObjects, it will get all serialisable UnityEngine.Object fields/properties as dependencies.
|
||||
*/
|
||||
public static HashSet<UnityEngine.Object> CollectDependencies(UnityEngine.Object[] objs, HashSet<UnityEngine.Object> dependencies = null, int depth = CollectDependenciesDepth)
|
||||
{
|
||||
if (depth < 0)
|
||||
return dependencies;
|
||||
|
||||
if (dependencies == null)
|
||||
dependencies = new HashSet<UnityEngine.Object>();
|
||||
|
||||
foreach (var obj in objs)
|
||||
{
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
var type = obj.GetType();
|
||||
|
||||
// Skip types which don't need processing
|
||||
if (type == typeof(ES3ReferenceMgr) || type == typeof(ES3AutoSaveMgr) || type == typeof(ES3AutoSave) || type == typeof(ES3InspectorInfo))
|
||||
continue;
|
||||
|
||||
// Add the prefab to the manager but don't process it. We'll use this to work out what prefabs to add to the prefabs list later.
|
||||
if (type == typeof(ES3Prefab))
|
||||
{
|
||||
dependencies.Add(obj);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's a GameObject, get the GameObject's Components and collect their dependencies.
|
||||
if (type == typeof(GameObject))
|
||||
{
|
||||
var go = (GameObject)obj;
|
||||
// If we've not already processed this GameObject ...
|
||||
if (dependencies.Add(go))
|
||||
{
|
||||
// Get the dependencies of each Component in the GameObject.
|
||||
CollectDependencies(go.GetComponents<Component>(), dependencies, depth - 1);
|
||||
// Get the dependencies of each child in the GameObject.
|
||||
foreach (Transform child in go.transform)
|
||||
CollectDependencies(child.gameObject, dependencies, depth); // Don't decrement child, as we consider this a top-level object.
|
||||
}
|
||||
}
|
||||
// Else if it's a Component or ScriptableObject, add the values of any UnityEngine.Object fields as dependencies.
|
||||
else
|
||||
CollectDependenciesFromFields(obj, dependencies, depth - 1);
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private static void CollectDependenciesFromFields(UnityEngine.Object obj, HashSet<UnityEngine.Object> dependencies, int depth)
|
||||
{
|
||||
// If we've already collected dependencies for this, do nothing.
|
||||
if (!dependencies.Add(obj))
|
||||
return;
|
||||
|
||||
if (depth < 0)
|
||||
return;
|
||||
|
||||
var type = obj.GetType();
|
||||
|
||||
if (isEnteringPlayMode && type == typeof(UnityEngine.UI.Text))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// SerializedObject is expensive, so for known classes we manually gather references.
|
||||
|
||||
if (type == typeof(Animator) || obj is Transform || type == typeof(CanvasRenderer) || type == typeof(Mesh) || type == typeof(AudioClip) || type == typeof(Rigidbody) || obj is Texture || obj is HorizontalOrVerticalLayoutGroup)
|
||||
return;
|
||||
|
||||
if (obj is Graphic)
|
||||
{
|
||||
var m = (Graphic)obj;
|
||||
dependencies.Add(m.material);
|
||||
dependencies.Add(m.defaultMaterial);
|
||||
dependencies.Add(m.mainTexture);
|
||||
|
||||
if (type == typeof(Text))
|
||||
{
|
||||
var text = (Text)obj;
|
||||
dependencies.Add(text.font);
|
||||
}
|
||||
else if (type == typeof(Image))
|
||||
{
|
||||
var img = (Image)obj;
|
||||
dependencies.Add(img.sprite);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(Mesh))
|
||||
{
|
||||
if (UnityEditor.AssetDatabase.Contains(obj))
|
||||
dependencies.Add(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(Material))
|
||||
{
|
||||
dependencies.Add(((Material)obj).shader);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(MeshFilter))
|
||||
{
|
||||
dependencies.Add(((MeshFilter)obj).sharedMesh);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(MeshCollider))
|
||||
{
|
||||
var mc = (MeshCollider)obj;
|
||||
dependencies.Add(mc.sharedMesh);
|
||||
dependencies.Add(mc.sharedMaterial);
|
||||
dependencies.Add(mc.attachedRigidbody);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(Camera))
|
||||
{
|
||||
var c = (Camera)obj;
|
||||
dependencies.Add(c.targetTexture);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == typeof(SkinnedMeshRenderer))
|
||||
dependencies.Add(((SkinnedMeshRenderer)obj).sharedMesh); // Don't return. Let this fall through to the if(obj is renderer) call.
|
||||
else if (type == typeof(SpriteRenderer))
|
||||
dependencies.Add(((SpriteRenderer)obj).sprite); // Don't return. Let this fall through to the if(obj is renderer) call.
|
||||
else if (type == typeof(ParticleSystemRenderer))
|
||||
dependencies.Add(((ParticleSystemRenderer)obj).mesh); // Don't return. Let this fall through to the if(obj is renderer) call.
|
||||
|
||||
if (obj is Renderer)
|
||||
{
|
||||
dependencies.UnionWith(((Renderer)obj).sharedMaterials);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
var so = new UnityEditor.SerializedObject(obj);
|
||||
if (so == null)
|
||||
return;
|
||||
|
||||
var property = so.GetIterator();
|
||||
if (property == null)
|
||||
return;
|
||||
|
||||
// Iterate through each of this object's properties.
|
||||
while (property.NextVisible(true))
|
||||
{
|
||||
try
|
||||
{
|
||||
// If it's an array which contains UnityEngine.Objects, add them as dependencies.
|
||||
if (property.isArray)
|
||||
{
|
||||
for (int i = 0; i < property.arraySize; i++)
|
||||
{
|
||||
var element = property.GetArrayElementAtIndex(i);
|
||||
|
||||
// If the array contains UnityEngine.Object types, add them to the dependencies.
|
||||
if (element.propertyType == UnityEditor.SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
var elementValue = element.objectReferenceValue;
|
||||
var elementType = elementValue.GetType();
|
||||
|
||||
// If it's a GameObject, use CollectDependencies so that Components are also added.
|
||||
if (elementType == typeof(GameObject))
|
||||
CollectDependencies(elementValue, dependencies, depth - 1);
|
||||
else
|
||||
CollectDependenciesFromFields(elementValue, dependencies, depth - 1);
|
||||
}
|
||||
// Otherwise this array does not contain UnityEngine.Object types, so we should stop.
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Else if it's a normal UnityEngine.Object field, add it.
|
||||
else if (property.propertyType == UnityEditor.SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
var propertyValue = property.objectReferenceValue;
|
||||
if (propertyValue == null)
|
||||
break;
|
||||
|
||||
// If it's a GameObject, use CollectDependencies so that Components are also added.
|
||||
if (propertyValue.GetType() == typeof(GameObject))
|
||||
CollectDependencies(propertyValue, dependencies, depth - 1);
|
||||
else
|
||||
CollectDependenciesFromFields(propertyValue, dependencies, depth - 1);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Called in the Editor when this Component is added.
|
||||
private void Reset()
|
||||
{
|
||||
// Ensure that Component can only be added by going to Assets > Easy Save 3 > Add Manager to Scene.
|
||||
if (gameObject.name != "Easy Save 3 Manager")
|
||||
{
|
||||
UnityEditor.EditorUtility.DisplayDialog("Cannot add ES3ReferenceMgr directly", "Please go to 'Assets > Easy Save 3 > Add Manager to Scene' to add an Easy Save 3 Manager to your scene.", "Ok");
|
||||
DestroyImmediate(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static bool CanBeSaved(UnityEngine.Object obj)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (obj == null)
|
||||
return true;
|
||||
|
||||
foreach (var flag in invalidHideFlags)
|
||||
if ((obj.hideFlags & flag) != 0 && obj.hideFlags != HideFlags.HideInHierarchy && obj.hideFlags != HideFlags.HideInInspector && obj.hideFlags != HideFlags.NotEditable)
|
||||
if (!(obj is Mesh || obj is Material))
|
||||
return false;
|
||||
|
||||
// Exclude the Easy Save 3 Manager, and all components attached to it.
|
||||
if (obj.name == "Easy Save 3 Manager")
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ES3IdRefDictionary : ES3SerializableDictionary<long, UnityEngine.Object>
|
||||
{
|
||||
protected override bool KeysAreEqual(long a, long b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
protected override bool ValuesAreEqual(UnityEngine.Object a, UnityEngine.Object b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
[System.Serializable]
|
||||
public class ES3RefIdDictionary : ES3SerializableDictionary<UnityEngine.Object, long>
|
||||
{
|
||||
protected override bool KeysAreEqual(UnityEngine.Object a, UnityEngine.Object b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
protected override bool ValuesAreEqual(long a, long b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f659e3ad478b6470d9744732042e7515
|
||||
timeCreated: 1519132301
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,766 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
using UnityEngine;
|
||||
using ES3Types;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
public static class ES3Reflection
|
||||
{
|
||||
public const string memberFieldPrefix = "m_";
|
||||
public const string componentTagFieldName = "tag";
|
||||
public const string componentNameFieldName = "name";
|
||||
public static readonly string[] excludedPropertyNames = new string[] { "runInEditMode", "useGUILayout", "hideFlags" };
|
||||
|
||||
public static readonly Type serializableAttributeType = typeof(System.SerializableAttribute);
|
||||
public static readonly Type serializeFieldAttributeType = typeof(SerializeField);
|
||||
public static readonly Type obsoleteAttributeType = typeof(System.ObsoleteAttribute);
|
||||
public static readonly Type nonSerializedAttributeType = typeof(System.NonSerializedAttribute);
|
||||
public static readonly Type es3SerializableAttributeType = typeof(ES3Serializable);
|
||||
public static readonly Type es3NonSerializableAttributeType = typeof(ES3NonSerializable);
|
||||
|
||||
public static Type[] EmptyTypes = new Type[0];
|
||||
|
||||
private static Assembly[] _assemblies = null;
|
||||
private static Assembly[] Assemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_assemblies == null)
|
||||
{
|
||||
var assemblyNames = new ES3Settings().assemblyNames;
|
||||
var assemblyList = new List<Assembly>();
|
||||
|
||||
for (int i = 0; i < assemblyNames.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.Load(new AssemblyName(assemblyNames[i]));
|
||||
if (assembly != null)
|
||||
assemblyList.Add(assembly);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
_assemblies = assemblyList.ToArray();
|
||||
}
|
||||
return _assemblies;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the element type of a collection or array.
|
||||
* Returns null if type is not a collection type.
|
||||
*/
|
||||
public static Type[] GetElementTypes(Type type)
|
||||
{
|
||||
if (IsGenericType(type))
|
||||
return ES3Reflection.GetGenericArguments(type);
|
||||
else if (type.IsArray)
|
||||
return new Type[] { ES3Reflection.GetElementType(type) };
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<FieldInfo> GetSerializableFields(Type type, List<FieldInfo> serializableFields = null, bool safe = true, string[] memberNames = null, BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
{
|
||||
if (type == null)
|
||||
return new List<FieldInfo>();
|
||||
|
||||
var fields = type.GetFields(bindings);
|
||||
|
||||
if (serializableFields == null)
|
||||
serializableFields = new List<FieldInfo>();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var fieldName = field.Name;
|
||||
|
||||
// If a members array was provided as a parameter, only include the field if it's in the array.
|
||||
if (memberNames != null)
|
||||
if (!memberNames.Contains(fieldName))
|
||||
continue;
|
||||
|
||||
var fieldType = field.FieldType;
|
||||
|
||||
if (AttributeIsDefined(field, es3SerializableAttributeType))
|
||||
{
|
||||
serializableFields.Add(field);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AttributeIsDefined(field, es3NonSerializableAttributeType))
|
||||
continue;
|
||||
|
||||
if (safe)
|
||||
{
|
||||
// If the field is private, only serialize it if it's explicitly marked as serializable.
|
||||
if (!field.IsPublic && !AttributeIsDefined(field, serializeFieldAttributeType))
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude const or readonly fields.
|
||||
if (field.IsLiteral || field.IsInitOnly)
|
||||
continue;
|
||||
|
||||
// Don't store fields whose type is the same as the class the field is housed in unless it's stored by reference (to prevent cyclic references)
|
||||
if (fieldType == type && !IsAssignableFrom(typeof(UnityEngine.Object), fieldType))
|
||||
continue;
|
||||
|
||||
// If property is marked as obsolete or non-serialized, don't serialize it.
|
||||
if (AttributeIsDefined(field, nonSerializedAttributeType) || AttributeIsDefined(field, obsoleteAttributeType))
|
||||
continue;
|
||||
|
||||
if (!TypeIsSerializable(field.FieldType))
|
||||
continue;
|
||||
|
||||
// Don't serialize member fields.
|
||||
if (safe && fieldName.StartsWith(memberFieldPrefix) && field.DeclaringType.Namespace != null && field.DeclaringType.Namespace.Contains("UnityEngine"))
|
||||
continue;
|
||||
|
||||
serializableFields.Add(field);
|
||||
}
|
||||
|
||||
var baseType = BaseType(type);
|
||||
if (baseType != null && baseType != typeof(System.Object) && baseType != typeof(UnityEngine.Object))
|
||||
GetSerializableFields(BaseType(type), serializableFields, safe, memberNames);
|
||||
|
||||
return serializableFields;
|
||||
}
|
||||
|
||||
public static List<PropertyInfo> GetSerializableProperties(Type type, List<PropertyInfo> serializableProperties = null, bool safe = true, string[] memberNames = null, BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
{
|
||||
bool isComponent = IsAssignableFrom(typeof(UnityEngine.Component), type);
|
||||
|
||||
// Only get private properties if we're not getting properties safely.
|
||||
if (!safe)
|
||||
bindings = bindings | BindingFlags.NonPublic;
|
||||
|
||||
var properties = type.GetProperties(bindings);
|
||||
|
||||
if (serializableProperties == null)
|
||||
serializableProperties = new List<PropertyInfo>();
|
||||
|
||||
foreach (var p in properties)
|
||||
{
|
||||
if (AttributeIsDefined(p, es3SerializableAttributeType))
|
||||
{
|
||||
serializableProperties.Add(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AttributeIsDefined(p, es3NonSerializableAttributeType))
|
||||
continue;
|
||||
|
||||
var propertyName = p.Name;
|
||||
|
||||
if (excludedPropertyNames.Contains(propertyName))
|
||||
continue;
|
||||
|
||||
// If a members array was provided as a parameter, only include the property if it's in the array.
|
||||
if (memberNames != null)
|
||||
if (!memberNames.Contains(propertyName))
|
||||
continue;
|
||||
|
||||
if (safe)
|
||||
{
|
||||
// If safe serialization is enabled, only get properties which are explicitly marked as serializable.
|
||||
if (!AttributeIsDefined(p, serializeFieldAttributeType) && !AttributeIsDefined(p, es3SerializableAttributeType))
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertyType = p.PropertyType;
|
||||
|
||||
// Don't store properties whose type is the same as the class the property is housed in unless it's stored by reference (to prevent cyclic references)
|
||||
if (propertyType == type && !IsAssignableFrom(typeof(UnityEngine.Object), propertyType))
|
||||
continue;
|
||||
|
||||
if (!p.CanRead || !p.CanWrite)
|
||||
continue;
|
||||
|
||||
// Only support properties with indexing if they're an array.
|
||||
if (p.GetIndexParameters().Length != 0 && !propertyType.IsArray)
|
||||
continue;
|
||||
|
||||
// Check that the type of the property is one which we can serialize.
|
||||
// Also check whether an ES3Type exists for it.
|
||||
if (!TypeIsSerializable(propertyType))
|
||||
continue;
|
||||
|
||||
// Ignore certain properties on components.
|
||||
if (isComponent)
|
||||
{
|
||||
// Ignore properties which are accessors for GameObject fields.
|
||||
if (propertyName == componentTagFieldName || propertyName == componentNameFieldName)
|
||||
continue;
|
||||
}
|
||||
|
||||
// If property is marked as obsolete or non-serialized, don't serialize it.
|
||||
if (AttributeIsDefined(p, obsoleteAttributeType) || AttributeIsDefined(p, nonSerializedAttributeType))
|
||||
continue;
|
||||
|
||||
serializableProperties.Add(p);
|
||||
}
|
||||
|
||||
var baseType = BaseType(type);
|
||||
if (baseType != null && baseType != typeof(System.Object))
|
||||
GetSerializableProperties(baseType, serializableProperties, safe, memberNames);
|
||||
|
||||
return serializableProperties;
|
||||
}
|
||||
|
||||
public static bool TypeIsSerializable(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
return false;
|
||||
|
||||
if (AttributeIsDefined(type, es3NonSerializableAttributeType))
|
||||
return false;
|
||||
|
||||
if (IsPrimitive(type) || IsValueType(type) || IsAssignableFrom(typeof(UnityEngine.Component), type) || IsAssignableFrom(typeof(UnityEngine.ScriptableObject), type))
|
||||
return true;
|
||||
|
||||
var es3Type = ES3TypeMgr.GetOrCreateES3Type(type, false);
|
||||
|
||||
if (es3Type != null && !es3Type.isUnsupported)
|
||||
return true;
|
||||
|
||||
if (TypeIsArray(type))
|
||||
{
|
||||
if (TypeIsSerializable(type.GetElementType()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
var genericArgs = type.GetGenericArguments();
|
||||
for (int i = 0; i < genericArgs.Length; i++)
|
||||
if (!TypeIsSerializable(genericArgs[i]))
|
||||
return false;
|
||||
|
||||
if (HasParameterlessConstructor(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static System.Object CreateInstance(Type type)
|
||||
{
|
||||
if (IsAssignableFrom(typeof(UnityEngine.Component), type))
|
||||
return ES3ComponentType.CreateComponent(type);
|
||||
else if (IsAssignableFrom(typeof(ScriptableObject), type))
|
||||
return ScriptableObject.CreateInstance(type);
|
||||
return Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
public static System.Object CreateInstance(Type type, params object[] args)
|
||||
{
|
||||
if (IsAssignableFrom(typeof(UnityEngine.Component), type))
|
||||
return ES3ComponentType.CreateComponent(type);
|
||||
else if (IsAssignableFrom(typeof(ScriptableObject), type))
|
||||
return ScriptableObject.CreateInstance(type);
|
||||
return Activator.CreateInstance(type, args);
|
||||
}
|
||||
|
||||
public static Array ArrayCreateInstance(Type type, int length)
|
||||
{
|
||||
return Array.CreateInstance(type, new int[] { length });
|
||||
}
|
||||
|
||||
public static Array ArrayCreateInstance(Type type, int[] dimensions)
|
||||
{
|
||||
return Array.CreateInstance(type, dimensions);
|
||||
}
|
||||
|
||||
public static Type MakeGenericType(Type type, Type genericParam)
|
||||
{
|
||||
return type.MakeGenericType(genericParam);
|
||||
}
|
||||
|
||||
public static ES3ReflectedMember[] GetSerializableMembers(Type type, bool safe = true, string[] memberNames = null)
|
||||
{
|
||||
if (type == null)
|
||||
return new ES3ReflectedMember[0];
|
||||
|
||||
var fieldInfos = GetSerializableFields(type, new List<FieldInfo>(), safe, memberNames);
|
||||
var propertyInfos = GetSerializableProperties(type, new List<PropertyInfo>(), safe, memberNames);
|
||||
var reflectedFields = new ES3ReflectedMember[fieldInfos.Count + propertyInfos.Count];
|
||||
|
||||
for (int i = 0; i < fieldInfos.Count; i++)
|
||||
reflectedFields[i] = new ES3ReflectedMember(fieldInfos[i]);
|
||||
for (int i = 0; i < propertyInfos.Count; i++)
|
||||
reflectedFields[i + fieldInfos.Count] = new ES3ReflectedMember(propertyInfos[i]);
|
||||
|
||||
return reflectedFields;
|
||||
}
|
||||
|
||||
public static ES3ReflectedMember GetES3ReflectedProperty(Type type, string propertyName)
|
||||
{
|
||||
var propertyInfo = ES3Reflection.GetProperty(type, propertyName);
|
||||
return new ES3ReflectedMember(propertyInfo);
|
||||
}
|
||||
|
||||
public static ES3ReflectedMember GetES3ReflectedMember(Type type, string fieldName)
|
||||
{
|
||||
var fieldInfo = ES3Reflection.GetField(type, fieldName);
|
||||
return new ES3ReflectedMember(fieldInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds all classes of a specific type, and then returns an instance of each.
|
||||
* Ignores classes which can't be instantiated (i.e. abstract classes).
|
||||
*/
|
||||
public static IList<T> GetInstances<T>()
|
||||
{
|
||||
var instances = new List<T>();
|
||||
foreach (var assembly in Assemblies)
|
||||
foreach (var type in assembly.GetTypes())
|
||||
if (IsAssignableFrom(typeof(T), type) && ES3Reflection.HasParameterlessConstructor(type) && !ES3Reflection.IsAbstract(type))
|
||||
instances.Add((T)Activator.CreateInstance(type));
|
||||
return instances;
|
||||
}
|
||||
|
||||
public static IList<Type> GetDerivedTypes(Type derivedType)
|
||||
{
|
||||
return
|
||||
(
|
||||
from assembly in Assemblies
|
||||
from type in assembly.GetTypes()
|
||||
where IsAssignableFrom(derivedType, type)
|
||||
select type
|
||||
).ToList();
|
||||
}
|
||||
|
||||
public static bool IsAssignableFrom(Type a, Type b)
|
||||
{
|
||||
return a.IsAssignableFrom(b);
|
||||
}
|
||||
|
||||
public static Type GetGenericTypeDefinition(Type type)
|
||||
{
|
||||
return type.GetGenericTypeDefinition();
|
||||
}
|
||||
|
||||
public static Type[] GetGenericArguments(Type type)
|
||||
{
|
||||
return type.GetGenericArguments();
|
||||
}
|
||||
|
||||
public static int GetArrayRank(Type type)
|
||||
{
|
||||
return type.GetArrayRank();
|
||||
}
|
||||
|
||||
public static string GetAssemblyQualifiedName(Type type)
|
||||
{
|
||||
return type.AssemblyQualifiedName;
|
||||
}
|
||||
|
||||
public static ES3ReflectedMethod GetMethod(Type type, string methodName, Type[] genericParameters, Type[] parameterTypes)
|
||||
{
|
||||
return new ES3ReflectedMethod(type, methodName, genericParameters, parameterTypes);
|
||||
}
|
||||
|
||||
public static bool TypeIsArray(Type type)
|
||||
{
|
||||
return type.IsArray;
|
||||
}
|
||||
|
||||
public static Type GetElementType(Type type)
|
||||
{
|
||||
return type.GetElementType();
|
||||
}
|
||||
|
||||
#if NETFX_CORE
|
||||
public static bool IsAbstract(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsAbstract;
|
||||
}
|
||||
|
||||
public static bool IsInterface(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsInterface;
|
||||
}
|
||||
|
||||
public static bool IsGenericType(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsGenericType;
|
||||
}
|
||||
|
||||
public static bool IsValueType(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsValueType;
|
||||
}
|
||||
|
||||
public static bool IsEnum(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().IsEnum;
|
||||
}
|
||||
|
||||
public static bool HasParameterlessConstructor(Type type)
|
||||
{
|
||||
foreach (var cInfo in type.GetTypeInfo().DeclaredConstructors)
|
||||
{
|
||||
if (!cInfo.IsFamily && !cInfo.IsStatic && cInfo.GetParameters().Length == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public static ConstructorInfo GetParameterlessConstructor(Type type)
|
||||
{
|
||||
foreach (var cInfo in type.GetTypeInfo().DeclaredConstructors)
|
||||
{
|
||||
if (!cInfo.IsFamily && cInfo.GetParameters().Length == 0)
|
||||
return cInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetShortAssemblyQualifiedName(Type type)
|
||||
{
|
||||
if (IsPrimitive (type))
|
||||
return type.ToString ();
|
||||
return type.FullName + "," + type.GetTypeInfo().Assembly.GetName().Name;
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(Type type, string propertyName)
|
||||
{
|
||||
var property = type.GetTypeInfo().GetDeclaredProperty(propertyName);
|
||||
if (property == null && type.BaseType != typeof(object))
|
||||
return GetProperty(type.BaseType, propertyName);
|
||||
return property;
|
||||
}
|
||||
|
||||
public static FieldInfo GetField(Type type, string fieldName)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredField(fieldName);
|
||||
}
|
||||
|
||||
public static MethodInfo[] GetMethods(Type type, string methodName)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredMethods(methodName);
|
||||
}
|
||||
|
||||
public static bool IsPrimitive(Type type)
|
||||
{
|
||||
return (type.GetTypeInfo().IsPrimitive || type == typeof(string) || type == typeof(decimal));
|
||||
}
|
||||
|
||||
public static bool AttributeIsDefined(MemberInfo info, Type attributeType)
|
||||
{
|
||||
var attributes = info.GetCustomAttributes(attributeType, true);
|
||||
foreach(var attribute in attributes)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AttributeIsDefined(Type type, Type attributeType)
|
||||
{
|
||||
var attributes = type.GetTypeInfo().GetCustomAttributes(attributeType, true);
|
||||
foreach(var attribute in attributes)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ImplementsInterface(Type type, Type interfaceType)
|
||||
{
|
||||
return type.GetTypeInfo().ImplementedInterfaces.Contains(interfaceType);
|
||||
}
|
||||
|
||||
public static Type BaseType(Type type)
|
||||
{
|
||||
return type.GetTypeInfo().BaseType;
|
||||
}
|
||||
#else
|
||||
public static bool IsAbstract(Type type)
|
||||
{
|
||||
return type.IsAbstract;
|
||||
}
|
||||
|
||||
public static bool IsInterface(Type type)
|
||||
{
|
||||
return type.IsInterface;
|
||||
}
|
||||
|
||||
public static bool IsGenericType(Type type)
|
||||
{
|
||||
return type.IsGenericType;
|
||||
}
|
||||
|
||||
public static bool IsValueType(Type type)
|
||||
{
|
||||
return type.IsValueType;
|
||||
}
|
||||
|
||||
public static bool IsEnum(Type type)
|
||||
{
|
||||
return type.IsEnum;
|
||||
}
|
||||
|
||||
public static bool HasParameterlessConstructor(Type type)
|
||||
{
|
||||
return type.GetConstructor(Type.EmptyTypes) != null || IsValueType(type);
|
||||
}
|
||||
|
||||
public static ConstructorInfo GetParameterlessConstructor(Type type)
|
||||
{
|
||||
return type.GetConstructor(Type.EmptyTypes);
|
||||
}
|
||||
|
||||
public static string GetShortAssemblyQualifiedName(Type type)
|
||||
{
|
||||
if (IsPrimitive(type))
|
||||
return type.ToString();
|
||||
return type.FullName + "," + type.Assembly.GetName().Name;
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(Type type, string propertyName)
|
||||
{
|
||||
var property = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (property == null && BaseType(type) != typeof(object))
|
||||
return GetProperty(BaseType(type), propertyName);
|
||||
return property;
|
||||
}
|
||||
|
||||
public static FieldInfo GetField(Type type, string fieldName)
|
||||
{
|
||||
var field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (field == null && BaseType(type) != typeof(object))
|
||||
return GetField(BaseType(type), fieldName);
|
||||
return field;
|
||||
}
|
||||
|
||||
public static MethodInfo[] GetMethods(Type type, string methodName)
|
||||
{
|
||||
return type.GetMethods().Where(t => t.Name == methodName).ToArray();
|
||||
}
|
||||
|
||||
public static bool IsPrimitive(Type type)
|
||||
{
|
||||
return (type.IsPrimitive || type == typeof(string) || type == typeof(decimal));
|
||||
}
|
||||
|
||||
public static bool AttributeIsDefined(MemberInfo info, Type attributeType)
|
||||
{
|
||||
return Attribute.IsDefined(info, attributeType, true);
|
||||
}
|
||||
|
||||
public static bool AttributeIsDefined(Type type, Type attributeType)
|
||||
{
|
||||
return type.IsDefined(attributeType, true);
|
||||
}
|
||||
|
||||
public static bool ImplementsInterface(Type type, Type interfaceType)
|
||||
{
|
||||
return (type.GetInterface(interfaceType.Name) != null);
|
||||
}
|
||||
|
||||
public static Type BaseType(Type type)
|
||||
{
|
||||
return type.BaseType;
|
||||
}
|
||||
|
||||
public static Type GetType(string typeString)
|
||||
{
|
||||
switch (typeString)
|
||||
{
|
||||
case "bool":
|
||||
return typeof(bool);
|
||||
case "byte":
|
||||
return typeof(byte);
|
||||
case "sbyte":
|
||||
return typeof(sbyte);
|
||||
case "char":
|
||||
return typeof(char);
|
||||
case "decimal":
|
||||
return typeof(decimal);
|
||||
case "double":
|
||||
return typeof(double);
|
||||
case "float":
|
||||
return typeof(float);
|
||||
case "int":
|
||||
return typeof(int);
|
||||
case "uint":
|
||||
return typeof(uint);
|
||||
case "long":
|
||||
return typeof(long);
|
||||
case "ulong":
|
||||
return typeof(ulong);
|
||||
case "short":
|
||||
return typeof(short);
|
||||
case "ushort":
|
||||
return typeof(ushort);
|
||||
case "string":
|
||||
return typeof(string);
|
||||
case "Vector2":
|
||||
return typeof(Vector2);
|
||||
case "Vector3":
|
||||
return typeof(Vector3);
|
||||
case "Vector4":
|
||||
return typeof(Vector4);
|
||||
case "Color":
|
||||
return typeof(Color);
|
||||
case "Transform":
|
||||
return typeof(Transform);
|
||||
case "Component":
|
||||
return typeof(UnityEngine.Component);
|
||||
case "GameObject":
|
||||
return typeof(GameObject);
|
||||
case "MeshFilter":
|
||||
return typeof(MeshFilter);
|
||||
case "Material":
|
||||
return typeof(Material);
|
||||
case "Texture2D":
|
||||
return typeof(Texture2D);
|
||||
case "UnityEngine.Object":
|
||||
return typeof(UnityEngine.Object);
|
||||
case "System.Object":
|
||||
return typeof(object);
|
||||
default:
|
||||
return Type.GetType(typeString);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTypeString(Type type)
|
||||
{
|
||||
if (type == typeof(bool))
|
||||
return "bool";
|
||||
else if (type == typeof(byte))
|
||||
return "byte";
|
||||
else if (type == typeof(sbyte))
|
||||
return "sbyte";
|
||||
else if (type == typeof(char))
|
||||
return "char";
|
||||
else if (type == typeof(decimal))
|
||||
return "decimal";
|
||||
else if (type == typeof(double))
|
||||
return "double";
|
||||
else if (type == typeof(float))
|
||||
return "float";
|
||||
else if (type == typeof(int))
|
||||
return "int";
|
||||
else if (type == typeof(uint))
|
||||
return "uint";
|
||||
else if (type == typeof(long))
|
||||
return "long";
|
||||
else if (type == typeof(ulong))
|
||||
return "ulong";
|
||||
else if (type == typeof(short))
|
||||
return "short";
|
||||
else if (type == typeof(ushort))
|
||||
return "ushort";
|
||||
else if (type == typeof(string))
|
||||
return "string";
|
||||
else if (type == typeof(Vector2))
|
||||
return "Vector2";
|
||||
else if (type == typeof(Vector3))
|
||||
return "Vector3";
|
||||
else if (type == typeof(Vector4))
|
||||
return "Vector4";
|
||||
else if (type == typeof(Color))
|
||||
return "Color";
|
||||
else if (type == typeof(Transform))
|
||||
return "Transform";
|
||||
else if (type == typeof(UnityEngine.Component))
|
||||
return "Component";
|
||||
else if (type == typeof(GameObject))
|
||||
return "GameObject";
|
||||
else if (type == typeof(MeshFilter))
|
||||
return "MeshFilter";
|
||||
else if (type == typeof(Material))
|
||||
return "Material";
|
||||
else if (type == typeof(Texture2D))
|
||||
return "Texture2D";
|
||||
else if (type == typeof(UnityEngine.Object))
|
||||
return "UnityEngine.Object";
|
||||
else if (type == typeof(object))
|
||||
return "System.Object";
|
||||
else
|
||||
return GetShortAssemblyQualifiedName(type);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allows us to use FieldInfo and PropertyInfo interchangably.
|
||||
*/
|
||||
public struct ES3ReflectedMember
|
||||
{
|
||||
// The FieldInfo or PropertyInfo for this field.
|
||||
private FieldInfo fieldInfo;
|
||||
private PropertyInfo propertyInfo;
|
||||
public bool isProperty;
|
||||
|
||||
public bool IsNull { get { return fieldInfo == null && propertyInfo == null; } }
|
||||
public string Name { get { return (isProperty ? propertyInfo.Name : fieldInfo.Name); } }
|
||||
public Type MemberType { get { return (isProperty ? propertyInfo.PropertyType : fieldInfo.FieldType); } }
|
||||
public bool IsPublic { get { return (isProperty ? (propertyInfo.GetGetMethod(true).IsPublic && propertyInfo.GetSetMethod(true).IsPublic) : fieldInfo.IsPublic); } }
|
||||
public bool IsProtected { get { return (isProperty ? (propertyInfo.GetGetMethod(true).IsFamily) : fieldInfo.IsFamily); } }
|
||||
public bool IsStatic { get { return (isProperty ? (propertyInfo.GetGetMethod(true).IsStatic) : fieldInfo.IsStatic); } }
|
||||
|
||||
public ES3ReflectedMember(System.Object fieldPropertyInfo)
|
||||
{
|
||||
if (fieldPropertyInfo == null)
|
||||
{
|
||||
this.propertyInfo = null;
|
||||
this.fieldInfo = null;
|
||||
isProperty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
isProperty = ES3Reflection.IsAssignableFrom(typeof(PropertyInfo), fieldPropertyInfo.GetType());
|
||||
if (isProperty)
|
||||
{
|
||||
this.propertyInfo = (PropertyInfo)fieldPropertyInfo;
|
||||
this.fieldInfo = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.fieldInfo = (FieldInfo)fieldPropertyInfo;
|
||||
this.propertyInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValue(System.Object obj, System.Object value)
|
||||
{
|
||||
if (isProperty)
|
||||
propertyInfo.SetValue(obj, value, null);
|
||||
else
|
||||
fieldInfo.SetValue(obj, value);
|
||||
}
|
||||
|
||||
public System.Object GetValue(System.Object obj)
|
||||
{
|
||||
if (isProperty)
|
||||
return propertyInfo.GetValue(obj, null);
|
||||
else
|
||||
return fieldInfo.GetValue(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public class ES3ReflectedMethod
|
||||
{
|
||||
private MethodInfo method;
|
||||
|
||||
public ES3ReflectedMethod(Type type, string methodName, Type[] genericParameters, Type[] parameterTypes)
|
||||
{
|
||||
MethodInfo nonGenericMethod = type.GetMethod(methodName, parameterTypes);
|
||||
this.method = nonGenericMethod.MakeGenericMethod(genericParameters);
|
||||
}
|
||||
|
||||
public ES3ReflectedMethod(Type type, string methodName, Type[] genericParameters, Type[] parameterTypes, BindingFlags bindingAttr)
|
||||
{
|
||||
MethodInfo nonGenericMethod = type.GetMethod(methodName, bindingAttr, null, parameterTypes, null);
|
||||
this.method = nonGenericMethod.MakeGenericMethod(genericParameters);
|
||||
}
|
||||
|
||||
public object Invoke(object obj, object[] parameters = null)
|
||||
{
|
||||
return method.Invoke(obj, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 499c212fb9e3c410dacca179f55ba150
|
||||
timeCreated: 1499764821
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
namespace ES3Internal
|
||||
{
|
||||
[System.Serializable]
|
||||
public abstract class ES3SerializableDictionary<TKey,TVal> : Dictionary<TKey,TVal>, ISerializationCallbackReceiver
|
||||
{
|
||||
[SerializeField]
|
||||
private List<TKey> _Keys;
|
||||
[SerializeField]
|
||||
private List<TVal> _Values;
|
||||
|
||||
protected abstract bool KeysAreEqual(TKey a, TKey b);
|
||||
protected abstract bool ValuesAreEqual(TVal a, TVal b);
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
_Keys = new List<TKey>();
|
||||
_Values = new List<TVal>();
|
||||
foreach(KeyValuePair<TKey, TVal> pair in this)
|
||||
{
|
||||
try
|
||||
{
|
||||
_Keys.Add(pair.Key);
|
||||
_Values.Add(pair.Value);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// load dictionary from lists
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
// There are some situations where Unity will not get the serialized data correctly, returning null.
|
||||
// In this case we don't want to change anything, otherwise we'll lose the data entirely.
|
||||
if (_Keys == null || _Values == null)
|
||||
return;
|
||||
|
||||
if(_Keys.Count != _Values.Count)
|
||||
throw new System.Exception(string.Format("Key count is different to value count after deserialising dictionary."));
|
||||
|
||||
this.Clear();
|
||||
|
||||
for (int i = 0; i < _Keys.Count; i++)
|
||||
{
|
||||
if (_Keys[i] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Add(_Keys[i], _Values[i]);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
_Keys = null;
|
||||
_Values = null;
|
||||
}
|
||||
|
||||
public int RemoveNullValues()
|
||||
{
|
||||
var nullKeys = this.Where(pair => pair.Value == null)
|
||||
.Select(pair => pair.Key)
|
||||
.ToList();
|
||||
foreach (var nullKey in nullKeys)
|
||||
Remove(nullKey);
|
||||
return nullKeys.Count;
|
||||
}
|
||||
|
||||
// Changes the key of a value without changing it's position in the underlying Lists.
|
||||
// Mainly used in the Editor where position might otherwise change while the user is editing it.
|
||||
// Returns true if a change was made.
|
||||
public bool ChangeKey(TKey oldKey, TKey newKey)
|
||||
{
|
||||
if(KeysAreEqual(oldKey, newKey))
|
||||
return false;
|
||||
|
||||
var val = this [oldKey];
|
||||
Remove(oldKey);
|
||||
this [newKey] = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 681896bd0089c4f7296b3ecbd899f44d
|
||||
timeCreated: 1519132287
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,280 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.IO;
|
||||
using ES3Internal;
|
||||
|
||||
public class ES3Spreadsheet
|
||||
{
|
||||
private int cols = 0;
|
||||
private int rows = 0;
|
||||
private Dictionary<Index, string> cells = new Dictionary<Index, string>();
|
||||
|
||||
private const string QUOTE = "\"";
|
||||
private const char QUOTE_CHAR = '"';
|
||||
private const char COMMA_CHAR = ',';
|
||||
private const char NEWLINE_CHAR = '\n';
|
||||
private const string ESCAPED_QUOTE = "\"\"";
|
||||
private static char[] CHARS_TO_ESCAPE = { ',', '"', '\n', ' ' };
|
||||
|
||||
public int ColumnCount
|
||||
{
|
||||
get{ return cols; }
|
||||
}
|
||||
|
||||
public int RowCount
|
||||
{
|
||||
get{ return rows; }
|
||||
}
|
||||
|
||||
public void SetCell<T>(int col, int row, T value)
|
||||
{
|
||||
// If we're writing a string, add it without formatting.
|
||||
if (value.GetType() == typeof(string))
|
||||
{
|
||||
SetCellString(col, row, (string)(object)value);
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = new ES3Settings ();
|
||||
using(var ms = new MemoryStream())
|
||||
{
|
||||
using (var jsonWriter = new ES3JSONWriter (ms, settings, false, false))
|
||||
jsonWriter.Write(value, ES3.ReferenceMode.ByValue);
|
||||
|
||||
SetCellString(col, row, settings.encoding.GetString(ms.ToArray()));
|
||||
}
|
||||
|
||||
// Expand the spreadsheet if necessary.
|
||||
if(col >= cols)
|
||||
cols = (col+1);
|
||||
if(row >= rows)
|
||||
rows = (row+1);
|
||||
}
|
||||
|
||||
private void SetCellString(int col, int row, string value)
|
||||
{
|
||||
cells [new Index (col, row)] = value;
|
||||
|
||||
// Expand the spreadsheet if necessary.
|
||||
if(col >= cols)
|
||||
cols = (col+1);
|
||||
if (row >= rows)
|
||||
rows = (row + 1);
|
||||
}
|
||||
|
||||
|
||||
// Don't create non-generic version of this. Generic parameter is necessary as no type data is stored in the CSV file.
|
||||
public T GetCell<T>(int col, int row)
|
||||
{
|
||||
var val = GetCell(typeof(T), col, row);
|
||||
|
||||
if (val == null)
|
||||
return default(T);
|
||||
return (T)val;
|
||||
}
|
||||
|
||||
internal object GetCell(System.Type type, int col, int row)
|
||||
{
|
||||
string value;
|
||||
|
||||
if (col >= cols || row >= rows)
|
||||
throw new System.IndexOutOfRangeException("Cell (" + col + ", " + row + ") is out of bounds of spreadsheet (" + cols + ", " + rows + ").");
|
||||
|
||||
if (!cells.TryGetValue(new Index(col, row), out value) || string.IsNullOrEmpty(value))
|
||||
return null;
|
||||
|
||||
// If we're loading a string, simply return the string value.
|
||||
if (type == typeof(string))
|
||||
{
|
||||
var str = (object)value;
|
||||
return str;
|
||||
}
|
||||
|
||||
var settings = new ES3Settings();
|
||||
using (var ms = new MemoryStream(settings.encoding.GetBytes(value)))
|
||||
{
|
||||
using (var jsonReader = new ES3JSONReader(ms, settings, false))
|
||||
{
|
||||
var obj = ES3TypeMgr.GetOrCreateES3Type(type, true).Read<object>(jsonReader);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Load(string filePath)
|
||||
{
|
||||
Load(new ES3Settings (filePath));
|
||||
}
|
||||
|
||||
public void Load(string filePath, ES3Settings settings)
|
||||
{
|
||||
Load(new ES3Settings (filePath, settings));
|
||||
}
|
||||
|
||||
public void Load(ES3Settings settings)
|
||||
{
|
||||
Load(ES3Stream.CreateStream(settings, ES3FileMode.Read), settings);
|
||||
}
|
||||
|
||||
public void LoadRaw(string str)
|
||||
{
|
||||
Load(new MemoryStream (((new ES3Settings ()).encoding).GetBytes(str)), new ES3Settings());
|
||||
}
|
||||
|
||||
public void LoadRaw(string str, ES3Settings settings)
|
||||
{
|
||||
Load(new MemoryStream ((settings.encoding).GetBytes(str)), settings);
|
||||
}
|
||||
|
||||
private void Load(Stream stream, ES3Settings settings)
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
int c_int;
|
||||
char c;
|
||||
string value = "";
|
||||
int col = 0;
|
||||
int row = 0;
|
||||
|
||||
// Read until the end of the stream.
|
||||
while(true)
|
||||
{
|
||||
c_int = reader.Read();
|
||||
c = (char)c_int;
|
||||
if(c == QUOTE_CHAR)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
c = (char)reader.Read();
|
||||
|
||||
if(c == QUOTE_CHAR)
|
||||
{
|
||||
// If this quote isn't escaped by another, it is the last quote, so we should stop parsing this value.
|
||||
if(((char)reader.Peek()) != QUOTE_CHAR)
|
||||
break;
|
||||
else
|
||||
c = (char)reader.Read();
|
||||
}
|
||||
value += c;
|
||||
}
|
||||
}
|
||||
// If this is the end of a column, row, or the stream, add the value to the spreadsheet.
|
||||
else if(c == COMMA_CHAR || c == NEWLINE_CHAR || c_int == -1)
|
||||
{
|
||||
SetCell(col, row, value);
|
||||
value = "";
|
||||
if(c == COMMA_CHAR)
|
||||
col++;
|
||||
else if(c == NEWLINE_CHAR)
|
||||
{
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
value += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(string filePath)
|
||||
{
|
||||
Save(new ES3Settings (filePath), false);
|
||||
}
|
||||
|
||||
public void Save(string filePath, ES3Settings settings)
|
||||
{
|
||||
Save(new ES3Settings (filePath, settings), false);
|
||||
}
|
||||
|
||||
public void Save(ES3Settings settings)
|
||||
{
|
||||
Save(settings, false);
|
||||
}
|
||||
|
||||
public void Save(string filePath, bool append)
|
||||
{
|
||||
Save(new ES3Settings (filePath), append);
|
||||
}
|
||||
|
||||
public void Save(string filePath, ES3Settings settings, bool append)
|
||||
{
|
||||
Save(new ES3Settings (filePath, settings), append);
|
||||
}
|
||||
|
||||
public void Save(ES3Settings settings, bool append)
|
||||
{
|
||||
using (var writer = new StreamWriter(ES3Stream.CreateStream(settings, append ? ES3FileMode.Append : ES3FileMode.Write)))
|
||||
{
|
||||
// If data already exists and we're appending, we need to prepend a newline.
|
||||
if(append && ES3.FileExists(settings))
|
||||
writer.Write(NEWLINE_CHAR);
|
||||
|
||||
var array = ToArray();
|
||||
for(int row = 0; row < rows; row++)
|
||||
{
|
||||
if(row != 0)
|
||||
writer.Write(NEWLINE_CHAR);
|
||||
|
||||
for(int col = 0; col < cols; col++)
|
||||
{
|
||||
if(col != 0)
|
||||
writer.Write(COMMA_CHAR);
|
||||
|
||||
writer.Write( Escape(array [col, row]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!append)
|
||||
ES3IO.CommitBackup(settings);
|
||||
}
|
||||
|
||||
private static string Escape(string str, bool isAlreadyWrappedInQuotes=false)
|
||||
{
|
||||
if(string.IsNullOrEmpty(str))
|
||||
return null;
|
||||
|
||||
// Now escape any other quotes.
|
||||
if(str.Contains(QUOTE))
|
||||
str = str.Replace(QUOTE, ESCAPED_QUOTE);
|
||||
|
||||
// If there's chars to escape, wrap the value in quotes.
|
||||
if(str.IndexOfAny(CHARS_TO_ESCAPE) > -1)
|
||||
str = QUOTE + str + QUOTE;
|
||||
return str;
|
||||
}
|
||||
|
||||
private static string Unescape(string str)
|
||||
{
|
||||
if(str.StartsWith(QUOTE) && str.EndsWith(QUOTE))
|
||||
{
|
||||
str = str.Substring(1, str.Length-2);
|
||||
if(str.Contains(ESCAPED_QUOTE))
|
||||
str = str.Replace(ESCAPED_QUOTE, QUOTE);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private string[,] ToArray()
|
||||
{
|
||||
var array = new string[cols, rows];
|
||||
foreach (var cell in cells)
|
||||
array [cell.Key.col, cell.Key.row] = cell.Value;
|
||||
return array;
|
||||
}
|
||||
|
||||
protected struct Index
|
||||
{
|
||||
public int col;
|
||||
public int row;
|
||||
|
||||
public Index(int col, int row)
|
||||
{
|
||||
this.col = col;
|
||||
this.row = row;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bb1f812633929432dabb61bb8de267ba
|
||||
timeCreated: 1508838134
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue