dx
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainAboutWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("Window/Infinity Code/Real World Terrain/About", false, 2000)]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
RealWorldTerrainAboutWindow window = GetWindow<RealWorldTerrainAboutWindow>(true, "About", true);
|
||||
window.minSize = new Vector2(200, 100);
|
||||
window.maxSize = new Vector2(200, 100);
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
GUIStyle titleStyle = new GUIStyle(EditorStyles.boldLabel);
|
||||
titleStyle.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
GUIStyle textStyle = new GUIStyle(EditorStyles.label);
|
||||
textStyle.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
GUILayout.Label("Real World Terrain", titleStyle);
|
||||
GUILayout.Label("version " + RealWorldTerrainWindow.version, textStyle);
|
||||
GUILayout.Label("created Infinity Code", textStyle);
|
||||
GUILayout.Label("2013-" + DateTime.Now.Year, textStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c49762c2dfe9bc945b29081dac646717
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,133 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainBuildRPresetsWindow : EditorWindow
|
||||
{
|
||||
public static string[] buildrGeneratorStyles;
|
||||
public static string[] buildrGeneratorTexturePacks;
|
||||
|
||||
private static RealWorldTerrainBuildRPresetsWindow wnd;
|
||||
|
||||
public static List<RealWorldTerrainBuildRPresetsItem> presets;
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private static RealWorldTerrainPrefs prefs
|
||||
{
|
||||
get { return RealWorldTerrainWindow.prefs; }
|
||||
}
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
wnd = GetWindow<RealWorldTerrainBuildRPresetsWindow>("BuildR Presets");
|
||||
if (prefs.customBuildRPresets != null) presets = prefs.customBuildRPresets.ToList();
|
||||
else presets = new List<RealWorldTerrainBuildRPresetsItem>();
|
||||
}
|
||||
|
||||
private static List<string> GetBuildRXML(string datatype)
|
||||
{
|
||||
const string xmlPath = "Assets/Buildr/XML/";
|
||||
string[] paths = Directory.GetFiles(xmlPath);
|
||||
List<string> filelist = new List<string>();
|
||||
|
||||
foreach (string path in paths)
|
||||
{
|
||||
if (path.Contains(".meta")) continue;
|
||||
if (!path.Contains(".xml")) continue;
|
||||
|
||||
XmlDocument xml = new XmlDocument();
|
||||
xml.Load(path);
|
||||
XmlNodeList xmlData = xml.SelectNodes("data/datatype");
|
||||
|
||||
if (xmlData != null && xmlData.Count > 0 && xmlData[0].FirstChild.Value == datatype) filelist.Add(path.Substring(xmlPath.Length));
|
||||
}
|
||||
|
||||
return filelist;
|
||||
}
|
||||
|
||||
private static string OnBuildRPreset(string val, string title)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
val = EditorGUILayout.TextField(title, val);
|
||||
if (GUILayout.Button("...", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
string v1 = EditorUtility.OpenFilePanel(title, Application.dataPath, "xml");
|
||||
if (!string.IsNullOrEmpty(v1)) val = v1;
|
||||
}
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false))) val = "";
|
||||
GUILayout.EndHorizontal();
|
||||
return val;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
prefs.customBuildRPresets = presets.ToArray();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (buildrGeneratorStyles == null)
|
||||
{
|
||||
List<string> generatorStyles = GetBuildRXML("ProGen");
|
||||
buildrGeneratorStyles = generatorStyles.ToArray();
|
||||
prefs.customBuildRGeneratorStyle = generatorStyles.IndexOf("none.xml");
|
||||
}
|
||||
if (buildrGeneratorTexturePacks == null)
|
||||
{
|
||||
List<string> generatorTexturePacks = GetBuildRXML("TexturePack");
|
||||
buildrGeneratorTexturePacks = generatorTexturePacks.ToArray();
|
||||
prefs.customBuildRGeneratorTexturePack = generatorTexturePacks.IndexOf("alltextures.xml");
|
||||
}
|
||||
|
||||
prefs.customBuildRGeneratorStyle = EditorGUILayout.Popup("Style: ", prefs.customBuildRGeneratorStyle, buildrGeneratorStyles);
|
||||
prefs.customBuildRGeneratorTexturePack = EditorGUILayout.Popup("Texture Pack: ", prefs.customBuildRGeneratorTexturePack, buildrGeneratorTexturePacks);
|
||||
|
||||
if (presets == null)
|
||||
{
|
||||
if (prefs.customBuildRPresets != null) presets = prefs.customBuildRPresets.ToList();
|
||||
else presets = new List<RealWorldTerrainBuildRPresetsItem>();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Add preset") || presets.Count == 0) presets.Add(new RealWorldTerrainBuildRPresetsItem());
|
||||
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
for (int i = 0; i < presets.Count; i++)
|
||||
{
|
||||
RealWorldTerrainBuildRPresetsItem preset = presets[i];
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
GUILayout.Label((i + 1).ToString(), GUILayout.ExpandWidth(false));
|
||||
|
||||
GUILayout.BeginVertical();
|
||||
|
||||
preset.facade = OnBuildRPreset(preset.facade, "Facade presets:");
|
||||
preset.roof = OnBuildRPreset(preset.roof, "Roof presets:");
|
||||
preset.texture = OnBuildRPreset(preset.texture, "Texture presets:");
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) presets[i] = null;
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
presets.RemoveAll(p => p == null);
|
||||
|
||||
if (GUILayout.Button("Close"))
|
||||
{
|
||||
wnd.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 905b52232d8632b46bc77031daf0ba82
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,163 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainClearCacheWindow : EditorWindow
|
||||
{
|
||||
private long elevationSize;
|
||||
private long osmSize;
|
||||
private long textureSize;
|
||||
|
||||
private void ClearElevationCache()
|
||||
{
|
||||
RealWorldTerrainFileSystem.SafeDeleteDirectory(RealWorldTerrainEditorUtils.heightmapCacheFolder);
|
||||
elevationSize = 0;
|
||||
}
|
||||
|
||||
private void ClearHistory()
|
||||
{
|
||||
RealWorldTerrainFileSystem.SafeDeleteDirectory(RealWorldTerrainEditorUtils.historyCacheFolder);
|
||||
RealWorldTerrainHistoryWindow.Load();
|
||||
}
|
||||
|
||||
private void ClearOSMCache()
|
||||
{
|
||||
RealWorldTerrainFileSystem.SafeDeleteDirectory(RealWorldTerrainEditorUtils.osmCacheFolder);
|
||||
osmSize = 0;
|
||||
}
|
||||
|
||||
private static void ClearSettings()
|
||||
{
|
||||
if (File.Exists(RealWorldTerrainPrefs.prefsFilename)) File.Delete(RealWorldTerrainPrefs.prefsFilename);
|
||||
RealWorldTerrainSettingsWindow.ClearSettings();
|
||||
RealWorldTerrainEditorUtils.ClearFoldersCache();
|
||||
}
|
||||
|
||||
private void ClearTextureCache(bool errorOnly = false)
|
||||
{
|
||||
if (!errorOnly)
|
||||
{
|
||||
RealWorldTerrainFileSystem.SafeDeleteDirectory(RealWorldTerrainEditorUtils.textureCacheFolder);
|
||||
textureSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] files = Directory.GetFiles(RealWorldTerrainEditorUtils.textureCacheFolder, "*.err", SearchOption.AllDirectories);
|
||||
foreach (string file in files) RealWorldTerrainFileSystem.SafeDeleteFile(file);
|
||||
textureSize = RealWorldTerrainFileSystem.GetDirectorySize(RealWorldTerrainEditorUtils.textureCacheFolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
elevationSize = RealWorldTerrainFileSystem.GetDirectorySize(RealWorldTerrainEditorUtils.heightmapCacheFolder);
|
||||
osmSize = RealWorldTerrainFileSystem.GetDirectorySize(RealWorldTerrainEditorUtils.osmCacheFolder);
|
||||
textureSize = RealWorldTerrainFileSystem.GetDirectorySize(RealWorldTerrainEditorUtils.textureCacheFolder);
|
||||
}
|
||||
|
||||
public static string FormatSize(long size)
|
||||
{
|
||||
if (size > 10485760) return size / 1048576 + " MB";
|
||||
if (size > 1024) return (size / 1048576f).ToString("0.000") + " MB";
|
||||
return size + " B";
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("Elevations", FormatSize(elevationSize), EditorStyles.textField);
|
||||
if (GUILayout.Button("Open", GUILayout.ExpandWidth(false))) EditorUtility.RevealInFinder(RealWorldTerrainEditorUtils.heightmapCacheFolder);
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear cache", "Are you sure you want to clear the elevation cache?", "Yes", "No"))
|
||||
{
|
||||
ClearElevationCache();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("Textures", FormatSize(textureSize), EditorStyles.textField);
|
||||
if (GUILayout.Button("Open", GUILayout.ExpandWidth(false))) EditorUtility.RevealInFinder(RealWorldTerrainEditorUtils.textureCacheFolder);
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
int result = EditorUtility.DisplayDialogComplex("Clear cache", "Are you sure you want to clear the texture cache?", "Full", "No", "Errors only");
|
||||
if (result == 0)
|
||||
{
|
||||
ClearTextureCache();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
else if (result == 2)
|
||||
{
|
||||
ClearTextureCache(true);
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("OSM", FormatSize(osmSize), EditorStyles.textField);
|
||||
if (GUILayout.Button("Open", GUILayout.ExpandWidth(false))) EditorUtility.RevealInFinder(RealWorldTerrainEditorUtils.osmCacheFolder);
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear cache", "Are you sure you want to clear the OSM cache?", "Yes", "No"))
|
||||
{
|
||||
ClearOSMCache();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("History");
|
||||
if (GUILayout.Button("Open", GUILayout.ExpandWidth(false))) EditorUtility.RevealInFinder(RealWorldTerrainEditorUtils.historyCacheFolder);
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear cache", "Are you sure you want to clear the history?", "Yes", "No"))
|
||||
{
|
||||
ClearHistory();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("Settings");
|
||||
if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear cache", "Are you sure you want to clear the settings?", "Yes", "No"))
|
||||
{
|
||||
ClearSettings();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("Clear All"))
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Clear cache", "Are you sure you want to clear the cache?", "Yes", "No"))
|
||||
{
|
||||
ClearElevationCache();
|
||||
ClearTextureCache();
|
||||
ClearOSMCache();
|
||||
ClearHistory();
|
||||
ClearSettings();
|
||||
EditorUtility.DisplayDialog("Complete", "Clear cache complete.", "OK");
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
RealWorldTerrainClearCacheWindow wnd = GetWindow<RealWorldTerrainClearCacheWindow>(true, "Clear cache");
|
||||
DontDestroyOnLoad(wnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb5edb018da5f88499d42bf04f186ca2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,167 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainHistoryWindow: EditorWindow
|
||||
{
|
||||
private static List<RealWorldTerrainHistoryItem> recent;
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private static string historyPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(RealWorldTerrainEditorUtils.historyCacheFolder, "hystory.xml");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Add(RealWorldTerrainPrefs prefs)
|
||||
{
|
||||
string id = Guid.NewGuid().ToString();
|
||||
string path = Path.Combine(RealWorldTerrainEditorUtils.historyCacheFolder, id + ".xml");
|
||||
File.WriteAllText(path, prefs.ToXML(new XmlDocument()).OuterXml, Encoding.UTF8);
|
||||
|
||||
if (recent == null) Load();
|
||||
recent.Add(new RealWorldTerrainHistoryItem(prefs, id));
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
if (recent == null) recent = new List<RealWorldTerrainHistoryItem>();
|
||||
else recent.Clear();
|
||||
|
||||
if (!File.Exists(historyPath)) return;
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load(historyPath);
|
||||
|
||||
foreach (XmlNode node in doc.FirstChild.ChildNodes) recent.Add(new RealWorldTerrainHistoryItem(node));
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
if (recent == null) Load();
|
||||
|
||||
GUIStyle headerStyle = new GUIStyle(EditorStyles.label);
|
||||
headerStyle.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
GUILayout.Label("№", headerStyle, GUILayout.Width(40));
|
||||
GUILayout.Label("Title", headerStyle);
|
||||
GUILayout.Label("Time", headerStyle, GUILayout.Width(120));
|
||||
GUILayout.Box("", GUIStyle.none, GUILayout.Width(50));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
GUIContent useContent = new GUIContent(">", "Restore");
|
||||
GUIContent deleteContent = new GUIContent("X", "Remove");
|
||||
|
||||
int removeIndex = -1;
|
||||
int index = 1;
|
||||
for (int i = recent.Count - 1; i >= 0; i--)
|
||||
{
|
||||
RealWorldTerrainHistoryItem item = recent[i];
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label(index.ToString(), GUILayout.Width(40));
|
||||
GUILayout.Label(item.title);
|
||||
|
||||
DateTime time = new DateTime(item.timestamp);
|
||||
|
||||
GUILayout.Label(time.ToString("yyyy-MM-dd HH:mm"), GUILayout.Width(120));
|
||||
|
||||
if (GUILayout.Button(useContent, GUILayout.Width(20)))
|
||||
{
|
||||
if (RealWorldTerrainWindow.wnd != null) RealWorldTerrainWindow.wnd.Close();
|
||||
|
||||
RealWorldTerrainWindow.OpenWindow(RealWorldTerrainGenerateType.full);
|
||||
RealWorldTerrainWindow.prefs.LoadFromXML(Path.Combine(RealWorldTerrainEditorUtils.historyCacheFolder, item.id + ".xml"));
|
||||
}
|
||||
|
||||
if (GUILayout.Button(deleteContent, GUILayout.Width(20))) removeIndex = i;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
index++;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
if (GUILayout.Button("Close")) Close();
|
||||
|
||||
if (removeIndex != -1)
|
||||
{
|
||||
RealWorldTerrainHistoryItem item = recent[removeIndex];
|
||||
string filaname = Path.Combine(RealWorldTerrainEditorUtils.historyCacheFolder, item.id + ".xml");
|
||||
if (File.Exists(filaname)) File.Delete(filaname);
|
||||
recent.RemoveAt(removeIndex);
|
||||
Save();
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Save()
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
XmlNode node = doc.CreateElement("History");
|
||||
doc.AppendChild(node);
|
||||
foreach (RealWorldTerrainHistoryItem item in recent) item.Save(node);
|
||||
File.WriteAllText(historyPath, doc.OuterXml, Encoding.UTF8);
|
||||
}
|
||||
|
||||
[MenuItem("Window/Infinity Code/Real World Terrain/History")]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainHistoryWindow>(true, "History");
|
||||
}
|
||||
}
|
||||
|
||||
public class RealWorldTerrainHistoryItem
|
||||
{
|
||||
public string title;
|
||||
public string id;
|
||||
public long timestamp;
|
||||
|
||||
public RealWorldTerrainHistoryItem(RealWorldTerrainPrefs prefs, string id)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(prefs.title)) title = prefs.title;
|
||||
else title = "(" + prefs.topLatitude + ", " + prefs.leftLongitude + ") - (" + prefs.bottomLatitude + ", " + prefs.rightLongitude + ")";
|
||||
|
||||
this.id = id;
|
||||
timestamp = DateTime.Now.Ticks;
|
||||
}
|
||||
|
||||
public RealWorldTerrainHistoryItem(XmlNode node)
|
||||
{
|
||||
title = node["Title"].InnerText.Trim();
|
||||
id = node["ID"].InnerText;
|
||||
timestamp = long.Parse(node["Timestamp"].InnerText);
|
||||
}
|
||||
|
||||
public void Save(XmlNode node)
|
||||
{
|
||||
XmlDocument doc = node.OwnerDocument;
|
||||
XmlElement itemNode = doc.CreateElement("Item");
|
||||
XmlElement titleNode = doc.CreateElement("Title");
|
||||
XmlElement idNode = doc.CreateElement("ID");
|
||||
XmlElement timestampNode = doc.CreateElement("Timestamp");
|
||||
|
||||
titleNode.AppendChild(doc.CreateCDataSection(title));
|
||||
idNode.AppendChild(doc.CreateTextNode(id));
|
||||
timestampNode.AppendChild(doc.CreateTextNode(timestamp.ToString()));
|
||||
|
||||
itemNode.AppendChild(titleNode);
|
||||
itemNode.AppendChild(idNode);
|
||||
itemNode.AppendChild(timestampNode);
|
||||
node.AppendChild(itemNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d96879a74ae6564dacf5ea4e9b73c30
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainInfoWindow : EditorWindow
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private const float mb = 1048576;
|
||||
|
||||
private static RealWorldTerrainInfoWindow instance;
|
||||
|
||||
private MemoryUsage memoryUsage = new MemoryUsage();
|
||||
private DownloadInfo downloadInfo = new DownloadInfo();
|
||||
|
||||
private int selectedTool = 0;
|
||||
|
||||
private bool CalculateUsage()
|
||||
{
|
||||
RealWorldTerrainPrefs p = RealWorldTerrainWindow.prefs;
|
||||
if (p == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Can not find the prefs. Open Real World Terrain window.", "OK");
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedTool == 0) downloadInfo.Calculate(p);
|
||||
else if (selectedTool == 1) memoryUsage.Calculate(p);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void DrawField(string prefix, string value)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(prefix, GUILayout.MaxWidth(instance.position.size.x / 2 - 10));
|
||||
EditorGUILayout.LabelField(value, GUILayout.MaxWidth(instance.position.size.x / 2 - 10));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
instance = this;
|
||||
CalculateUsage();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
//selectedTool = GUILayout.Toolbar(selectedTool, new[] {"Download", "Result"});
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (!CalculateUsage()) return;
|
||||
scrollPosition = Vector2.zero;
|
||||
}
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
/*if (selectedTool == 0) downloadInfo.Draw();
|
||||
else if (selectedTool == 1)*/ memoryUsage.Draw();
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
if (GUILayout.Button("Refresh")) CalculateUsage();
|
||||
}
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainInfoWindow>(true, "Area Info", true);
|
||||
}
|
||||
|
||||
internal class DownloadInfo
|
||||
{
|
||||
private int heightmapRequests;
|
||||
private int texturesRequests;
|
||||
private int osmRequests;
|
||||
private int totalRequests;
|
||||
|
||||
public void Calculate(RealWorldTerrainPrefs p)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class MemoryUsage
|
||||
{
|
||||
private long heightmap;
|
||||
private long controltexture;
|
||||
private long detailmap;
|
||||
private int countGrass;
|
||||
private long basemap;
|
||||
private long texture;
|
||||
private long totalPerTerrain;
|
||||
private RealWorldTerrainVector2i countTerrains;
|
||||
private long total;
|
||||
|
||||
private string heightmapS;
|
||||
|
||||
private string controltextureS;
|
||||
private string detailmapS;
|
||||
private string basemapS;
|
||||
private string textureS;
|
||||
private string totalPerTerrainS;
|
||||
private string totalS;
|
||||
private string countTerrainsS;
|
||||
|
||||
|
||||
public void Calculate(RealWorldTerrainPrefs p)
|
||||
{
|
||||
heightmap = p.heightmapResolution * p.heightmapResolution * 4;
|
||||
controltexture = p.controlTextureResolution * p.controlTextureResolution * 4;
|
||||
detailmap = p.detailResolution * p.detailResolution * 4;
|
||||
countGrass = p.generateGrass ? p.grassPrefabs.Count : 0;
|
||||
basemap = p.baseMapResolution * p.baseMapResolution * 4;
|
||||
texture = 0;
|
||||
if (p.generateTextures)
|
||||
{
|
||||
if (p.textureResultType == RealWorldTerrainTextureResultType.regularTexture) texture = p.textureSize.x * p.textureSize.y * 4;
|
||||
else if (p.textureResultType == RealWorldTerrainTextureResultType.hugeTexture) texture = p.hugeTexturePageSize * p.hugeTexturePageSize * p.hugeTextureCols * p.hugeTextureRows * 3;
|
||||
}
|
||||
totalPerTerrain = heightmap + countTerrains + detailmap * countGrass + basemap + texture;
|
||||
countTerrains = p.terrainCount;
|
||||
total = totalPerTerrain * countTerrains.count;
|
||||
|
||||
string format = "{0:### ##0.00}";
|
||||
heightmapS = string.Format(format, heightmap / mb) + " mb";
|
||||
controltextureS = string.Format(format, controltexture / mb) + " mb";
|
||||
detailmapS = string.Format(format, detailmap * countGrass / mb) + " mb";
|
||||
basemapS = string.Format(format, basemap / mb) + " mb";
|
||||
textureS = string.Format(format, texture / mb) + " mb";
|
||||
totalPerTerrainS = string.Format(format, totalPerTerrain / mb) + " mb";
|
||||
countTerrainsS = countTerrains.count + " (" + countTerrains.x + "x" + countTerrains.y + ")";
|
||||
totalS = string.Format(format, total / mb) + " mb";
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
EditorGUILayout.HelpBox("Uncompressed size of the result by the fields.\nHere only the main fields affecting the size are shown.\nNote that the memory that RWT will use for generation is not shown here.", MessageType.Info);
|
||||
|
||||
DrawField("Height Map:", heightmapS);
|
||||
DrawField("Control Texture:", controltextureS);
|
||||
DrawField("Detail Map: ", detailmapS);
|
||||
DrawField("Base Map: ", basemapS);
|
||||
DrawField("Textures: ", textureS);
|
||||
EditorGUILayout.Space();
|
||||
DrawField("Total Per Terrain: ", totalPerTerrainS);
|
||||
EditorGUILayout.LabelField("---");
|
||||
DrawField("Count Terrains: ", countTerrainsS);
|
||||
DrawField("Total: ", totalS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7661126f067dcc24abc2b041b0d1c041
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,116 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainMemoryUsageWindow : EditorWindow
|
||||
{
|
||||
private Vector2 scrollPosition;
|
||||
|
||||
private float mb = 1048576;
|
||||
|
||||
private long heightmap;
|
||||
private long controltexture;
|
||||
private long detailmap;
|
||||
private int countGrass;
|
||||
private long basemap;
|
||||
private long texture;
|
||||
private long totalPerTerrain;
|
||||
private RealWorldTerrainVector2i countTerrains;
|
||||
private long total;
|
||||
|
||||
private string heightmapS;
|
||||
|
||||
|
||||
private string controltextureS;
|
||||
private string detailmapS;
|
||||
private string basemapS;
|
||||
private string textureS;
|
||||
private string totalPerTerrainS;
|
||||
private string totalS;
|
||||
private string countTerrainsS;
|
||||
|
||||
private void CalculateUsage()
|
||||
{
|
||||
RealWorldTerrainPrefs p = RealWorldTerrainWindow.prefs;
|
||||
if (p == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Can not find the prefs. Open Real World Terrain window.", "OK");
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
heightmap = p.heightmapResolution * p.heightmapResolution * 4;
|
||||
controltexture = p.controlTextureResolution * p.controlTextureResolution * 4;
|
||||
detailmap = p.detailResolution * p.detailResolution * 4;
|
||||
countGrass = p.generateGrass ? p.grassPrefabs.Count : 0;
|
||||
basemap = p.baseMapResolution * p.baseMapResolution * 4;
|
||||
texture = 0;
|
||||
if (p.generateTextures)
|
||||
{
|
||||
if (p.textureResultType == RealWorldTerrainTextureResultType.regularTexture) texture = p.textureSize.x * p.textureSize.y * 4;
|
||||
else if (p.textureResultType == RealWorldTerrainTextureResultType.hugeTexture) texture = p.hugeTexturePageSize * p.hugeTexturePageSize * p.hugeTextureCols * p.hugeTextureRows * 3;
|
||||
}
|
||||
totalPerTerrain = heightmap + countTerrains + detailmap * countGrass + basemap + texture;
|
||||
countTerrains = p.terrainCount;
|
||||
total = totalPerTerrain * countTerrains.count;
|
||||
|
||||
string format = "{0:### ##0.00}";
|
||||
heightmapS = String.Format(format, heightmap / mb) + " mb";
|
||||
controltextureS = String.Format(format, controltexture / mb) + " mb";
|
||||
detailmapS = String.Format(format, detailmap * countGrass / mb) + " mb";
|
||||
basemapS = String.Format(format, basemap / mb) + " mb";
|
||||
textureS = String.Format(format, texture / mb) + " mb";
|
||||
totalPerTerrainS = String.Format(format, totalPerTerrain / mb) + " mb";
|
||||
countTerrainsS = countTerrains.count + " (" + countTerrains.x + "x" + countTerrains.y + ")";
|
||||
totalS = String.Format(format, total / mb) + " mb";
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
CalculateUsage();
|
||||
}
|
||||
|
||||
private void DrawField(string prefix, string value)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(prefix, GUILayout.MaxWidth(position.size.x / 2 - 10));
|
||||
EditorGUILayout.LabelField(value, GUILayout.MaxWidth(position.size.x / 2 - 10));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
EditorGUILayout.HelpBox("Uncompressed size of the result by the fields.\nHere only the main fields affecting the size are shown.\nNote that the memory that RWT will use for generation is not shown here.", MessageType.Info);
|
||||
|
||||
DrawField("Height Map:", heightmapS);
|
||||
DrawField("Control Texture:", controltextureS);
|
||||
DrawField("Detail Map: ", detailmapS);
|
||||
DrawField("Base Map: ", basemapS);
|
||||
DrawField("Textures: ", textureS);
|
||||
EditorGUILayout.Space();
|
||||
DrawField("Total Per Terrain: ", totalPerTerrainS);
|
||||
EditorGUILayout.LabelField("---");
|
||||
DrawField("Count Terrains: ", countTerrainsS);
|
||||
DrawField("Total: ", totalS);
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
if (GUILayout.Button("Refresh"))
|
||||
{
|
||||
CalculateUsage();
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainMemoryUsageWindow>(true, "Memory Usage", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9376171e0d65a59409225ae4c95728ca
|
||||
timeCreated: 1539976693
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,116 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainSettingsGeneratorWindow : EditorWindow
|
||||
{
|
||||
private int heightmapQuality = 50;
|
||||
private int textureQuality = 50;
|
||||
private Vector2 scrollPosition;
|
||||
private bool generateGrass;
|
||||
private bool generateTexture = true;
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainSettingsGeneratorWindow>(false, "Settings generator");
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
RealWorldTerrainPrefs prefs = RealWorldTerrainWindow.prefs;
|
||||
|
||||
heightmapQuality = EditorGUILayout.IntSlider("Heightmap quality:", heightmapQuality, 1, 100);
|
||||
generateTexture = EditorGUILayout.Toggle("Generate texture:", generateTexture);
|
||||
if (generateTexture) textureQuality = EditorGUILayout.IntSlider("Texture quality:", textureQuality, 1, 100);
|
||||
generateGrass = EditorGUILayout.Toggle("Generate grass", generateGrass);
|
||||
|
||||
double rangeX = prefs.rightLongitude - prefs.leftLongitude;
|
||||
double rangeY = prefs.topLatitude - prefs.bottomLatitude;
|
||||
|
||||
double sizeX = 0;
|
||||
double sizeY = 0;
|
||||
|
||||
if (prefs.sizeType == 0)
|
||||
{
|
||||
double scfY = Math.Sin(prefs.topLatitude * Mathf.Deg2Rad);
|
||||
double sctY = Math.Sin(prefs.bottomLatitude * Mathf.Deg2Rad);
|
||||
double ccfY = Math.Cos(prefs.topLatitude * Mathf.Deg2Rad);
|
||||
double cctY = Math.Cos(prefs.bottomLatitude * Mathf.Deg2Rad);
|
||||
double cX = Math.Cos(rangeX * Mathf.Deg2Rad);
|
||||
double sizeX1 = Math.Abs(RealWorldTerrainGeo.EARTH_RADIUS * Math.Acos(scfY * scfY + ccfY * ccfY * cX));
|
||||
double sizeX2 = Math.Abs(RealWorldTerrainGeo.EARTH_RADIUS * Math.Acos(sctY * sctY + cctY * cctY * cX));
|
||||
sizeX = (sizeX1 + sizeX2) / 2.0;
|
||||
sizeY = RealWorldTerrainGeo.EARTH_RADIUS * Math.Acos(scfY * sctY + ccfY * cctY);
|
||||
}
|
||||
else if (prefs.sizeType == 1)
|
||||
{
|
||||
sizeX = Math.Abs(rangeX / 360 * RealWorldTerrainGeo.EQUATOR_LENGTH);
|
||||
sizeY = Math.Abs(rangeY / 360 * RealWorldTerrainGeo.EQUATOR_LENGTH);
|
||||
}
|
||||
|
||||
int hmX = (int)Math.Round(sizeX / 9 * heightmapQuality);
|
||||
int hmY = (int)Math.Round(sizeY / 9 * heightmapQuality);
|
||||
|
||||
int tsX = generateTexture ? (int)Math.Round(sizeX * 10 * textureQuality) : 0;
|
||||
int tsY = generateTexture ? (int)Math.Round(sizeY * 10 * textureQuality) : 0;
|
||||
|
||||
int countX = Mathf.Max(hmX / 4096 + 1, tsX / 4096 + 1);
|
||||
int countY = Mathf.Max(hmY / 4096 + 1, tsY / 4096 + 1);
|
||||
|
||||
if (countX > 10 || countY > 10)
|
||||
{
|
||||
GUIStyle style = new GUIStyle(GUI.skin.label);
|
||||
style.normal.textColor = Color.red;
|
||||
style.fontStyle = FontStyle.Bold;
|
||||
style.wordWrap = true;
|
||||
GUILayout.Label("Too high a settings. Memory overflow may occur.", style);
|
||||
}
|
||||
|
||||
int heightmapRes = Mathf.Max(hmX / countX, hmY / countY);
|
||||
heightmapRes = Mathf.Clamp(Mathf.NextPowerOfTwo(heightmapRes), 32, 4096);
|
||||
int detailRes = (generateGrass) ? heightmapRes : 32;
|
||||
int textureWidth = Mathf.Clamp(Mathf.NextPowerOfTwo(tsX / countX), 32, 4096);
|
||||
int textureHeight = Mathf.Clamp(Mathf.NextPowerOfTwo(tsY / countY), 32, 4096);
|
||||
int basemapRes = Mathf.Clamp(Mathf.NextPowerOfTwo(Mathf.Max(textureWidth, textureHeight) / 4), 32, 4096);
|
||||
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Label(string.Format("Area size X:{0} km, Y:{1} km", sizeX, sizeY));
|
||||
GUILayout.Space(10);
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
GUILayout.Label("Recommended settings:");
|
||||
GUILayout.Label(string.Format("Count terrains: {0}x{1}", countX, countY));
|
||||
GUILayout.Label("Heightmap resolution: " + heightmapRes);
|
||||
GUILayout.Label("Detail resolution: " + detailRes);
|
||||
GUILayout.Label("Basemap resolution: " + basemapRes);
|
||||
if (generateTexture) GUILayout.Label(string.Format("Texture size: {0}x{1}", textureWidth, textureHeight));
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
if (GUILayout.Button("Apply"))
|
||||
{
|
||||
prefs.terrainCount = new RealWorldTerrainVector2i(countX, countY);
|
||||
prefs.heightmapResolution = heightmapRes;
|
||||
prefs.detailResolution = detailRes;
|
||||
prefs.baseMapResolution = basemapRes;
|
||||
|
||||
if (generateTexture)
|
||||
{
|
||||
prefs.textureSize = new RealWorldTerrainVector2i(textureWidth, textureHeight);
|
||||
prefs.generateTextures = true;
|
||||
}
|
||||
else prefs.generateTextures = false;
|
||||
|
||||
if (RealWorldTerrainWindow.wnd != null) RealWorldTerrainWindow.wnd.Repaint();
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3e684d2dc6475a46a11a65c99e1e823
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,520 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainSettingsWindow : EditorWindow
|
||||
{
|
||||
private static RealWorldTerrainSettingsWindow wnd;
|
||||
|
||||
private string customCacheFolder;
|
||||
private bool defaultCacheFolder = true;
|
||||
private bool hasThirdPartyAssets;
|
||||
private string resultName = "RealWorld Terrain";
|
||||
private Vector2 scrollPosition = Vector2.zero;
|
||||
private bool showGeneral = true;
|
||||
private bool showCacheFolder = true;
|
||||
private bool showResultName = true;
|
||||
private bool showTerrainNames = true;
|
||||
private bool showTerrainTokens;
|
||||
private bool showThirdPartyAssets = false;
|
||||
private bool showResultTokens;
|
||||
private static Assembly assembly;
|
||||
private bool appendResultNameIndex = true;
|
||||
private string terrainName = "Terrain {x}x{y}";
|
||||
private bool generateInThread = true;
|
||||
private RealWorldTerrainOSMOverpassServer osmServer = RealWorldTerrainOSMOverpassServer.main;
|
||||
private bool hasBuildR2;
|
||||
private bool hasBuildR3;
|
||||
private bool hasEasyRoads;
|
||||
private bool hasProceduralToolkit;
|
||||
private bool hasRoadArchitect;
|
||||
private bool hasRTP;
|
||||
private bool hasVolumeGrass;
|
||||
private bool hasWorldStreamer;
|
||||
private bool hasRAM2019;
|
||||
|
||||
private static void AddCompilerDirective(string key)
|
||||
{
|
||||
BuildTargetGroup g = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
UnityEditor.Build.NamedBuildTarget buildTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(g);
|
||||
string currentDefinitions = PlayerSettings.GetScriptingDefineSymbols(buildTarget);
|
||||
#else
|
||||
string currentDefinitions = PlayerSettings.GetScriptingDefineSymbolsForGroup(g);
|
||||
#endif
|
||||
|
||||
string[] defs = currentDefinitions.Split(';').Select(d => d.Trim(' ')).ToArray();
|
||||
|
||||
if (defs.All(d => d != key))
|
||||
{
|
||||
ArrayUtility.Add(ref defs, key);
|
||||
currentDefinitions = string.Join(";", defs);
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
PlayerSettings.SetScriptingDefineSymbols(buildTarget, currentDefinitions);
|
||||
#else
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(g, currentDefinitions);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearSettings()
|
||||
{
|
||||
RealWorldTerrainPrefs.DeletePref("CacheFolder");
|
||||
RealWorldTerrainPrefs.DeletePref("ResultName");
|
||||
RealWorldTerrainPrefs.DeletePref("TerrainName");
|
||||
RealWorldTerrainPrefs.DeletePref("AppendIndex");
|
||||
RealWorldTerrainPrefs.DeletePref("GenerateInTread");
|
||||
RealWorldTerrainPrefs.DeletePref("OSMServer");
|
||||
|
||||
if (wnd != null) wnd.Repaint();
|
||||
}
|
||||
|
||||
private static void DeleteCompilerDirective(string key)
|
||||
{
|
||||
BuildTargetGroup g = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
UnityEditor.Build.NamedBuildTarget buildTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(g);
|
||||
string currentDefinitions = PlayerSettings.GetScriptingDefineSymbols(buildTarget);
|
||||
#else
|
||||
string currentDefinitions = PlayerSettings.GetScriptingDefineSymbolsForGroup(g);
|
||||
#endif
|
||||
|
||||
string[] defs = currentDefinitions.Split(';').Select(d => d.Trim(' ')).ToArray();
|
||||
|
||||
if (defs.Any(d => d == key))
|
||||
{
|
||||
ArrayUtility.Remove(ref defs, key);
|
||||
currentDefinitions = string.Join(";", defs);
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
PlayerSettings.SetScriptingDefineSymbols(buildTarget, currentDefinitions);
|
||||
#else
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(g, currentDefinitions);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawResultTokens()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showResultTokens = EditorGUILayout.Foldout(showResultTokens, "Available tokens");
|
||||
if (showResultTokens)
|
||||
{
|
||||
GUILayout.Label("{title} - Title");
|
||||
GUILayout.Label("{tllat} - Top-Left latitude");
|
||||
GUILayout.Label("{tllng} - Top-Left longitude");
|
||||
GUILayout.Label("{brlat} - Bottom-Right latitude");
|
||||
GUILayout.Label("{brlng} - Bottom-Right longitude");
|
||||
GUILayout.Label("{cx} - Count X");
|
||||
GUILayout.Label("{cy} - Count Y");
|
||||
GUILayout.Label("{st} - Size type");
|
||||
GUILayout.Label("{me} - Max elevation");
|
||||
GUILayout.Label("{mu} - Max underwater depth");
|
||||
GUILayout.Label("{ds} - Depth shrapness");
|
||||
GUILayout.Label("{dr} - Detail resolution");
|
||||
GUILayout.Label("{rpp} - Resolution per patch");
|
||||
GUILayout.Label("{bmr} - Base map resolution");
|
||||
GUILayout.Label("{hmr} - Height map resolution");
|
||||
GUILayout.Label("{tp} - Texture provider");
|
||||
GUILayout.Label("{tw} - Texture width");
|
||||
GUILayout.Label("{th} - Texture height");
|
||||
GUILayout.Label("{tml} - Texture max level");
|
||||
GUILayout.Label("{ticks} - Current time ticks");
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void DrawTerrainTokens()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showTerrainTokens = EditorGUILayout.Foldout(showTerrainTokens, "Available tokens");
|
||||
if (showTerrainTokens)
|
||||
{
|
||||
GUILayout.Label("{tllat} - Top-Left latitude");
|
||||
GUILayout.Label("{tllng} - Top-Left longitude");
|
||||
GUILayout.Label("{brlat} - Bottom-Right latitude");
|
||||
GUILayout.Label("{brlng} - Bottom-Right longitude");
|
||||
GUILayout.Label("{x} - X Index");
|
||||
GUILayout.Label("{y} - Y Index");
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static Type FindType(string className)
|
||||
{
|
||||
if (assembly == null) assembly = typeof(RealWorldTerrainSettingsWindow).Assembly;
|
||||
return assembly.GetType(className);
|
||||
}
|
||||
|
||||
private void OnCacheFolderGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showCacheFolder = EditorGUILayout.Foldout(showCacheFolder, "Cache folder:");
|
||||
if (showCacheFolder)
|
||||
{
|
||||
defaultCacheFolder = GUILayout.Toggle(defaultCacheFolder, "{PROJECT FOLDER}/RWT_Cache");
|
||||
defaultCacheFolder = !GUILayout.Toggle(!defaultCacheFolder, "Custom cache folder");
|
||||
|
||||
if (!defaultCacheFolder)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
customCacheFolder = EditorGUILayout.TextField("", customCacheFolder);
|
||||
GUI.SetNextControlName("BrowseButton");
|
||||
if (GUILayout.Button("Browse", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
GUI.FocusControl("BrowseButton");
|
||||
string newCustomFolder = EditorUtility.OpenFolderPanel("Select the folder for the cache.", EditorApplication.applicationPath, "");
|
||||
if (!string.IsNullOrEmpty(newCustomFolder)) customCacheFolder = newCustomFolder;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void OnBuildR2(ref bool dirty)
|
||||
{
|
||||
if (!hasBuildR2) return;
|
||||
|
||||
#if !BUILDR2
|
||||
if (GUILayout.Button("Enable BuildR2"))
|
||||
{
|
||||
AddCompilerDirective("BUILDR2");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable BuildR2"))
|
||||
{
|
||||
DeleteCompilerDirective("BUILDR2");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnBuildR3(ref bool dirty)
|
||||
{
|
||||
if (!hasBuildR3) return;
|
||||
|
||||
#if !BUILDR3
|
||||
if (GUILayout.Button("Enable BuildR3"))
|
||||
{
|
||||
AddCompilerDirective("BUILDR3");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable BuildR3"))
|
||||
{
|
||||
DeleteCompilerDirective("BUILDR3");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnEasyRoads(ref bool dirty)
|
||||
{
|
||||
if (!hasEasyRoads) return;
|
||||
|
||||
#if !EASYROADS3D
|
||||
if (GUILayout.Button("Enable EasyRoads3D v3"))
|
||||
{
|
||||
AddCompilerDirective("EASYROADS3D");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable EasyRoads3D v3"))
|
||||
{
|
||||
DeleteCompilerDirective("EASYROADS3D");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
wnd = null;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
wnd = this;
|
||||
customCacheFolder = RealWorldTerrainPrefs.LoadPref("CacheFolder", "");
|
||||
defaultCacheFolder = customCacheFolder == "";
|
||||
resultName = RealWorldTerrainPrefs.LoadPref("ResultName", "RealWorld Terrain");
|
||||
terrainName = RealWorldTerrainPrefs.LoadPref("TerrainName", "Terrain {x}x{y}");
|
||||
appendResultNameIndex = RealWorldTerrainPrefs.LoadPref("AppendIndex", true);
|
||||
generateInThread = RealWorldTerrainPrefs.LoadPref("GenerateInThread", true);
|
||||
osmServer = (RealWorldTerrainOSMOverpassServer)RealWorldTerrainPrefs.LoadPref("OSMServer", 0);
|
||||
|
||||
hasBuildR2 = FindType("BuildR2.BuildingEditor") != null;
|
||||
hasBuildR3 = FindType("BuildRCities.EditorScripts.BuildREditor") != null;
|
||||
|
||||
string[] easyRoads3DResult = Directory.GetFiles("Assets", "EasyRoads3Dv3.dll", SearchOption.AllDirectories);
|
||||
hasEasyRoads = easyRoads3DResult.Length > 0;
|
||||
|
||||
string[] proceduralToolkitResults = Directory.GetFiles("Assets", "ProceduralToolkit.Editor.asmdef", SearchOption.AllDirectories);
|
||||
hasProceduralToolkit = proceduralToolkitResults.Length > 0;
|
||||
|
||||
hasRoadArchitect = FindType("GSDRoadEditor") != null;
|
||||
hasRTP = FindType("RTP_LODmanagerEditor") != null;
|
||||
hasVolumeGrass = FindType("VolumeGrassEditor") != null;
|
||||
hasWorldStreamer = FindType("SceneSplitterEditor") != null;
|
||||
hasRAM2019 = FindType("RamSplineEditor") != null;
|
||||
}
|
||||
|
||||
private void OnGeneralGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showGeneral = EditorGUILayout.Foldout(showGeneral, "General:");
|
||||
if (!showGeneral) EditorGUILayout.EndVertical();
|
||||
|
||||
generateInThread = EditorGUILayout.Toggle("Generate in Thread", generateInThread);
|
||||
osmServer = (RealWorldTerrainOSMOverpassServer)EditorGUILayout.EnumPopup("OSM Overpass Server", osmServer);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
bool dirty = false;
|
||||
scrollPosition = GUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
OnGeneralGUI();
|
||||
OnCacheFolderGUI();
|
||||
OnResultNameGUI();
|
||||
OnTerrainNameGUI();
|
||||
|
||||
OnThirdPartyGUI(ref dirty);
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Save"))
|
||||
{
|
||||
if (defaultCacheFolder) RealWorldTerrainPrefs.DeletePref("CacheFolder");
|
||||
else RealWorldTerrainPrefs.SetPref("CacheFolder", customCacheFolder);
|
||||
|
||||
if (resultName == "") RealWorldTerrainPrefs.DeletePref("ResultName");
|
||||
else RealWorldTerrainPrefs.SetPref("ResultName", resultName);
|
||||
|
||||
if (terrainName == "") RealWorldTerrainPrefs.DeletePref("TerrainName");
|
||||
else RealWorldTerrainPrefs.SetPref("TerrainName", terrainName);
|
||||
|
||||
RealWorldTerrainPrefs.SetPref("AppendIndex", appendResultNameIndex);
|
||||
RealWorldTerrainPrefs.SetPref("GenerateInThread", generateInThread);
|
||||
RealWorldTerrainPrefs.SetPref("OSMServer", (int)osmServer);
|
||||
|
||||
RealWorldTerrainEditorUtils.ClearFoldersCache();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Revert to default settings", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
int result = EditorUtility.DisplayDialogComplex("Revert to default settings", "Reset generation settings?", "Reset", "Ignore", "Cancel");
|
||||
Debug.Log(result);
|
||||
if (result < 2)
|
||||
{
|
||||
if (result == 0 && File.Exists(RealWorldTerrainPrefs.prefsFilename)) File.Delete(RealWorldTerrainPrefs.prefsFilename);
|
||||
ClearSettings();
|
||||
RealWorldTerrainEditorUtils.ClearFoldersCache();
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (dirty) Repaint();
|
||||
}
|
||||
|
||||
private void OnProceduralToolkit(ref bool dirty)
|
||||
{
|
||||
if (!hasProceduralToolkit) return;
|
||||
|
||||
#if !PROCEDURAL_TOOLKIT
|
||||
if (GUILayout.Button("Enable Procedural Toolkit"))
|
||||
{
|
||||
AddCompilerDirective("PROCEDURAL_TOOLKIT");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable Procedural Toolkit"))
|
||||
{
|
||||
DeleteCompilerDirective("PROCEDURAL_TOOLKIT");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnRAM2019(ref bool dirty)
|
||||
{
|
||||
if (!hasRAM2019) return;
|
||||
#if !RAM2019
|
||||
if (GUILayout.Button("Enable R.A.M 2019"))
|
||||
{
|
||||
AddCompilerDirective("RAM2019");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable R.A.M 2019"))
|
||||
{
|
||||
DeleteCompilerDirective("RAM2019");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnRTP(ref bool dirty)
|
||||
{
|
||||
if (!hasRTP) return;
|
||||
#if !RTP
|
||||
if (GUILayout.Button("Enable Relief Terrain Pack"))
|
||||
{
|
||||
AddCompilerDirective("RTP");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable Relief Terrain Pack"))
|
||||
{
|
||||
DeleteCompilerDirective("RTP");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnRoadArchitect(ref bool dirty)
|
||||
{
|
||||
if (!hasRoadArchitect) return;
|
||||
|
||||
#if !ROADARCHITECT
|
||||
if (GUILayout.Button("Enable Road Architect"))
|
||||
{
|
||||
AddCompilerDirective("ROADARCHITECT");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable Road Architect"))
|
||||
{
|
||||
DeleteCompilerDirective("ROADARCHITECT");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnResultNameGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showResultName = EditorGUILayout.Foldout(showResultName, "Result GameObject name: ");
|
||||
if (showResultName)
|
||||
{
|
||||
resultName = EditorGUILayout.TextField("", resultName);
|
||||
GUILayout.Label("Example:\nRWT_{cx}x{cy} = RWT_4x4");
|
||||
|
||||
DrawResultTokens();
|
||||
|
||||
appendResultNameIndex = GUILayout.Toggle(appendResultNameIndex, "Append index if GameObject already exists?");
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void OnTerrainNameGUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showTerrainNames = EditorGUILayout.Foldout(showTerrainNames, "Terrain GameObjects name: ");
|
||||
if (showTerrainNames)
|
||||
{
|
||||
terrainName = EditorGUILayout.TextField("", terrainName);
|
||||
GUILayout.Label("Example:\nTerrain_{x}x{y} = Terrain_1x3");
|
||||
|
||||
DrawTerrainTokens();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void OnThirdPartyGUI(ref bool dirty)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showThirdPartyAssets = EditorGUILayout.Foldout(showThirdPartyAssets, "Third Party Assets:");
|
||||
if (showThirdPartyAssets)
|
||||
{
|
||||
hasThirdPartyAssets = false;
|
||||
|
||||
OnBuildR2(ref dirty);
|
||||
OnBuildR3(ref dirty);
|
||||
OnEasyRoads(ref dirty);
|
||||
//OnProceduralToolkit(ref dirty);
|
||||
OnRAM2019(ref dirty);
|
||||
OnRTP(ref dirty);
|
||||
OnRoadArchitect(ref dirty);
|
||||
OnVolumeGrass(ref dirty);
|
||||
OnWorldStreamer(ref dirty);
|
||||
|
||||
if (!hasThirdPartyAssets) GUILayout.Label("Third Party Assets not found.");
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private void OnVolumeGrass(ref bool dirty)
|
||||
{
|
||||
if (!hasVolumeGrass) return;
|
||||
|
||||
#if !VOLUMEGRASS
|
||||
if (GUILayout.Button("Enable Volume Grass"))
|
||||
{
|
||||
AddCompilerDirective("VOLUMEGRASS");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable Volume Grass"))
|
||||
{
|
||||
DeleteCompilerDirective("VOLUMEGRASS");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
private void OnWorldStreamer(ref bool dirty)
|
||||
{
|
||||
if (!hasWorldStreamer) return;
|
||||
|
||||
#if !WORLDSTREAMER
|
||||
if (GUILayout.Button("Enable WorldStreamer"))
|
||||
{
|
||||
AddCompilerDirective("WORLDSTREAMER");
|
||||
dirty = true;
|
||||
}
|
||||
#else
|
||||
if (GUILayout.Button("Disable WorldStreamer"))
|
||||
{
|
||||
DeleteCompilerDirective("WORLDSTREAMER");
|
||||
dirty = true;
|
||||
}
|
||||
#endif
|
||||
hasThirdPartyAssets = true;
|
||||
}
|
||||
|
||||
[MenuItem("Window/Infinity Code/Real World Terrain/Settings")]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
wnd = GetWindow<RealWorldTerrainSettingsWindow>(false, "Settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e2d352ec8995d9428a8fc49324b9420
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,335 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using InfinityCode.RealWorldTerrain.Net;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainUpdaterWindow : EditorWindow
|
||||
{
|
||||
private const string packageID = "Real World Terrain";
|
||||
private const string assetPrefix = "RealWorldTerrainWindow";
|
||||
private const string lastVersionKey = assetPrefix + "LastVersion";
|
||||
private const string lastVersionCheckKey = assetPrefix + "LastVersionCheck";
|
||||
private const string channelKey = assetPrefix + "UpdateChannel";
|
||||
private const string invoiceNumberKey = assetPrefix + "InvoiceNumber";
|
||||
|
||||
public static bool hasNewVersion = false;
|
||||
|
||||
private static RealWorldTerrainUpdateChannel channel = RealWorldTerrainUpdateChannel.stable;
|
||||
private string invoiceNumber;
|
||||
private Vector2 scrollPosition;
|
||||
private List<RealWorldTerrainUpdateItem> updates;
|
||||
private static string lastVersionID;
|
||||
|
||||
private void CheckNewVersions()
|
||||
{
|
||||
if (string.IsNullOrEmpty(invoiceNumber))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please enter the Invoice Number.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
SavePrefs();
|
||||
|
||||
string updateKey = GetUpdateKey();
|
||||
GetUpdateList(updateKey);
|
||||
}
|
||||
|
||||
public static void CheckNewVersionAvailable()
|
||||
{
|
||||
if (EditorPrefs.HasKey(lastVersionKey))
|
||||
{
|
||||
lastVersionID = EditorPrefs.GetString(lastVersionKey);
|
||||
|
||||
if (CompareVersions())
|
||||
{
|
||||
hasNewVersion = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const long ticksInHour = 36000000000;
|
||||
|
||||
if (EditorPrefs.HasKey(lastVersionCheckKey))
|
||||
{
|
||||
long lastVersionCheck = EditorPrefs.GetInt(lastVersionCheckKey) * ticksInHour;
|
||||
if (DateTime.Now.Ticks - lastVersionCheck < 24 * ticksInHour)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EditorPrefs.SetInt(lastVersionCheckKey, (int)(DateTime.Now.Ticks / ticksInHour));
|
||||
|
||||
if (EditorPrefs.HasKey(channelKey)) channel = (RealWorldTerrainUpdateChannel)EditorPrefs.GetInt(channelKey);
|
||||
else channel = RealWorldTerrainUpdateChannel.stable;
|
||||
|
||||
if (channel == RealWorldTerrainUpdateChannel.stablePrevious) channel = RealWorldTerrainUpdateChannel.stable;
|
||||
|
||||
WebClient client = new WebClient();
|
||||
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
|
||||
client.UploadDataCompleted += delegate (object sender, UploadDataCompletedEventArgs response)
|
||||
{
|
||||
if (response.Error != null)
|
||||
{
|
||||
Debug.Log("Real World Terrain Updater: " + response.Error.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
string version = Encoding.UTF8.GetString(response.Result);
|
||||
|
||||
try
|
||||
{
|
||||
string[] vars = version.Split('.');
|
||||
string[] vars2 = new string[4];
|
||||
vars2[0] = vars[0];
|
||||
vars2[1] = int.Parse(vars[1].Substring(0, 2)).ToString();
|
||||
vars2[2] = int.Parse(vars[1].Substring(2, 2)).ToString();
|
||||
vars2[3] = int.Parse(vars[1].Substring(4, 4)).ToString();
|
||||
version = string.Join(".", vars2);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Log("Real World Terrain Updater: Bad response");
|
||||
return;
|
||||
}
|
||||
|
||||
lastVersionID = version;
|
||||
|
||||
hasNewVersion = CompareVersions();
|
||||
EditorApplication.update += SetLastVersion;
|
||||
};
|
||||
client.UploadDataAsync(new Uri("https://infinity-code.com/products_update/getlastversion.php"), "POST", Encoding.UTF8.GetBytes("c=" + (int)channel + "&package=" + RealWorldTerrainDownloadManager.EscapeURL(packageID)));
|
||||
}
|
||||
|
||||
private static bool CompareVersions()
|
||||
{
|
||||
double v1 = GetDoubleVersion(RealWorldTerrainWindow.version);
|
||||
double v2 = GetDoubleVersion(lastVersionID);
|
||||
return v1 < v2;
|
||||
}
|
||||
|
||||
private static double GetDoubleVersion(string v)
|
||||
{
|
||||
string[] vs = v.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (vs[1].Length < 2) vs[1] = "0" + vs[1];
|
||||
if (vs[2].Length < 2) vs[2] = "0" + vs[2];
|
||||
if (vs[3].Length < 4)
|
||||
{
|
||||
vs[3] = "000" + vs[3];
|
||||
vs[3] = vs[3].Substring(vs[3].Length - 4, 4);
|
||||
}
|
||||
v = vs[0] + "." + vs[1] + vs[2] + vs[3];
|
||||
double result;
|
||||
if (!double.TryParse(v, out result)) result = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void SetLastVersion()
|
||||
{
|
||||
EditorPrefs.SetString(lastVersionKey, lastVersionID);
|
||||
EditorApplication.update -= SetLastVersion;
|
||||
}
|
||||
|
||||
private string GetUpdateKey()
|
||||
{
|
||||
WebClient client = new WebClient();
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
|
||||
string updateKey = client.UploadString("https://infinity-code.com/products_update/getupdatekey.php",
|
||||
"key=" + invoiceNumber + "&package=" + RealWorldTerrainDownloadManager.EscapeURL(packageID));
|
||||
|
||||
return updateKey;
|
||||
}
|
||||
|
||||
private void GetUpdateList(string updateKey)
|
||||
{
|
||||
WebClient client = new WebClient();
|
||||
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
|
||||
|
||||
try
|
||||
{
|
||||
string response = client.UploadString("https://infinity-code.com/products_update/checkupdates.php", "k=" + RealWorldTerrainDownloadManager.EscapeURL(updateKey) + "&v=" + RealWorldTerrainWindow.version + "&c=" + (int)channel);
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(response);
|
||||
updates = new List<RealWorldTerrainUpdateItem>();
|
||||
|
||||
foreach (XmlNode node in doc.DocumentElement.ChildNodes) updates.Add(new RealWorldTerrainUpdateItem(node));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogError(exception.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
invoiceNumber = EditorPrefs.HasKey(invoiceNumberKey) ? EditorPrefs.GetString(invoiceNumberKey) : "";
|
||||
|
||||
if (EditorPrefs.HasKey(channelKey)) channel = (RealWorldTerrainUpdateChannel)EditorPrefs.GetInt(channelKey);
|
||||
else channel = RealWorldTerrainUpdateChannel.stable;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
SavePrefs();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
invoiceNumber = EditorGUILayout.TextField("Invoice Number:", invoiceNumber).Trim(' ');
|
||||
|
||||
GUIStyle helpStyle = new GUIStyle();
|
||||
helpStyle.margin = new RectOffset(2, 2, 2, 2);
|
||||
|
||||
GUIContent helpContent = new GUIContent(RealWorldTerrainResources.helpIcon, "You can find out your Invoice Number in the email confirming the purchase, or page the user in Unity Asset Store.\nClick to go to the Unity Asset Store.");
|
||||
if (GUILayout.Button(helpContent, helpStyle, GUILayout.ExpandWidth(false))) Process.Start("https://assetstore.unity.com/orders");
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
channel = (RealWorldTerrainUpdateChannel)EditorGUILayout.EnumPopup("Channel:", channel);
|
||||
GUILayout.Label("Current version: " + RealWorldTerrainWindow.version);
|
||||
|
||||
if (GUILayout.Button("Check new versions")) CheckNewVersions();
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||||
|
||||
if (updates != null)
|
||||
{
|
||||
foreach (RealWorldTerrainUpdateItem update in updates) update.Draw();
|
||||
if (updates.Count == 0) GUILayout.Label("No updates");
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
[MenuItem("Window/Infinity Code/Real World Terrain/Check Updates", false, 1999)]
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainUpdaterWindow>(false, "Real World Terrain Updater", true);
|
||||
}
|
||||
|
||||
private void SavePrefs()
|
||||
{
|
||||
EditorPrefs.SetString(invoiceNumberKey, invoiceNumber);
|
||||
EditorPrefs.SetInt(channelKey, (int)channel);
|
||||
}
|
||||
}
|
||||
|
||||
public class RealWorldTerrainUpdateItem
|
||||
{
|
||||
private string version;
|
||||
private int type;
|
||||
private string changelog;
|
||||
private string download;
|
||||
private string date;
|
||||
|
||||
private static GUIStyle _changelogStyle;
|
||||
private static GUIStyle _titleStyle;
|
||||
|
||||
private static GUIStyle changelogStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_changelogStyle == null) _changelogStyle = new GUIStyle(EditorStyles.label) {wordWrap = true};
|
||||
return _changelogStyle;
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIStyle titleStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_titleStyle == null) _titleStyle = new GUIStyle(EditorStyles.boldLabel) {alignment = TextAnchor.MiddleCenter};
|
||||
return _titleStyle;
|
||||
}
|
||||
}
|
||||
|
||||
public string typeStr
|
||||
{
|
||||
get { return Enum.GetName(typeof(RealWorldTerrainUpdateChannel), type); }
|
||||
}
|
||||
|
||||
public RealWorldTerrainUpdateItem(XmlNode node)
|
||||
{
|
||||
version = node["Version"].InnerXml;
|
||||
type = int.Parse(node["Type"].InnerXml);
|
||||
changelog = Unescape(node["ChangeLog"].InnerXml);
|
||||
download = node["Download"].InnerXml;
|
||||
date = node["Date"].InnerXml;
|
||||
|
||||
string[] vars = version.Split('.');
|
||||
string[] vars2 = new string[4];
|
||||
vars2[0] = vars[0];
|
||||
vars2[1] = int.Parse(vars[1].Substring(0, 2)).ToString();
|
||||
vars2[2] = int.Parse(vars[1].Substring(2, 2)).ToString();
|
||||
vars2[3] = int.Parse(vars[1].Substring(4, 4)).ToString();
|
||||
version = string.Join(".", vars2);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
GUILayout.BeginVertical(GUI.skin.box);
|
||||
GUILayout.Label("Version: " + version + " (" + typeStr + "). " + date, titleStyle);
|
||||
|
||||
GUILayout.Label(changelog, changelogStyle);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if (GUILayout.Button("Download"))
|
||||
{
|
||||
Process.Start("https://infinity-code.com/products_update/download.php?k=" + download);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Copy download link", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = "https://infinity-code.com/products_update/download.php?k=" + download;
|
||||
EditorUtility.DisplayDialog("Success",
|
||||
"Download link is copied to the clipboard.\nOpen a browser and paste the link into the address bar.",
|
||||
"OK");
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static string Unescape(string str)
|
||||
{
|
||||
return Regex.Replace(str, @"&(\w+);", delegate (Match match)
|
||||
{
|
||||
string v = match.Groups[1].Value;
|
||||
if (v == "amp") return "&";
|
||||
if (v == "lt") return "<";
|
||||
if (v == "gt") return ">";
|
||||
if (v == "quot") return "\"";
|
||||
if (v == "apos") return "'";
|
||||
return match.Value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public enum RealWorldTerrainUpdateChannel
|
||||
{
|
||||
stable = 10,
|
||||
stablePrevious = 15,
|
||||
releaseCandidate = 20,
|
||||
beta = 30,
|
||||
alpha = 40,
|
||||
working = 50
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 110ed232e8ee3294cadbf75cd6566785
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,189 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainWaterMaskConverter : EditorWindow
|
||||
{
|
||||
private string inputFile;
|
||||
private int width;
|
||||
private int height;
|
||||
private Depth depth = Depth.eight;
|
||||
private RealWorldTerrainByteOrder byteOrder = RealWorldTerrainByteOrder.Windows;
|
||||
private int threshold = 128;
|
||||
|
||||
private void Convert()
|
||||
{
|
||||
if (!Validate()) return;
|
||||
|
||||
string outputFile = EditorUtility.SaveFilePanel("Save Water Mask", "", "WaterMask.bytes", "bytes");
|
||||
if (string.IsNullOrEmpty(outputFile)) return;
|
||||
|
||||
FileStream stream = File.OpenRead(inputFile);
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
int countBytes = depth == Depth.eight ? 1 : 2;
|
||||
int bufferSize = 8192 * countBytes;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
byte[] output = new byte[Mathf.CeilToInt(width * height / 8f) + 8];
|
||||
|
||||
MemoryStream ms = new MemoryStream(output);
|
||||
BinaryWriter writer = new BinaryWriter(ms);
|
||||
writer.Write(width);
|
||||
writer.Write(height);
|
||||
writer.Close();
|
||||
|
||||
long outputIndex = 64;
|
||||
int bufferIndex = 0;
|
||||
int bufferCount = 0;
|
||||
int value = 0;
|
||||
|
||||
int delimiter = depth == Depth.eight ? 1 : 256;
|
||||
|
||||
while ((bufferCount = reader.Read(buffer, bufferIndex, bufferSize)) > 0)
|
||||
{
|
||||
for (int i = 0; i < bufferCount; i++)
|
||||
{
|
||||
if (depth == Depth.sixteen)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
value = buffer[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (byteOrder == RealWorldTerrainByteOrder.Windows)
|
||||
{
|
||||
value += buffer[i] * 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = buffer[i] + value * 256;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = buffer[i];
|
||||
}
|
||||
|
||||
value /= delimiter;
|
||||
|
||||
int bitIndex = (int)(outputIndex % 8);
|
||||
int bit = value > threshold ? 1 : 0;
|
||||
byte o = (byte)(output[outputIndex / 8] | (bit << bitIndex));
|
||||
output[outputIndex / 8] = o;
|
||||
outputIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
stream.Close();
|
||||
|
||||
File.WriteAllBytes(outputFile, output);
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EditorUtility.DisplayDialog("Success", "Water mask successfully saved.", "OK");
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
ProcessDragAndDrop();
|
||||
|
||||
EditorGUILayout.HelpBox("Tool to convert RAW files to bitmask for water generation.", MessageType.Info);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
inputFile = EditorGUILayout.TextField("Input File", inputFile);
|
||||
if (GUILayout.Button("...", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
inputFile = EditorUtility.OpenFilePanel("Select Input File", inputFile, "raw");
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
width = EditorGUILayout.IntField("Width", width);
|
||||
height = EditorGUILayout.IntField("Height", height);
|
||||
depth = (Depth)EditorGUILayout.EnumPopup("Depth", depth);
|
||||
if (depth == Depth.sixteen)
|
||||
{
|
||||
byteOrder = (RealWorldTerrainByteOrder)EditorGUILayout.EnumPopup("Byte Order", byteOrder);
|
||||
}
|
||||
threshold = EditorGUILayout.IntField("Threshold", threshold);
|
||||
|
||||
if (GUILayout.Button("Convert"))
|
||||
{
|
||||
Convert();
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessDragAndDrop()
|
||||
{
|
||||
Event e = Event.current;
|
||||
Rect rect = new Rect(0, 0, position.width, position.height);
|
||||
|
||||
switch (e.type)
|
||||
{
|
||||
case EventType.DragUpdated:
|
||||
case EventType.DragPerform:
|
||||
if (!rect.Contains(e.mousePosition)) return;
|
||||
if (DragAndDrop.paths.Length != 1) return;
|
||||
if (!string.IsNullOrEmpty(inputFile)) return;
|
||||
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
|
||||
|
||||
if (e.type != EventType.DragPerform) return;
|
||||
|
||||
DragAndDrop.AcceptDrag();
|
||||
|
||||
inputFile = DragAndDrop.paths[0];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenWindow()
|
||||
{
|
||||
GetWindow<RealWorldTerrainWaterMaskConverter>(true, "Raw to Water Mask Converter", true);
|
||||
}
|
||||
|
||||
private bool Validate()
|
||||
{
|
||||
if (string.IsNullOrEmpty(inputFile))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Input file is empty.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.Exists(inputFile))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Input file does not exist.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Width and height must be greater than zero.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
FileInfo info = new FileInfo(inputFile);
|
||||
int countBytes = depth == Depth.eight ? 1 : 2;
|
||||
if (info.Length != width * height * countBytes)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "File size does not match the specified width, height and depth.", "OK");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public enum Depth
|
||||
{
|
||||
eight,
|
||||
sixteen,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52357ae39ca24d140b8557d6267a7b83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,402 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using InfinityCode.RealWorldTerrain.Generators;
|
||||
using InfinityCode.RealWorldTerrain.Net;
|
||||
using InfinityCode.RealWorldTerrain.Phases;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain.Windows
|
||||
{
|
||||
public class RealWorldTerrainWindow : EditorWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Current version number
|
||||
/// </summary>
|
||||
public const string version = "4.9.4.1";
|
||||
|
||||
/// <summary>
|
||||
/// The action that occurs when the user aborts the generation.
|
||||
/// </summary>
|
||||
public static Action OnCaptureCanceled;
|
||||
|
||||
/// <summary>
|
||||
/// The action that occurs when the generation is completed.
|
||||
/// </summary>
|
||||
public static Action OnCaptureCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// The action that occurs when the generation is started.
|
||||
/// </summary>
|
||||
public static Action OnCaptureStarted;
|
||||
|
||||
public static RealWorldTerrainContainer container;
|
||||
public static bool generateInThread;
|
||||
public static RealWorldTerrainMonoBase generateTarget;
|
||||
public static RealWorldTerrainGenerateType generateType = RealWorldTerrainGenerateType.full;
|
||||
public static bool isCapturing;
|
||||
public static float progress;
|
||||
public static RealWorldTerrainPrefs prefs;
|
||||
public static RealWorldTerrainItem[,] terrains;
|
||||
public static RealWorldTerrainWindow wnd;
|
||||
|
||||
private static int textureLevel;
|
||||
private static Thread thread;
|
||||
|
||||
public static void CancelCapture()
|
||||
{
|
||||
Dispose();
|
||||
|
||||
if (OnCaptureCanceled != null) OnCaptureCanceled();
|
||||
}
|
||||
|
||||
public static void CancelInMainThread()
|
||||
{
|
||||
EditorApplication.update += OnCancelInMainThread;
|
||||
}
|
||||
|
||||
private static bool CheckFields()
|
||||
{
|
||||
if (prefs.resultType == RealWorldTerrainResultType.gaiaStamp)
|
||||
{
|
||||
#if !GAIA_PRESENT && !GAIA_PRO_PRESENT && !GAIA_2_PRESENT && !GAIA_2023
|
||||
Debug.Log("Gaia not found. Import Gaia into the project.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else if (prefs.resultType == RealWorldTerrainResultType.rawFile)
|
||||
{
|
||||
string filename = prefs.rawFilename;
|
||||
string ext = prefs.rawType == RealWorldTerrainRawType.RAW ? ".raw" : ".png";
|
||||
if (!filename.ToLower().EndsWith(ext)) filename += ext;
|
||||
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Warning", "File already exists. Overwrite?", "Overwrite", "Cancel"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prefs.leftLongitude >= prefs.rightLongitude)
|
||||
{
|
||||
Debug.Log("Bottom-Right Longitude must be greater than Top-Left Longitude");
|
||||
return false;
|
||||
}
|
||||
if (prefs.topLatitude <= prefs.bottomLatitude)
|
||||
{
|
||||
Debug.Log("Top-Left Latitude must be greater than Bottom-Right Latitude");
|
||||
return false;
|
||||
}
|
||||
if (prefs.leftLongitude < -180 || prefs.rightLongitude < -180 || prefs.leftLongitude > 180 || prefs.rightLongitude > 180)
|
||||
{
|
||||
Debug.Log("Longitude must be between -180 and 180.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps)
|
||||
{
|
||||
RealWorldTerrainBingElevationGenerator.key = RealWorldTerrainPrefs.LoadPref("BingAPI", string.Empty);
|
||||
if (string.IsNullOrEmpty(RealWorldTerrainBingElevationGenerator.key))
|
||||
{
|
||||
Debug.LogError("Bing Maps API key is not specified.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.Mapbox)
|
||||
{
|
||||
if (string.IsNullOrEmpty(RealWorldTerrainPrefs.mapboxAccessToken))
|
||||
{
|
||||
Debug.LogError("Mapbox Access Token is not specified.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30)
|
||||
{
|
||||
RealWorldTerrainSRTM30ElevationGenerator.login = RealWorldTerrainPrefs.LoadPref("EarthDataLogin", string.Empty);
|
||||
RealWorldTerrainSRTM30ElevationGenerator.pass = RealWorldTerrainPrefs.LoadPref("EarthDataPass", string.Empty);
|
||||
if (string.IsNullOrEmpty(RealWorldTerrainSRTM30ElevationGenerator.login))
|
||||
{
|
||||
Debug.LogError("EarthData username is not specified.");
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(RealWorldTerrainSRTM30ElevationGenerator.pass))
|
||||
{
|
||||
Debug.LogError("EarthData password is not specified.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (prefs.elevationRange == RealWorldTerrainElevationRange.fixedValue && prefs.fixedMaxElevation - prefs.fixedMinElevation < 0)
|
||||
{
|
||||
Debug.LogError("EarthData password is not specified.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain && !CheckHeightmapMemory()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CheckHeightmapMemory()
|
||||
{
|
||||
int count = prefs.terrainCount;
|
||||
long size = prefs.heightmapResolution * prefs.heightmapResolution * 4 * count;
|
||||
size += prefs.baseMapResolution * prefs.baseMapResolution * 4 * count;
|
||||
size += prefs.detailResolution * prefs.detailResolution * 4 * count;
|
||||
size += 513 * 513 * 4 * count; //Alphamaps
|
||||
|
||||
if (size > int.MaxValue * 0.75f)
|
||||
{
|
||||
return EditorUtility.DisplayDialog("Warning", "Too high settings. Perhaps out of memory error.", "Continue", "Abort");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void ClearCache()
|
||||
{
|
||||
RealWorldTerrainClearCacheWindow.OpenWindow();
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
isCapturing = false;
|
||||
|
||||
if (thread != null)
|
||||
{
|
||||
thread.Abort();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
RealWorldTerrainElevationGenerator.Dispose();
|
||||
|
||||
RealWorldTerrainTextureGenerator.Dispose();
|
||||
RealWorldTerrainTerrainLayersGenerator.Dispose();
|
||||
RealWorldTerrainDownloadManager.Dispose();
|
||||
RealWorldTerrainRoadGenerator.Dispose();
|
||||
RealWorldTerrainRiverGenerator.Dispose();
|
||||
RealWorldTerrainGrassGenerator.Dispose();
|
||||
RealWorldTerrainTreesGenerator.Dispose();
|
||||
RealWorldTerrainBuildingGenerator.Dispose();
|
||||
RealWorldTerrainWaterMask.Dispose();
|
||||
|
||||
EditorUtility.UnloadUnusedAssetsImmediate();
|
||||
|
||||
RealWorldTerrainPhase.requiredPhases = null;
|
||||
if (RealWorldTerrainPhase.activePhase != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
RealWorldTerrainPhase.activePhase.Finish();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
RealWorldTerrainPhase.activePhase = null;
|
||||
RealWorldTerrainPhase.activePhaseIndex = -1;
|
||||
|
||||
if (wnd != null) wnd.Repaint();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private static void OnCancelInMainThread()
|
||||
{
|
||||
CancelCapture();
|
||||
EditorApplication.update -= OnCancelInMainThread;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
wnd = null;
|
||||
prefs.Save();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
wnd = this;
|
||||
if (prefs == null) prefs = new RealWorldTerrainPrefs();
|
||||
prefs.Load();
|
||||
|
||||
RealWorldTerrainWindowUI.OnEnable();
|
||||
|
||||
RealWorldTerrainUpdaterWindow.CheckNewVersionAvailable();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
RealWorldTerrainWindowUI.OnGUI();
|
||||
}
|
||||
|
||||
[MenuItem("Window/Infinity Code/Real World Terrain/Open Real World Terrain", false, 0)]
|
||||
private static void OpenWindow()
|
||||
{
|
||||
OpenWindow(RealWorldTerrainGenerateType.full);
|
||||
}
|
||||
|
||||
public static void OpenWindow(RealWorldTerrainGenerateType type, RealWorldTerrainMonoBase target = null)
|
||||
{
|
||||
generateTarget = target;
|
||||
generateType = type;
|
||||
wnd = GetWindow<RealWorldTerrainWindow>(false, "Real World Terrain");
|
||||
if (target == null)
|
||||
{
|
||||
prefs = new RealWorldTerrainPrefs();
|
||||
prefs.Load();
|
||||
}
|
||||
else if (type == RealWorldTerrainGenerateType.full)
|
||||
{
|
||||
prefs = RealWorldTerrainPrefs.GetPrefs(target, true);
|
||||
generateTarget = null;
|
||||
}
|
||||
else prefs = RealWorldTerrainPrefs.GetPrefs(target);
|
||||
|
||||
if (type == RealWorldTerrainGenerateType.additional)
|
||||
{
|
||||
prefs.generateBuildings = false;
|
||||
prefs.generateGrass = false;
|
||||
prefs.generateRoads = false;
|
||||
prefs.generateTrees = false;
|
||||
}
|
||||
|
||||
RealWorldTerrainWindowUI.InitTextureProviders();
|
||||
RealWorldTerrainUpdaterWindow.CheckNewVersionAvailable();
|
||||
}
|
||||
|
||||
private static void PrepareStart()
|
||||
{
|
||||
generateInThread = RealWorldTerrainPrefs.LoadPref("GenerateInThread", true);
|
||||
RealWorldTerrainOSMUtils.InitOSMServer();
|
||||
|
||||
if (!CheckFields()) return;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.mesh ||
|
||||
prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
prefs.textureCount = prefs.terrainCount;
|
||||
}
|
||||
|
||||
RealWorldTerrainElevationGenerator.elevations = new List<RealWorldTerrainElevationGenerator>();
|
||||
|
||||
if (generateType == RealWorldTerrainGenerateType.full || generateType == RealWorldTerrainGenerateType.terrain || generateType == RealWorldTerrainGenerateType.additional)
|
||||
{
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM) RealWorldTerrainSRTMElevationGenerator.Init();
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps) RealWorldTerrainBingElevationGenerator.Init();
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30) RealWorldTerrainSRTM30ElevationGenerator.Init();
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.Mapbox) RealWorldTerrainMapboxElevationGenerator.Init();
|
||||
//else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.ArcGIS) RealWorldTerrainArcGISElevationGenerator.Init();
|
||||
}
|
||||
|
||||
if (generateType == RealWorldTerrainGenerateType.full || generateType == RealWorldTerrainGenerateType.texture)
|
||||
{
|
||||
if (prefs.generateTextures && prefs.resultType != RealWorldTerrainResultType.gaiaStamp)
|
||||
{
|
||||
if (prefs.textureResultType == RealWorldTerrainTextureResultType.regularTexture || prefs.textureResultType == RealWorldTerrainTextureResultType.hugeTexture)
|
||||
{
|
||||
RealWorldTerrainTextureGenerator.Init();
|
||||
}
|
||||
else if (prefs.textureResultType == RealWorldTerrainTextureResultType.terrainLayers)
|
||||
{
|
||||
RealWorldTerrainTerrainLayersGenerator.Init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (generateType == RealWorldTerrainGenerateType.full || generateType == RealWorldTerrainGenerateType.additional)
|
||||
{
|
||||
if (prefs.resultType != RealWorldTerrainResultType.gaiaStamp)
|
||||
{
|
||||
RealWorldTerrainBuildingGenerator.Download();
|
||||
RealWorldTerrainRoadGenerator.Download();
|
||||
RealWorldTerrainTreesGenerator.Download();
|
||||
RealWorldTerrainGrassGenerator.Download();
|
||||
RealWorldTerrainRiverGenerator.Download();
|
||||
}
|
||||
}
|
||||
|
||||
if (prefs.mapType == null) prefs.mapType = RealWorldTerrainTextureProviderManager.FindMapType(prefs.mapTypeID);
|
||||
prefs.mapTypeID = prefs.mapType.fullID;
|
||||
prefs.mapTypeExtraFields = prefs.mapType.GetSettings();
|
||||
|
||||
if (generateTarget != null) prefs.Apply(generateTarget);
|
||||
if (generateType == RealWorldTerrainGenerateType.full) RealWorldTerrainHistoryWindow.Add(prefs);
|
||||
|
||||
isCapturing = true;
|
||||
|
||||
RealWorldTerrainPhase.Init();
|
||||
|
||||
if (OnCaptureStarted != null) OnCaptureStarted();
|
||||
}
|
||||
|
||||
public static void StartCapture()
|
||||
{
|
||||
prefs.Save();
|
||||
|
||||
if (generateType == RealWorldTerrainGenerateType.additional)
|
||||
{
|
||||
RealWorldTerrainMonoBase target = generateTarget;
|
||||
|
||||
if (target is RealWorldTerrainContainer)
|
||||
{
|
||||
if (prefs.generateBuildings) RealWorldTerrainUtils.DeleteGameObject(target.transform, "Buildings");
|
||||
if (prefs.generateRoads) RealWorldTerrainUtils.DeleteGameObject(target.transform, "Roads");
|
||||
if (prefs.generateRivers) RealWorldTerrainUtils.DeleteGameObject(target.transform, "Rivers");
|
||||
if (prefs.generateTrees)
|
||||
{
|
||||
foreach (RealWorldTerrainItem item in (target as RealWorldTerrainContainer).terrains)
|
||||
{
|
||||
item.terrainData.treeInstances = new TreeInstance[0];
|
||||
item.terrainData.treePrototypes = new TreePrototype[0];
|
||||
}
|
||||
}
|
||||
if (prefs.generateGrass)
|
||||
{
|
||||
foreach (RealWorldTerrainItem item in (target as RealWorldTerrainContainer).terrains)
|
||||
{
|
||||
item.terrainData.detailPrototypes = new DetailPrototype[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RealWorldTerrainItem item = target as RealWorldTerrainItem;
|
||||
|
||||
string index = item.x + "x" + (item.container.terrainCount.y - item.y - 1);
|
||||
if (prefs.generateBuildings) RealWorldTerrainUtils.DeleteGameObject(target.transform.parent, "Buildings " + index);
|
||||
if (prefs.generateRoads) RealWorldTerrainUtils.DeleteGameObject(target.transform.parent, "Roads " + index);
|
||||
if (prefs.generateTrees)
|
||||
{
|
||||
item.terrainData.treeInstances = new TreeInstance[0];
|
||||
item.terrainData.treePrototypes = new TreePrototype[0];
|
||||
}
|
||||
if (prefs.generateGrass) item.terrainData.detailPrototypes = new DetailPrototype[0];
|
||||
}
|
||||
}
|
||||
|
||||
PrepareStart();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (RealWorldTerrainPhase.activePhase == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
RealWorldTerrainPhase.activePhase.Enter();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
CancelCapture();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c13add9f7f666fc428a5c03c3b6fde57
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b023828a76464b74785d0fdc0f4dd374
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,219 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using InfinityCode.RealWorldTerrain.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static bool showCoordinates = true;
|
||||
private static int coordinateMode = 0;
|
||||
|
||||
private static string utmTLLatZone;
|
||||
private static int utmTLLngZone;
|
||||
private static int utmTLEasting;
|
||||
private static int utmTLNorthing;
|
||||
|
||||
private static string utmBRLatZone;
|
||||
private static int utmBRLngZone;
|
||||
private static int utmBREasting;
|
||||
private static int utmBRNorthing;
|
||||
|
||||
private static void AnchorUI()
|
||||
{
|
||||
prefs.useAnchor = Toggle(prefs.useAnchor, "Use Anchor", true, "The coordinates of the anchor point at which there will be a zero position in the scene.");
|
||||
if (!prefs.useAnchor) return;
|
||||
|
||||
prefs.anchorLatitude = DoubleField("Latitude", prefs.anchorLatitude, "Latitude of the Anchor. \nValues: -90 to 90.", "http://en.wikipedia.org/wiki/Latitude");
|
||||
prefs.anchorLongitude = DoubleField("Longitude", prefs.anchorLongitude, "Longitude of the Anchor. \nValues: -180 to 180.", "http://en.wikipedia.org/wiki/Longitude");
|
||||
}
|
||||
|
||||
private static void ApplyUTMValues()
|
||||
{
|
||||
RealWorldTerrainUTM.ToLngLat(utmTLLatZone, utmTLLngZone, utmTLEasting, utmTLNorthing, out prefs.leftLongitude, out prefs.topLatitude);
|
||||
RealWorldTerrainUTM.ToLngLat(utmBRLatZone, utmBRLngZone, utmBREasting, utmBRNorthing, out prefs.rightLongitude, out prefs.bottomLatitude);
|
||||
coordinateMode = 0;
|
||||
}
|
||||
|
||||
private static void AreaUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showCoordinates = EditorGUILayout.Foldout(showCoordinates, "Area");
|
||||
if (!showCoordinates)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
prefs.title = EditorGUILayout.TextField("Title", prefs.title);
|
||||
GUILayout.Space(10);
|
||||
|
||||
CoordinatesUI();
|
||||
AnchorUI();
|
||||
AreaButtonsUI();
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static void AreaButtonsUI()
|
||||
{
|
||||
GUI.SetNextControlName("InsertCoordsButton");
|
||||
if (GUILayout.Button("Insert the coordinates from the clipboard")) InsertCoords();
|
||||
if (GUILayout.Button("Run the helper")) RunHelper();
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain && GUILayout.Button("Get the best settings for the specified coordinates")) RealWorldTerrainSettingsGeneratorWindow.OpenWindow();
|
||||
if (GUILayout.Button("Show Open Street Map"))
|
||||
{
|
||||
Vector2 center;
|
||||
int zoom;
|
||||
RealWorldTerrainMath.GetCenterPointAndZoom(new[] {prefs.leftLongitude, prefs.topLatitude, prefs.rightLongitude, prefs.bottomLatitude}, out center, out zoom);
|
||||
Process.Start(string.Format(RealWorldTerrainCultureInfo.numberFormat, "http://www.openstreetmap.org/#map={0}/{1}/{2}", zoom, center.y, center.x));
|
||||
}
|
||||
}
|
||||
|
||||
private static void CoordinatesUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
coordinateMode = GUILayout.Toolbar(coordinateMode, new[] {"Decimal", "UTM"});
|
||||
if (EditorGUI.EndChangeCheck() && coordinateMode == 1) InitUTMValues();
|
||||
|
||||
if (coordinateMode == 0) DecimalCoordinatesUI();
|
||||
else UTMCoordinatesUI();
|
||||
}
|
||||
|
||||
private static void DecimalCoordinatesUI()
|
||||
{
|
||||
GUILayout.Label("Top-Left");
|
||||
EditorGUI.indentLevel++;
|
||||
prefs.topLatitude = DoubleField("Latitude", prefs.topLatitude, "Latitude of the Top-Left corner of the area. \nValues: -90 to 90.", "http://en.wikipedia.org/wiki/Latitude");
|
||||
prefs.leftLongitude = DoubleField("Longitude", prefs.leftLongitude, "Longitude of the Top-Left corner of the area. \nValues: -180 to 180.", "http://en.wikipedia.org/wiki/Longitude");
|
||||
EditorGUI.indentLevel--;
|
||||
GUILayout.Space(10);
|
||||
|
||||
GUILayout.Label("Bottom-Right");
|
||||
EditorGUI.indentLevel++;
|
||||
prefs.bottomLatitude = DoubleField("Latitude", prefs.bottomLatitude, "Latitude of the Bottom-Right corner of the area. \nValues: -90 to 90.", "http://en.wikipedia.org/wiki/Latitude");
|
||||
prefs.rightLongitude = DoubleField("Longitude", prefs.rightLongitude, "Longitude of the Bottom-Right corner of the area. \nValues: -180 to 180.", "http://en.wikipedia.org/wiki/Longitude");
|
||||
EditorGUI.indentLevel--;
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (prefs.topLatitude > 60 || prefs.bottomLatitude < -60)
|
||||
{
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM || prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30)
|
||||
{
|
||||
EditorGUILayout.HelpBox("SRTM and SRTM30 only contain data in the latitude range 60 to -60. Please select another Elevation Provider.", MessageType.Error);
|
||||
}
|
||||
else if (/*prefs.elevationProvider == RealWorldTerrainElevationProvider.ArcGIS || */prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps)
|
||||
{
|
||||
EditorGUILayout.HelpBox("For latitudes north of 60 degrees or south of -60 degrees, ArcGIS and Bing Maps contain data with an accuracy of 900 meters per value, which is very small for a good result. Try using Mapbox first.", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitUTMValues()
|
||||
{
|
||||
double e, n;
|
||||
RealWorldTerrainUTM.ToUTM(prefs.leftLongitude, prefs.topLatitude, out utmTLLatZone, out utmTLLngZone, out e, out n);
|
||||
utmTLEasting = (int) Math.Round(e);
|
||||
utmTLNorthing = (int) Math.Round(n);
|
||||
|
||||
RealWorldTerrainUTM.ToUTM(prefs.rightLongitude, prefs.bottomLatitude, out utmBRLatZone, out utmBRLngZone, out e, out n);
|
||||
utmBREasting = (int) Math.Round(e);
|
||||
utmBRNorthing = (int) Math.Round(n);
|
||||
}
|
||||
|
||||
public static void InsertCoords()
|
||||
{
|
||||
GUI.FocusControl("InsertCoordsButton");
|
||||
string nodeStr = EditorGUIUtility.systemCopyBuffer;
|
||||
if (string.IsNullOrEmpty(nodeStr)) return;
|
||||
|
||||
XmlDocument doc = new XmlDocument();
|
||||
try
|
||||
{
|
||||
doc.LoadXml(nodeStr);
|
||||
XmlNode node = doc.FirstChild;
|
||||
if (node.Name != "Coords" || node.Attributes == null) return;
|
||||
|
||||
prefs.leftLongitude = RealWorldTerrainXMLExt.GetAttribute<float>(node, "tlx");
|
||||
prefs.topLatitude = RealWorldTerrainXMLExt.GetAttribute<float>(node, "tly");
|
||||
prefs.rightLongitude = RealWorldTerrainXMLExt.GetAttribute<float>(node, "brx");
|
||||
prefs.bottomLatitude = RealWorldTerrainXMLExt.GetAttribute<float>(node, "bry");
|
||||
|
||||
if (prefs.useAnchor)
|
||||
{
|
||||
if (EditorUtility.DisplayDialog("Remove Anchor", "Remove anchor point from previous settings?", "Remove", "Keep"))
|
||||
{
|
||||
prefs.useAnchor = false;
|
||||
double mx1, my1, mx2, my2;
|
||||
RealWorldTerrainGeo.LatLongToMercat(prefs.leftLongitude, prefs.topLatitude, out mx1, out my1);
|
||||
RealWorldTerrainGeo.LatLongToMercat(prefs.rightLongitude, prefs.bottomLatitude, out mx2, out my2);
|
||||
mx1 = (mx2 + mx1) / 2;
|
||||
my1 = (my2 + my1) / 2;
|
||||
RealWorldTerrainGeo.MercatToLatLong(mx1, my1, out prefs.anchorLongitude, out prefs.anchorLatitude);
|
||||
}
|
||||
}
|
||||
|
||||
XmlNodeList POInodes = node.SelectNodes("//POI");
|
||||
prefs.POI = new List<RealWorldTerrainPOI>();
|
||||
foreach (XmlNode n in POInodes) prefs.POI.Add(new RealWorldTerrainPOI(n));
|
||||
|
||||
prefs.Save();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static void RunHelper()
|
||||
{
|
||||
string helperPath = "file://" + Directory.GetFiles(Application.dataPath, "RWT_Helper.html", SearchOption.AllDirectories)[0].Replace('\\', '/');
|
||||
if (Application.platform == RuntimePlatform.OSXEditor) helperPath = helperPath.Replace(" ", "%20");
|
||||
prefs.Save();
|
||||
Application.OpenURL(helperPath);
|
||||
}
|
||||
|
||||
private static void UTMCoordinatesUI()
|
||||
{
|
||||
GUILayout.Label("Top-Left");
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
utmTLLngZone = EditorGUILayout.IntField(utmTLLngZone);
|
||||
utmTLLatZone = EditorGUILayout.TextField(utmTLLatZone);
|
||||
utmTLEasting = EditorGUILayout.IntField(utmTLEasting);
|
||||
utmTLNorthing = EditorGUILayout.IntField(utmTLNorthing);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
GUILayout.Space(10);
|
||||
|
||||
GUILayout.Label("Bottom-Right");
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
utmBRLngZone = EditorGUILayout.IntField(utmBRLngZone);
|
||||
utmBRLatZone = EditorGUILayout.TextField(utmBRLatZone);
|
||||
utmBREasting = EditorGUILayout.IntField(utmBREasting);
|
||||
utmBRNorthing = EditorGUILayout.IntField(utmBRNorthing);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
if (GUILayout.Button("Apply")) ApplyUTMValues();
|
||||
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20ad28ba9a7439b45875728058473670
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,308 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
#if BUILDR2
|
||||
using BuildR2;
|
||||
#endif
|
||||
|
||||
#if BUILDR3
|
||||
using BuildRCities;
|
||||
#endif
|
||||
|
||||
#if PROCEDURAL_TOOLKIT
|
||||
using ProceduralToolkit.Buildings;
|
||||
#endif
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static bool showBuildRCustomPresets;
|
||||
private static List<string> availableBuildingEngine;
|
||||
private static List<int> availableBuildingsIDs;
|
||||
|
||||
private static void BuildR2Fields()
|
||||
{
|
||||
#if BUILDR2
|
||||
prefs.buildRCollider = (RealWorldTerrainBuildR2Collider)EditorGUILayout.EnumPopup("Collider", prefs.buildRCollider);
|
||||
prefs.buildRRenderMode = (RealWorldTerrainBuildR2RenderMode)EditorGUILayout.EnumPopup("Render Mode", prefs.buildRRenderMode);
|
||||
|
||||
if (prefs.buildR2Materials == null) prefs.buildR2Materials = new List<RealWorldTerrainBuildR2Material>{new RealWorldTerrainBuildR2Material()};
|
||||
else if (prefs.buildR2Materials.Count == 0)
|
||||
{
|
||||
prefs.buildR2Materials.Add(new RealWorldTerrainBuildR2Material());
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("Surfaces & Facades");
|
||||
|
||||
int removeIndex = -1;
|
||||
|
||||
for (int i = 0; i < prefs.buildR2Materials.Count; i++)
|
||||
{
|
||||
RealWorldTerrainBuildR2Material material = prefs.buildR2Materials[i];
|
||||
EditorGUILayout.BeginHorizontal(i % 2 == 0 ? evenStyle : oddStyle);
|
||||
|
||||
EditorGUILayout.LabelField(i + 1 + ": ", GUILayout.Width(30));
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
material.roofSurface = EditorGUILayout.ObjectField(new GUIContent("Roof Surface:"), material.roofSurface, typeof(Surface), false) as Surface;
|
||||
material.roofType = (Roof.Types)EditorGUILayout.EnumPopup("Roof Type:", material.roofType);
|
||||
|
||||
if (material.facades == null) material.facades = new List<Facade>();
|
||||
|
||||
EditorGUILayout.LabelField("Facades:");
|
||||
int removeFacadeIndex = -1;
|
||||
|
||||
for (int j = 0; j < material.facades.Count; j++)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
material.facades[j] = EditorGUILayout.ObjectField(material.facades[j], typeof(Facade), false) as Facade;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (material.facades[j] == null) removeFacadeIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeFacadeIndex != -1) material.facades.RemoveAt(removeFacadeIndex);
|
||||
|
||||
Facade newFacade = EditorGUILayout.ObjectField(null, typeof(Facade), false) as Facade;
|
||||
if (newFacade != null) material.facades.Add(newFacade);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.buildR2Materials.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add new item"))
|
||||
{
|
||||
prefs.buildR2Materials.Add(new RealWorldTerrainBuildR2Material());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void BuildR3Fields()
|
||||
{
|
||||
#if BUILDR3
|
||||
if (prefs.buildR3Materials == null) prefs.buildR3Materials = new List<RealWorldTerrainBuildR3Material> {new RealWorldTerrainBuildR3Material()};
|
||||
else if (prefs.buildR3Materials.Count == 0)
|
||||
{
|
||||
prefs.buildR3Materials.Add(new RealWorldTerrainBuildR3Material());
|
||||
}
|
||||
|
||||
prefs.buildR3Collider = EditorGUILayout.Toggle("Generate Colliders", prefs.buildR3Collider);
|
||||
|
||||
EditorGUILayout.LabelField("Surfaces & Facades");
|
||||
|
||||
int removeIndex = -1;
|
||||
|
||||
for (int i = 0; i < prefs.buildR3Materials.Count; i++)
|
||||
{
|
||||
RealWorldTerrainBuildR3Material material = prefs.buildR3Materials[i];
|
||||
EditorGUILayout.BeginHorizontal(i % 2 == 0 ? evenStyle : oddStyle);
|
||||
|
||||
EditorGUILayout.LabelField(i + 1 + ": ", GUILayout.Width(30));
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
EditorGUILayout.LabelField("Facades:");
|
||||
|
||||
material.wallFacade = EditorGUILayout.ObjectField("Wall:", material.wallFacade, typeof(FacadeAsset), false) as FacadeAsset;
|
||||
material.roofTexture = EditorGUILayout.ObjectField("Roof:", material.roofTexture, typeof(DynamicTextureAsset), false) as DynamicTextureAsset;
|
||||
material.roofType = (Roof.Types) EditorGUILayout.EnumPopup("Roof Type:", material.roofType);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.buildR3Materials.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add new item"))
|
||||
{
|
||||
prefs.buildR3Materials.Add(new RealWorldTerrainBuildR3Material());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void BuildingsUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
prefs.generateBuildings = EditorGUILayout.Toggle("Generate buildings", prefs.generateBuildings);
|
||||
|
||||
if (!prefs.generateBuildings)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
prefs.buildingGenerator = EditorGUILayout.IntPopup("Building generator", prefs.buildingGenerator, availableBuildingEngine.ToArray(), availableBuildingsIDs.ToArray());
|
||||
|
||||
prefs.buildingSingleRequest = Toggle("Download using a single request", prefs.buildingSingleRequest, false, "If enabled, one request will be sent for the entire area.\nIf disabled, the request will be split into small parts, which will make downloading data for megacities more stable.");
|
||||
|
||||
if (prefs.buildingGenerator == 2) BuildR2Fields();
|
||||
else if (prefs.buildingGenerator == 5) BuildR3Fields();
|
||||
else if (prefs.buildingGenerator == 3) InstantiatePrefabsFields();
|
||||
else if (prefs.buildingGenerator == 4) ProceduralToolkitBuildingsFields();
|
||||
|
||||
RealWorldTerrainRangeI range = prefs.buildingFloorLimits;
|
||||
float minLevelLimit = range.min;
|
||||
float maxLevelLimit = range.max;
|
||||
MinMaxSlider(string.Format("Floors if unknown ({0}-{1})", range.min, range.max),
|
||||
ref minLevelLimit, ref maxLevelLimit, 1, 50,
|
||||
"If no building height or number of floors is specified in the OSM data, a random value for floors in this range will be used.");
|
||||
range.Set(minLevelLimit, maxLevelLimit);
|
||||
|
||||
if (prefs.buildingGenerator == 0) BuiltInBuildingEngineFields();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static void BuiltInBuildingEngineFields()
|
||||
{
|
||||
prefs.buildingFloorHeight = EditorGUILayout.FloatField("Floor Height", prefs.buildingFloorHeight);
|
||||
prefs.buildingBottomMode = (RealWorldTerrainBuildingBottomMode)EditorGUILayout.EnumPopup("Bottom Mode", prefs.buildingBottomMode);
|
||||
prefs.buildingBasementDepth = FloatField("Basement Depth", prefs.buildingBasementDepth, "Building depth below ground level in meters (Zero or positive number).");
|
||||
prefs.buildingUseColorTags = Toggle("Use Color Tags", prefs.buildingUseColorTags, false, "Whether to use color tag from OSM data? If so, a new material will be created for each building with a color.");
|
||||
prefs.dynamicBuildings = Toggle("Dynamic Buildings", prefs.dynamicBuildings, false, "Dynamic buildings are generated at runtime and are not saved as meshes, thus bypassing the meshes import phase.");
|
||||
prefs.buildingSaveInResult = Toggle("Save In Result", prefs.buildingSaveInResult, false, "Should meshes and materials be saved in the project? If disabled, you may lose non-dynamic meshes and materials when resetting the scene state (saving / loading, compiling scripts, etc.).");
|
||||
|
||||
GUILayout.Label("Building Materials");
|
||||
if (prefs.buildingMaterials == null) prefs.buildingMaterials = new List<RealWorldTerrainBuildingMaterial>();
|
||||
for (int i = 0; i < prefs.buildingMaterials.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUILayout.Label((i + 1).ToString(), GUILayout.ExpandWidth(false));
|
||||
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
RealWorldTerrainBuildingMaterial material = prefs.buildingMaterials[i];
|
||||
material.wall = EditorGUILayout.ObjectField("Wall material", material.wall, typeof(Material), false) as Material;
|
||||
material.roof = EditorGUILayout.ObjectField("Roof material", material.roof, typeof(Material), false) as Material;
|
||||
material.tileSize = EditorGUILayout.Vector2Field("Tile Size (meters)", material.tileSize);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
prefs.buildingMaterials[i] = null;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
prefs.buildingMaterials.RemoveAll(m => m == null);
|
||||
|
||||
if (GUILayout.Button("Add material")) prefs.buildingMaterials.Add(new RealWorldTerrainBuildingMaterial());
|
||||
}
|
||||
|
||||
private static void InitBuildingEngines()
|
||||
{
|
||||
availableBuildingEngine = new List<string> { "Built-in", "Instantiate Prefabs" };
|
||||
availableBuildingsIDs = new List<int> { 0, 3 };
|
||||
#if BUILDR2
|
||||
availableBuildingEngine.Add("BuildR2");
|
||||
availableBuildingsIDs.Add(2);
|
||||
#endif
|
||||
#if BUILDR3
|
||||
availableBuildingEngine.Add("BuildR3");
|
||||
availableBuildingsIDs.Add(5);
|
||||
#endif
|
||||
#if PROCEDURAL_TOOLKIT
|
||||
availableBuildingEngine.Add("Procedural Toolkit");
|
||||
availableBuildingsIDs.Add(4);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void InstantiatePrefabsFields()
|
||||
{
|
||||
EditorGUILayout.HelpBox("If you use highly detailed buildings, when generating areas that contain a lot of buildings (for example, cities), Unity Editor can crashes.", MessageType.Info);
|
||||
EditorGUILayout.HelpBox("Prefab must contain a BoxCollider so that RWT can determine the boundaries of the building.", MessageType.Info);
|
||||
|
||||
if (prefs.buildingPrefabs == null) prefs.buildingPrefabs = new List<RealWorldTerrainBuildingPrefab>();
|
||||
|
||||
int removeIndex = -1;
|
||||
|
||||
for (int i = 0; i < prefs.buildingPrefabs.Count; i++)
|
||||
{
|
||||
RealWorldTerrainBuildingPrefab b = prefs.buildingPrefabs[i];
|
||||
EditorGUILayout.BeginHorizontal(i % 2 == 0 ? evenStyle : oddStyle);
|
||||
|
||||
EditorGUILayout.LabelField(i + 1 + ": ", GUILayout.Width(30));
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
b.prefab = EditorGUILayout.ObjectField("Prefab", b.prefab, typeof(GameObject), false) as GameObject;
|
||||
b.sizeMode = (RealWorldTerrainBuildingPrefab.SizeMode) EditorGUILayout.EnumPopup("Size Mode", b.sizeMode);
|
||||
b.heightMode = (RealWorldTerrainBuildingPrefab.HeightMode) EditorGUILayout.EnumPopup("Height Mode", b.heightMode);
|
||||
|
||||
if (b.heightMode == RealWorldTerrainBuildingPrefab.HeightMode.fixedHeight)
|
||||
{
|
||||
b.fixedHeight = EditorGUILayout.FloatField("Height", b.fixedHeight);
|
||||
}
|
||||
|
||||
b.placementMode = (RealWorldTerrainBuildingPrefab.PlacementMode)EditorGUILayout.EnumPopup("Placement Mode", b.placementMode);
|
||||
|
||||
if (b.tags == null) b.tags = new List<RealWorldTerrainBuildingPrefab.OSMTag>();
|
||||
|
||||
EditorGUILayout.LabelField("Tags (if no tags, prefab can be used for all buildings)");
|
||||
|
||||
int tagRemoveIndex = -1;
|
||||
|
||||
for (int j = 0; j < b.tags.Count; j++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(j % 2 == 0 ? evenStyle : oddStyle);
|
||||
|
||||
EditorGUILayout.LabelField(j + 1 + ": ", GUILayout.Width(30));
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
RealWorldTerrainBuildingPrefab.OSMTag t = b.tags[j];
|
||||
t.key = EditorGUILayout.TextField("Key", t.key);
|
||||
t.value = EditorGUILayout.TextField("Value", t.value);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) tagRemoveIndex = j;
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (tagRemoveIndex != -1) b.tags.RemoveAt(tagRemoveIndex);
|
||||
if (GUILayout.Button("Add tag"))
|
||||
{
|
||||
b.tags.Add(new RealWorldTerrainBuildingPrefab.OSMTag());
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.buildingPrefabs.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add new item"))
|
||||
{
|
||||
RealWorldTerrainBuildingPrefab newPrefab = new RealWorldTerrainBuildingPrefab();
|
||||
newPrefab.tags = new List<RealWorldTerrainBuildingPrefab.OSMTag>();
|
||||
prefs.buildingPrefabs.Add(newPrefab);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProceduralToolkitBuildingsFields()
|
||||
{
|
||||
#if PROCEDURAL_TOOLKIT
|
||||
prefs.ptFacadePlanningStrategy = EditorGUILayout.ObjectField("Facade Planning Strategy", prefs.ptFacadePlanningStrategy, typeof(FacadePlanningStrategy), false) as FacadePlanningStrategy;
|
||||
prefs.ptFacadeConstructionStrategy = EditorGUILayout.ObjectField("Facade Construction Strategy", prefs.ptFacadeConstructionStrategy, typeof(FacadeConstructionStrategy), false) as FacadeConstructionStrategy;
|
||||
prefs.ptRoofPlanningStrategy = EditorGUILayout.ObjectField("Roof Planning Strategy", prefs.ptRoofPlanningStrategy, typeof(RoofPlanningStrategy), false) as RoofPlanningStrategy;
|
||||
prefs.ptRoofConstructionStrategy = EditorGUILayout.ObjectField("Roof Construction Strategy", prefs.ptRoofConstructionStrategy, typeof(RoofConstructionStrategy), false) as RoofConstructionStrategy;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c0c7518427817044a4d7e89f5306dfc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static string bingAPI;
|
||||
private static string earthDataLogin;
|
||||
private static string earthDataPass;
|
||||
private static bool showElevationProvider = true;
|
||||
|
||||
private static void BingMapsElevationExtraFields()
|
||||
{
|
||||
if (bingAPI == null) bingAPI = RealWorldTerrainPrefs.LoadPref("BingAPI", "");
|
||||
EditorGUILayout.HelpBox("Public Windows App or Public Windows Phone App have the 50.000 transaction within 24 hours. With the other chooses there's only 125.000 transactions within a year and the key will expire if exceeding it.", MessageType.Info);
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bingAPI = EditorGUILayout.TextField("Bing Maps API key", bingAPI);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (bingAPI == "") RealWorldTerrainPrefs.DeletePref("BingAPI");
|
||||
else RealWorldTerrainPrefs.SetPref("BingAPI", bingAPI);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(bingAPI))
|
||||
{
|
||||
GUILayout.Box(new GUIContent(RealWorldTerrainResources.warningIcon, "Required"), RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false));
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Create Key", GUILayout.ExpandWidth(false))) Process.Start("http://msdn.microsoft.com/en-us/library/ff428642.aspx");
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private static void ElevationProviderUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showElevationProvider = EditorGUILayout.Foldout(showElevationProvider, "Elevation Provider");
|
||||
|
||||
if (!showElevationProvider)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
prefs.elevationProvider = (RealWorldTerrainElevationProvider) EditorGUILayout.EnumPopup(prefs.elevationProvider);
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The latitude range is 60°S - 60°N.\nThe resolution of the source data is 3 arc seconds(about 90 meters).", MessageType.Info);
|
||||
}
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The latitude range is 60°S - 60°N.\nThe resolution of the source data is 1 arc seconds(about 30 meters).", MessageType.Info);
|
||||
}
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps /*|| prefs.elevationProvider == RealWorldTerrainElevationProvider.ArcGIS*/)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Global coverage.\nThe resolution of the source data:\nUSA - 10 meters, Global 56°S - 60°N - 90 meters, other (including poles) - 900 meters.", MessageType.Info);
|
||||
}
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.Mapbox)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Global coverage.\nThe resolution of the source data up to 5 meters.", MessageType.Info);
|
||||
}
|
||||
|
||||
ElevationProviderExtraFields();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static void ElevationProviderExtraFields()
|
||||
{
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM || prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30)
|
||||
{
|
||||
prefs.ignoreSRTMErrors = EditorGUILayout.Toggle("Ignore SRTM errors", prefs.ignoreSRTMErrors);
|
||||
}
|
||||
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps) BingMapsElevationExtraFields();
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.Mapbox) MapboxElevationExtraFields();
|
||||
else if (prefs.elevationProvider == RealWorldTerrainElevationProvider.SRTM30) SRTM30ExtraFields();
|
||||
}
|
||||
|
||||
private static void MapboxElevationExtraFields()
|
||||
{
|
||||
MapboxAccessToken();
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
|
||||
private static void SRTM30ExtraFields()
|
||||
{
|
||||
if (earthDataLogin == null || earthDataPass == null)
|
||||
{
|
||||
earthDataLogin = RealWorldTerrainPrefs.LoadPref("EarthDataLogin", "");
|
||||
earthDataPass = RealWorldTerrainPrefs.LoadPref("EarthDataPass", "");
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
earthDataLogin = EditorGUILayout.TextField("EarthData username", earthDataLogin);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (earthDataLogin == "") RealWorldTerrainPrefs.DeletePref("EarthDataLogin");
|
||||
else RealWorldTerrainPrefs.SetPref("EarthDataLogin", earthDataLogin);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(earthDataLogin))
|
||||
{
|
||||
GUILayout.Box(new GUIContent(RealWorldTerrainResources.warningIcon, "Required"), RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false));
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
earthDataPass = EditorGUILayout.TextField("EarthData password", earthDataPass);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (earthDataPass == "") RealWorldTerrainPrefs.DeletePref("EarthDataPass");
|
||||
else RealWorldTerrainPrefs.SetPref("EarthDataPass", earthDataPass);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(earthDataPass))
|
||||
{
|
||||
GUILayout.Button(new GUIContent(RealWorldTerrainResources.warningIcon, "Required"), RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false));
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (GUILayout.Button("Register on EarthData", GUILayout.ExpandWidth(true))) Process.Start("https://urs.earthdata.nasa.gov/users/new");
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e450b8bd11e19442833ce383d90bcdd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static List<string> availableGrassType;
|
||||
|
||||
private static void GrassUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
prefs.generateGrass = EditorGUILayout.Toggle("Generate grass", prefs.generateGrass);
|
||||
if (!prefs.generateGrass)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
SelectGrassEngine();
|
||||
|
||||
if (prefs.grassEngine == "Standard") StandardGrassEngineFields();
|
||||
else if (prefs.grassEngine == "Volume Grass") VolumeGrassFields();
|
||||
else if (prefs.grassEngine == "Vegetation Studio") VegetationStudioGrassFields();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static void VegetationStudioGrassFields()
|
||||
{
|
||||
#if VEGETATION_STUDIO || VEGETATION_STUDIO_PRO
|
||||
#if !VEGETATION_STUDIO_PRO
|
||||
prefs.vegetationStudioPackage = EditorGUILayout.ObjectField("Package", prefs.vegetationStudioPackage, typeof(AwesomeTechnologies.VegetationPackage), false) as AwesomeTechnologies.VegetationPackage;
|
||||
#else
|
||||
prefs.vegetationStudioPackage = EditorGUILayout.ObjectField("Package", prefs.vegetationStudioPackage, typeof(AwesomeTechnologies.VegetationSystem.VegetationPackagePro), false) as AwesomeTechnologies.VegetationSystem.VegetationPackagePro;
|
||||
#endif
|
||||
if (prefs.vegetationStudioGrassTypes == null) prefs.vegetationStudioGrassTypes = new List<int> {1};
|
||||
|
||||
int removeIndex = -1;
|
||||
for (int i = 0; i < prefs.vegetationStudioGrassTypes.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
prefs.vegetationStudioGrassTypes[i] = EditorGUILayout.IntSlider("Vegetation Type " + (i + 1) + ": ", prefs.vegetationStudioGrassTypes[i], 1, 32);
|
||||
if (prefs.vegetationStudioGrassTypes.Count > 1 && GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.vegetationStudioGrassTypes.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add item")) prefs.vegetationStudioGrassTypes.Add(1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private static void VolumeGrassFields()
|
||||
{
|
||||
#if VOLUMEGRASS
|
||||
EditorGUILayout.HelpBox("Important: points outside terrains can crash Unity Editor.", MessageType.Info);
|
||||
prefs.volumeGrassOutsidePoints = (RealWorldTerrainVolumeGrassOutsidePoints) EditorGUILayout.EnumPopup("Outside Points", prefs.volumeGrassOutsidePoints);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void StandardGrassEngineFields()
|
||||
{
|
||||
prefs.grassDensity = EditorGUILayout.IntField("Density (%)", prefs.grassDensity);
|
||||
if (prefs.grassDensity < 1) prefs.grassDensity = 1;
|
||||
if (prefs.grassPrefabs == null) prefs.grassPrefabs = new List<Texture2D>();
|
||||
|
||||
EditorGUILayout.LabelField("Grass Prefabs");
|
||||
for (int i = 0; i < prefs.grassPrefabs.Count; i++)
|
||||
{
|
||||
prefs.grassPrefabs[i] =
|
||||
(Texture2D)
|
||||
EditorGUILayout.ObjectField(i + 1 + ":", prefs.grassPrefabs[i], typeof(Texture2D), false);
|
||||
}
|
||||
|
||||
Texture2D newGrass =
|
||||
(Texture2D)
|
||||
EditorGUILayout.ObjectField(prefs.grassPrefabs.Count + 1 + ":", null, typeof(Texture2D), false);
|
||||
if (newGrass != null) prefs.grassPrefabs.Add(newGrass);
|
||||
prefs.grassPrefabs.RemoveAll(go => go == null);
|
||||
}
|
||||
|
||||
private static void SelectGrassEngine()
|
||||
{
|
||||
if (availableGrassType.Count > 1)
|
||||
{
|
||||
int grassEngineIndex = availableGrassType.IndexOf(prefs.grassEngine);
|
||||
if (grassEngineIndex == -1) grassEngineIndex = 0;
|
||||
grassEngineIndex = EditorGUILayout.Popup("Grass engine ", grassEngineIndex, availableGrassType.ToArray());
|
||||
prefs.grassEngine = availableGrassType[grassEngineIndex];
|
||||
}
|
||||
else prefs.grassEngine = availableGrassType[0];
|
||||
}
|
||||
|
||||
private static void InitGrassEngines()
|
||||
{
|
||||
availableGrassType = new List<string>();
|
||||
availableGrassType.Add("Standard");
|
||||
#if VOLUMEGRASS
|
||||
availableGrassType.Add("Volume Grass");
|
||||
#endif
|
||||
#if VEGETATION_STUDIO || VEGETATION_STUDIO_PRO
|
||||
availableGrassType.Add("Vegetation Studio");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ddec60e0a0a6e6479429e629ec1cf14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Diagnostics;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
#if HUGETEXTURE
|
||||
private static readonly string[] labelsHugeTexturePageSize = { "256", "512", "1024", "2048", "4096", "8192" };
|
||||
private static readonly int[] valuesHugeTexturePageSize = { 256, 512, 1024, 2048, 4096, 8192 };
|
||||
#endif
|
||||
|
||||
private static void HugeTextureGUI()
|
||||
{
|
||||
#if HUGETEXTURE
|
||||
EditorGUILayout.HelpBox("Important: when using Huge Texture, you cannot use Terrain Layers.", MessageType.Info);
|
||||
|
||||
TextureSourceUI();
|
||||
|
||||
prefs.hugeTexturePageSize = EditorGUILayout.IntPopup("Page Size", prefs.hugeTexturePageSize, labelsHugeTexturePageSize, valuesHugeTexturePageSize);
|
||||
prefs.hugeTextureCols = EditorGUILayout.IntField("Cols", prefs.hugeTextureCols);
|
||||
prefs.hugeTextureRows = EditorGUILayout.IntField("Rows", prefs.hugeTextureRows);
|
||||
|
||||
if (prefs.hugeTextureCols < 1) prefs.hugeTextureCols = 1;
|
||||
if (prefs.hugeTextureRows < 1) prefs.hugeTextureRows = 1;
|
||||
|
||||
long width = prefs.hugeTexturePageSize * prefs.hugeTextureCols;
|
||||
long height = prefs.hugeTexturePageSize * prefs.hugeTextureRows;
|
||||
EditorGUILayout.LabelField("Width", width.ToString());
|
||||
EditorGUILayout.LabelField("Height", height.ToString());
|
||||
EditorGUILayout.LabelField("Total Pages", (prefs.hugeTextureCols * prefs.hugeTextureCols).ToString());
|
||||
|
||||
if (width * height * 3 > 2147483648L)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Width * Height * 3 must be less than or equal to 2 GB (2 147 483 648 bytes).", MessageType.Error);
|
||||
}
|
||||
|
||||
TextureMaxLevelUI();
|
||||
#else
|
||||
EditorGUILayout.HelpBox("HugeTexture is not in the project.", MessageType.Warning);
|
||||
if (GUILayout.Button("Huge Texture")) Process.Start("https://assetstore.unity.com/packages/tools/input-management/huge-texture-163576?aid=1100liByC&pubref=rwt_ht_asset");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50e2498c71e291142be31fe592cabb1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using InfinityCode.RealWorldTerrain.Windows;
|
||||
using UnityEditor;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static void OsmUI()
|
||||
{
|
||||
EditorGUIUtility.labelWidth = LabelWidth + 20;
|
||||
|
||||
if (RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.additional)
|
||||
{
|
||||
prefs.elevationType = (RealWorldTerrainElevationType)EditorGUILayout.EnumPopup("Elevation", prefs.elevationType);
|
||||
}
|
||||
else prefs.elevationType = RealWorldTerrainElevationType.realWorld;
|
||||
|
||||
|
||||
BuildingsUI();
|
||||
RoadsUI();
|
||||
RiversUI();
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
TreesUI();
|
||||
GrassUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
prefs.generateGrass = false;
|
||||
prefs.generateTrees = false;
|
||||
}
|
||||
|
||||
EditorGUIUtility.labelWidth = LabelWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf8d945692cc56c4a8362979015b534a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static bool showPOI;
|
||||
|
||||
private static void PoiUI()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
|
||||
if (prefs.POI == null) prefs.POI = new List<RealWorldTerrainPOI>();
|
||||
|
||||
if (GUILayout.Button(new GUIContent("+", "Add POI"), EditorStyles.toolbarButton, GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
prefs.POI.Add(new RealWorldTerrainPOI("New POI " + (prefs.POI.Count + 1),
|
||||
(prefs.leftLongitude + prefs.rightLongitude) / 2, (prefs.topLatitude + prefs.bottomLatitude) / 2));
|
||||
}
|
||||
|
||||
GUILayout.Label("");
|
||||
|
||||
if (GUILayout.Button("Clear", EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) prefs.POI = new List<RealWorldTerrainPOI>();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (prefs.POI.Count == 0)
|
||||
{
|
||||
GUILayout.Label("POI is not specified.");
|
||||
}
|
||||
|
||||
int poiIndex = 1;
|
||||
int poiDeleteIndex = -1;
|
||||
|
||||
foreach (RealWorldTerrainPOI poi in prefs.POI)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label(poiIndex.ToString(), GUILayout.ExpandWidth(false));
|
||||
poi.title = EditorGUILayout.TextField("", poi.title);
|
||||
GUILayout.Label("Lat", GUILayout.ExpandWidth(false));
|
||||
poi.y = EditorGUILayout.DoubleField("", poi.y, GUILayout.Width(80));
|
||||
GUILayout.Label("Lng", GUILayout.ExpandWidth(false));
|
||||
poi.x = EditorGUILayout.DoubleField("", poi.x, GUILayout.Width(80));
|
||||
if (GUILayout.Button(new GUIContent("X", "Delete POI"), GUILayout.ExpandWidth(false))) poiDeleteIndex = poiIndex - 1;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(16);
|
||||
GUILayout.Label("Altitude", GUILayout.ExpandWidth(false));
|
||||
poi.altitude = EditorGUILayout.FloatField("", poi.altitude, GUILayout.Width(40));
|
||||
GUILayout.Label("Prefab", GUILayout.ExpandWidth(false));
|
||||
poi.prefab = EditorGUILayout.ObjectField("", poi.prefab, typeof(GameObject), false) as GameObject;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
poiIndex++;
|
||||
}
|
||||
|
||||
if (poiDeleteIndex != -1) prefs.POI.RemoveAt(poiDeleteIndex);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2f50c1586916674592ee423773ff5ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using InfinityCode.RealWorldTerrain.Generators;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static List<string> availableRiverEngines;
|
||||
private static string[] availableRiverEnginesArr;
|
||||
|
||||
private static void InitRiverEngines()
|
||||
{
|
||||
availableRiverEngines = new List<string> {
|
||||
RealWorldTerrainRiverGenerator.BUILTIN_RIVER_ENGINE,
|
||||
#if RAM2019
|
||||
RealWorldTerrainRiverGenerator.RAM2019_RIVER_ENGINE
|
||||
#endif
|
||||
};
|
||||
|
||||
availableRiverEnginesArr = availableRiverEngines.ToArray();
|
||||
}
|
||||
|
||||
private static void RiversUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
prefs.generateRivers = EditorGUILayout.Toggle("Generate rivers", prefs.generateRivers);
|
||||
|
||||
if (!prefs.generateRivers)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
int riverEngineIndex = availableRiverEngines.IndexOf(prefs.riverEngine);
|
||||
if (riverEngineIndex == -1)
|
||||
{
|
||||
riverEngineIndex = 0;
|
||||
prefs.riverEngine = availableRiverEnginesArr[0];
|
||||
}
|
||||
int ri = EditorGUILayout.Popup("River Engine", riverEngineIndex, availableRiverEnginesArr);
|
||||
if (ri != riverEngineIndex) prefs.riverEngine = availableRiverEnginesArr[ri];
|
||||
|
||||
if (prefs.riverEngine == RealWorldTerrainRiverGenerator.BUILTIN_RIVER_ENGINE)
|
||||
{
|
||||
prefs.riverMaterial = EditorGUILayout.ObjectField("Material", prefs.riverMaterial, typeof(Material), false) as Material;
|
||||
}
|
||||
else if (prefs.riverEngine == RealWorldTerrainRiverGenerator.RAM2019_RIVER_ENGINE)
|
||||
{
|
||||
#if RAM2019
|
||||
prefs.ramAreaProfile = EditorGUILayout.ObjectField("Area Profile", prefs.ramAreaProfile, typeof(LakePolygonProfile), false) as LakePolygonProfile;
|
||||
prefs.ramSplineProfile = EditorGUILayout.ObjectField("Spline Profile", prefs.ramSplineProfile, typeof(SplineProfile), false) as SplineProfile;
|
||||
#endif
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 604a5631442b0a24b825aa03293ef1a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,197 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
#if EASYROADS3D
|
||||
using EasyRoads3Dv3;
|
||||
#endif
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private const string EasyRoadsLabel = "EasyRoads3D";
|
||||
private const string RoadArchitectLabel = "Road Architect";
|
||||
|
||||
private static List<string> availableRoadType;
|
||||
private static string[] roadTypeNames;
|
||||
|
||||
#if EASYROADS3D
|
||||
private static ERModularBase roadNetwork;
|
||||
private static bool needFindRoadNetwork = true;
|
||||
private static string[] erRoadTypeNames;
|
||||
#endif
|
||||
|
||||
private static void EasyRoads3DFields()
|
||||
{
|
||||
prefs.erSnapToTerrain = EditorGUILayout.Toggle("Snap to Terrain", prefs.erSnapToTerrain);
|
||||
|
||||
if (Math.Abs(prefs.erWidthMultiplier - 1) > float.Epsilon && prefs.erGenerateConnection)
|
||||
{
|
||||
EditorGUILayout.HelpBox("If you select any connection, the width of the road will be reset to the default value.", MessageType.Warning);
|
||||
}
|
||||
|
||||
prefs.roadTypeMode = (RealWorldTerrainRoadTypeMode)EditorGUILayout.EnumPopup("Mode", prefs.roadTypeMode);
|
||||
if (prefs.roadTypeMode == RealWorldTerrainRoadTypeMode.simple)
|
||||
{
|
||||
prefs.erWidthMultiplier = EditorGUILayout.FloatField("Width Multiplier", prefs.erWidthMultiplier);
|
||||
}
|
||||
|
||||
prefs.erGenerateConnection = EditorGUILayout.Toggle("Generate Connections", prefs.erGenerateConnection);
|
||||
if (prefs.erGenerateConnection)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Important: the ability to generate connections is in beta. \nThis means that some roads may be not connected. \nWe and AndaSoft are working to improve this feature.", MessageType.Warning);
|
||||
}
|
||||
|
||||
if (prefs.roadTypeMode == RealWorldTerrainRoadTypeMode.simple)
|
||||
{
|
||||
prefs.roadTypes = (RealWorldTerrainRoadType)EditorGUILayout.EnumFlagsField("Road types", prefs.roadTypes);
|
||||
}
|
||||
else if (prefs.roadTypeMode == RealWorldTerrainRoadTypeMode.advanced)
|
||||
{
|
||||
#if EASYROADS3D
|
||||
if (roadNetwork == null && needFindRoadNetwork)
|
||||
{
|
||||
roadNetwork = RealWorldTerrainUtils.FindObjectOfType<ERModularBase>();
|
||||
needFindRoadNetwork = false;
|
||||
}
|
||||
|
||||
if (roadNetwork == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Mode - Advanced requires a road network in the scene.", MessageType.Error);
|
||||
|
||||
if (GUILayout.Button("Find Road Network in scene"))
|
||||
{
|
||||
roadNetwork = RealWorldTerrainUtils.FindObjectOfType<ERModularBase>();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Create Road Network"))
|
||||
{
|
||||
ERRoadNetwork newRoadNetwork = new ERRoadNetwork();
|
||||
roadNetwork = newRoadNetwork.roadNetwork;
|
||||
}
|
||||
}
|
||||
|
||||
if (roadTypeNames == null) roadTypeNames = Enum.GetNames(typeof(RealWorldTerrainRoadType));
|
||||
|
||||
if (roadNetwork == null)
|
||||
{
|
||||
foreach (string name in roadTypeNames) EditorGUILayout.LabelField(ObjectNames.NicifyVariableName(name));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (erRoadTypeNames == null) UpdateERRoadTypes();
|
||||
|
||||
if (GUILayout.Button("Update EasyRoad3D Road Types")) UpdateERRoadTypes();
|
||||
|
||||
if (erRoadTypeNames != null)
|
||||
{
|
||||
if (prefs.erRoadTypes == null) prefs.erRoadTypes = new string[roadTypeNames.Length];
|
||||
if (prefs.erRoadTypes.Length != erRoadTypeNames.Length) Array.Resize(ref prefs.erRoadTypes, roadTypeNames.Length);
|
||||
|
||||
for (int i = 0; i < roadTypeNames.Length; i++)
|
||||
{
|
||||
int index = 0;
|
||||
string roadTypeName = prefs.erRoadTypes[i];
|
||||
|
||||
if (!string.IsNullOrEmpty(roadTypeName))
|
||||
{
|
||||
for (int j = 0; j < erRoadTypeNames.Length; j++)
|
||||
{
|
||||
if (erRoadTypeNames[j] == roadTypeName)
|
||||
{
|
||||
index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index = EditorGUILayout.Popup(ObjectNames.NicifyVariableName(roadTypeNames[i]), index, erRoadTypeNames);
|
||||
if (index != 0) prefs.erRoadTypes[i] = erRoadTypeNames[index];
|
||||
else prefs.erRoadTypes[i] = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitRoadEngines()
|
||||
{
|
||||
availableRoadType = new List<string>();
|
||||
#if EASYROADS3D
|
||||
availableRoadType.Add(EasyRoadsLabel);
|
||||
#endif
|
||||
#if ROADARCHITECT
|
||||
availableRoadType.Add(RoadArchitectLabel);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
private static void RoadArchitectFields()
|
||||
{
|
||||
prefs.roadTypeMode = RealWorldTerrainRoadTypeMode.simple;
|
||||
prefs.roadTypes = (RealWorldTerrainRoadType)EditorGUILayout.EnumFlagsField("Road types", prefs.roadTypes);
|
||||
}
|
||||
|
||||
private static void RoadsUI()
|
||||
{
|
||||
if (availableRoadType.Count == 0)
|
||||
{
|
||||
prefs.generateRoads = false;
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
prefs.generateRoads = EditorGUILayout.Toggle("Generate roads", prefs.generateRoads);
|
||||
|
||||
if (!prefs.generateRoads)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox("If the selected area contains cities, generation of roads can take a VERY long time.", MessageType.Info);
|
||||
|
||||
SelectRoadEngine();
|
||||
|
||||
prefs.normalizeRoadDistances = EditorGUILayout.Toggle("Normalize Road Distances", prefs.normalizeRoadDistances);
|
||||
|
||||
if (prefs.roadEngine == EasyRoadsLabel) EasyRoads3DFields();
|
||||
else if (prefs.roadEngine == RoadArchitectLabel) RoadArchitectFields();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
private static void SelectRoadEngine()
|
||||
{
|
||||
if (availableRoadType.Count == 1)
|
||||
{
|
||||
EditorGUILayout.LabelField("Road engine - " + availableRoadType[0]);
|
||||
prefs.roadEngine = availableRoadType[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
int roadEngineIndex = availableRoadType.IndexOf(prefs.roadEngine);
|
||||
if (roadEngineIndex == -1) roadEngineIndex = 0;
|
||||
roadEngineIndex = EditorGUILayout.Popup("Road engine", roadEngineIndex, availableRoadType.ToArray());
|
||||
prefs.roadEngine = availableRoadType[roadEngineIndex];
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateERRoadTypes()
|
||||
{
|
||||
#if EASYROADS3D
|
||||
ERRoadType[] erRoadTypes = roadNetwork.GetRoadTypes();
|
||||
if (erRoadTypes != null) erRoadTypeNames = new[] { "Ignore" }.Concat(erRoadTypes.Select(t => t.roadTypeName)).ToArray();
|
||||
else erRoadTypeNames = null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccdf09dcd9e60ba4abf323ac7e51cee9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,213 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using InfinityCode.RealWorldTerrain.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static readonly string[] labelsBaseMapRes = { "16", "32", "64", "128", "256", "512", "1024", "2048" };
|
||||
private static readonly int[] valuesBaseMapRes = { 16, 32, 64, 128, 256, 512, 1024, 2048 };
|
||||
private static bool showTerrains = true;
|
||||
|
||||
private static void CountTerrainsUI()
|
||||
{
|
||||
if (prefs.resultType != RealWorldTerrainResultType.terrain && prefs.resultType != RealWorldTerrainResultType.mesh) return;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Count terrains. X");
|
||||
prefs.terrainCount.x = Mathf.Max(EditorGUILayout.IntField(prefs.terrainCount.x), 1);
|
||||
GUILayout.Label("Z");
|
||||
prefs.terrainCount.y = Mathf.Max(EditorGUILayout.IntField(prefs.terrainCount.y), 1);
|
||||
DrawHelpButton("The number of terrains horizontally and vertically (XZ axis).");
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private static void ElevationRangeUI()
|
||||
{
|
||||
if (prefs.resultType == RealWorldTerrainResultType.rawFile) return;
|
||||
|
||||
prefs.elevationRange = (RealWorldTerrainElevationRange) EditorGUILayout.EnumPopup("Elevation range", prefs.elevationRange);
|
||||
if (prefs.elevationRange == RealWorldTerrainElevationRange.autoDetect)
|
||||
{
|
||||
prefs.autoDetectElevationOffset.x = EditorGUILayout.FloatField("Min elevation offset", prefs.autoDetectElevationOffset.x);
|
||||
prefs.autoDetectElevationOffset.y = EditorGUILayout.FloatField("Max elevation offset", prefs.autoDetectElevationOffset.y);
|
||||
}
|
||||
else if (prefs.elevationRange == RealWorldTerrainElevationRange.fixedValue)
|
||||
{
|
||||
prefs.fixedMinElevation = EditorGUILayout.FloatField("Min elevation", prefs.fixedMinElevation);
|
||||
prefs.fixedMaxElevation = EditorGUILayout.FloatField("Max elevation", prefs.fixedMaxElevation);
|
||||
}
|
||||
else if (prefs.elevationRange == RealWorldTerrainElevationRange.realWorldValue)
|
||||
{
|
||||
EditorGUILayout.HelpBox("When using Elevation range - Real World Value, you can have steps in the hills.\nThis is due to the way the Unity Terrain Engine stores elevation data.\nUse Elevation range - Real World Value only for areas that have a very wide range of heights, and when you are sure that you really need it!", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GaiaStampFields()
|
||||
{
|
||||
#if !GAIA_PRESENT && !GAIA_PRO_PRESENT && !GAIA_2_PRESENT && !GAIA_2023
|
||||
EditorGUILayout.HelpBox("Gaia not found. Import Gaia into the project.", MessageType.Error);
|
||||
#endif
|
||||
prefs.gaiaStampResolution = EditorGUILayout.IntField("Stamp Resolution", prefs.gaiaStampResolution);
|
||||
}
|
||||
|
||||
private static void GenerateUnderwaterUI()
|
||||
{
|
||||
prefs.generateUnderWater = EditorGUILayout.Toggle("Generate Underwater", prefs.generateUnderWater);
|
||||
|
||||
if (!prefs.generateUnderWater) return;
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
int nodata = IntField(
|
||||
"Max Underwater Depth",
|
||||
prefs.nodataValue,
|
||||
"SRTM v4.1 does not contain data on the underwater depths. Real World Terrain generates it by closest known areas of land. \nSpecify a value relative to sea level. \nFor example, if you want to get a depth of 200 meters, set the value \"-200\"."
|
||||
);
|
||||
if (nodata < short.MinValue) nodata = short.MinValue;
|
||||
if (nodata > short.MaxValue) nodata = short.MaxValue;
|
||||
prefs.depthSharpness = FloatField(
|
||||
"Depth Sharpness",
|
||||
prefs.depthSharpness,
|
||||
"Escarpment of the seabed. \nGreater value - steeper slope.\nUnknown Value = Average Neighbor Known Values - Depth Sharpness."
|
||||
);
|
||||
if (prefs.depthSharpness < 0) prefs.depthSharpness = 0;
|
||||
if (prefs.elevationProvider == RealWorldTerrainElevationProvider.BingMaps) prefs.bingMapsUseZeroAsUnknown = EditorGUILayout.Toggle("Zero Elevation is Unknown", prefs.bingMapsUseZeroAsUnknown);
|
||||
prefs.nodataValue = (short) nodata;
|
||||
prefs.waterDetectionSource = (RealWorldTerrainWaterDetectionSource)EditorGUILayout.EnumPopup("Water Detection Source", prefs.waterDetectionSource);
|
||||
if (prefs.waterDetectionSource == RealWorldTerrainWaterDetectionSource.texture)
|
||||
{
|
||||
prefs.waterDetectionTexture = ObjectField("Water Detection Texture", prefs.waterDetectionTexture, typeof(Texture2D), "The texture of the current area where the water is white and the rest is black.\nThe coordinates of the borders of the texture must match the coordinates of the borders of the generated area.\nMust have Read / Write Enabled - ON.") as Texture2D;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefs.waterDetectionBitMask = ObjectField("Water Detection BitMask", prefs.waterDetectionBitMask, typeof(TextAsset), "The bit mask of the current area where the water is 0 and the rest is 1.") as TextAsset;
|
||||
if (GUILayout.Button("Open BitMask Convertor"))
|
||||
{
|
||||
RealWorldTerrainWaterMaskConverter.OpenWindow();
|
||||
}
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
private static void RawFileFields()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
prefs.rawFilename = EditorGUILayout.TextField("Filename", prefs.rawFilename);
|
||||
if (GUILayout.Button("...", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
GUI.FocusControl(null);
|
||||
string ext = prefs.rawType == RealWorldTerrainRawType.RAW ? "raw" : "png";
|
||||
string rawFilename = EditorUtility.SaveFilePanel("Output RAW filename", Application.dataPath, "terrain." + ext, ext);
|
||||
if (!string.IsNullOrEmpty(rawFilename)) prefs.rawFilename = rawFilename;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
prefs.rawType = (RealWorldTerrainRawType) EditorGUILayout.EnumPopup("Type", prefs.rawType);
|
||||
if (prefs.rawType == RealWorldTerrainRawType.RAW) prefs.rawByteOrder = (RealWorldTerrainByteOrder) EditorGUILayout.EnumPopup("Byte order", prefs.rawByteOrder);
|
||||
prefs.rawWidth = EditorGUILayout.IntField("Width", prefs.rawWidth);
|
||||
prefs.rawHeight = EditorGUILayout.IntField("Height", prefs.rawHeight);
|
||||
}
|
||||
|
||||
private static void TerrainDataSettings()
|
||||
{
|
||||
if (values2n1.All(v => v != prefs.heightmapResolution))
|
||||
{
|
||||
prefs.heightmapResolution = Mathf.ClosestPowerOfTwo(prefs.heightmapResolution) + 1;
|
||||
if (values2n1.All(v => v != prefs.heightmapResolution)) prefs.heightmapResolution = 129;
|
||||
}
|
||||
|
||||
prefs.heightmapResolution =
|
||||
IntPopup("Heightmap Resolution", prefs.heightmapResolution, labels2n1, values2n1,
|
||||
"The Heightmap resolution for each Terrain.", "http://docs.unity3d.com/Documentation/Components/terrain-UsingTerrains.html");
|
||||
|
||||
prefs.detailResolution = IntField("Detail Resolution", prefs.detailResolution,
|
||||
"The resolution of the map that controls grass and detail meshes. For performance reasons (to save on draw calls) the lower you set this number the better.",
|
||||
"http://docs.unity3d.com/Documentation/Components/terrain-UsingTerrains.html");
|
||||
|
||||
prefs.detailResolution = Mathf.Clamp(prefs.detailResolution, 32, 4096);
|
||||
|
||||
prefs.resolutionPerPatch = IntField("Resolution Per Patch", prefs.resolutionPerPatch,
|
||||
"Specifies the size in pixels of each individually rendered detail patch. A larger number reduces draw calls, but might increase triangle count since detail patches are culled on a per batch basis. A recommended value is 16. If you use a very large detail object distance and your grass is very sparse, it makes sense to increase the value.",
|
||||
"http://docs.unity3d.com/Documentation/ScriptReference/TerrainData.SetDetailResolution.html");
|
||||
prefs.resolutionPerPatch = Mathf.Clamp(prefs.resolutionPerPatch, 8, 1000);
|
||||
|
||||
if (prefs.detailResolution % prefs.resolutionPerPatch != 0)
|
||||
{
|
||||
prefs.detailResolution = prefs.detailResolution / prefs.resolutionPerPatch * prefs.resolutionPerPatch;
|
||||
if (prefs.detailResolution < 32) prefs.detailResolution = 32;
|
||||
}
|
||||
|
||||
prefs.controlTextureResolution = IntPopup("Control Texture Resolution", prefs.controlTextureResolution, labels2n, values2n,
|
||||
"Resolution of the splatmap that controls the blending of the different terrain textures.",
|
||||
"http://docs.unity3d.com/Documentation/Components/terrain-UsingTerrains.html");
|
||||
|
||||
prefs.baseMapResolution = IntPopup("Base Map Resolution", prefs.baseMapResolution, labelsBaseMapRes, valuesBaseMapRes,
|
||||
"The resolution of the composite texture that is used in place of the splat map at certain distances.",
|
||||
"http://docs.unity3d.com/Documentation/Components/terrain-UsingTerrains.html");
|
||||
|
||||
if (!valuesBaseMapRes.Contains(prefs.baseMapResolution)) prefs.baseMapResolution = 1024;
|
||||
}
|
||||
|
||||
private static void TerrainFullFields()
|
||||
{
|
||||
prefs.resultType = (RealWorldTerrainResultType)EnumPopup("Result", prefs.resultType, "The type of the generated object.");
|
||||
|
||||
CountTerrainsUI();
|
||||
|
||||
prefs.alignWaterLine = Toggle("Align Water Line", prefs.alignWaterLine, false,
|
||||
"If disabled terrains will have zero Y at minimum elevation.\nIf enabled, terrains will have zero Y on the water line(zero elevation).");
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.gaiaStamp) GaiaStampFields();
|
||||
else if (prefs.resultType == RealWorldTerrainResultType.rawFile) RawFileFields();
|
||||
else TerrainSizeTypeUI();
|
||||
|
||||
ElevationRangeUI();
|
||||
}
|
||||
|
||||
private static void TerrainSizeTypeUI()
|
||||
{
|
||||
prefs.sizeType = IntPopup(
|
||||
"Size type",
|
||||
prefs.sizeType, new[] {"Real world sizes", "Mercator sizes", "Fixed size"},
|
||||
new[] {0, 1, 2},
|
||||
"Specifies whether the projection will be determined by the size of the area.",
|
||||
new[] {"http://en.wikipedia.org/wiki/Cylindrical_equal-area_projection", "http://en.wikipedia.org/wiki/Mercator_projection"}
|
||||
);
|
||||
|
||||
if (prefs.sizeType == 2)
|
||||
{
|
||||
prefs.fixedTerrainSize.x = FloatField("Terrain Width", prefs.fixedTerrainSize.x, "Width of each terrain (units)");
|
||||
prefs.fixedTerrainSize.z = FloatField("Terrain Length", prefs.fixedTerrainSize.z, "Length of each terrain (units)");
|
||||
prefs.terrainScale.y = FloatField("Scale Y", prefs.terrainScale.y, "The scale of the elevations.");
|
||||
}
|
||||
else prefs.terrainScale = Vector3Field("Scale", prefs.terrainScale, "The scale of the resulting objects.");
|
||||
}
|
||||
|
||||
private static void TerrainUI()
|
||||
{
|
||||
if (generateType == RealWorldTerrainGenerateType.full) TerrainFullFields();
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain) GenerateUnderwaterUI();
|
||||
else prefs.generateUnderWater = false;
|
||||
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain) TerrainDataSettings();
|
||||
else if (prefs.resultType == RealWorldTerrainResultType.mesh)
|
||||
{
|
||||
prefs.heightmapResolution =
|
||||
RealWorldTerrainMath.Limit(IntField("Height Map Resolution", prefs.heightmapResolution,
|
||||
"Heightmap resolution for each mesh."), 8, 250);
|
||||
}
|
||||
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29aa7a479c145ba4ab7bd267c09fb7b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,202 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private const float TerrainLayerLineHeight = RealWorldTerrainVectorTerrainLayerFeature.TerrainLayerLineHeight;
|
||||
private static ReorderableList terrainLayersList;
|
||||
|
||||
private static void AddVectorTerrainLayerFeature(ReorderableList list)
|
||||
{
|
||||
prefs.vectorTerrainLayers.Add(new RealWorldTerrainVectorTerrainLayerFeature());
|
||||
}
|
||||
|
||||
private static int DrawVectorLayerData(RealWorldTerrainVectorTerrainLayerFeature.Rule rule, int index, ref Rect r)
|
||||
{
|
||||
int ret = 0; // 0 - do nothing, -1 - remove, 1 - update height
|
||||
|
||||
GUI.Label(new Rect(r.x, r.y, r.width - 20, r.height), "Rule " + (index + 1) + ": ");
|
||||
if (GUI.Button(new Rect(r.xMax - 20, r.y, 20, r.height), "X")) ret = -1;
|
||||
r.y += TerrainLayerLineHeight;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
rule.layer = (RealWorldTerrainMapboxLayer)EditorGUI.EnumPopup(r, "Layer", rule.layer);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
rule.extra = ~0;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (rule.hasExtra)
|
||||
{
|
||||
if (rule.layer == RealWorldTerrainMapboxLayer.landuse)
|
||||
{
|
||||
rule.extra = (int)(RealWorldTerrainMapboxLanduse)EditorGUI.EnumFlagsField(r, "Classes", (RealWorldTerrainMapboxLanduse)rule.extra);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
else if (rule.layer == RealWorldTerrainMapboxLayer.landuse_overlay)
|
||||
{
|
||||
rule.extra = (int)(RealWorldTerrainMapboxLanduseOverlay)EditorGUI.EnumFlagsField(r, "Classes", (RealWorldTerrainMapboxLanduseOverlay)rule.extra);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
else if (rule.layer == RealWorldTerrainMapboxLayer.waterway)
|
||||
{
|
||||
rule.extra = (int)(RealWorldTerrainMapboxWaterway)EditorGUI.EnumFlagsField(r, "Classes", (RealWorldTerrainMapboxWaterway)rule.extra);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
else if (rule.layer == RealWorldTerrainMapboxLayer.structure)
|
||||
{
|
||||
rule.extra = (int)(RealWorldTerrainMapboxStructure)EditorGUI.EnumFlagsField(r, "Classes", (RealWorldTerrainMapboxStructure)rule.extra);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void DrawVectorTerrainBaseLayers()
|
||||
{
|
||||
EditorGUILayout.LabelField("Base Layers");
|
||||
if (prefs.vectorTerrainBaseLayers == null) prefs.vectorTerrainBaseLayers = new List<TerrainLayer>();
|
||||
if (prefs.vectorTerrainBaseLayers.Count == 0) prefs.vectorTerrainBaseLayers.Add(null);
|
||||
|
||||
int removeIndex = -1;
|
||||
for (int i = 0; i < prefs.vectorTerrainBaseLayers.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
prefs.vectorTerrainBaseLayers[i] = EditorGUILayout.ObjectField(new GUIContent((i + 1).ToString()), prefs.vectorTerrainBaseLayers[i], typeof(TerrainLayer), false) as TerrainLayer;
|
||||
if (GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (prefs.vectorTerrainBaseLayers.Count > 1)
|
||||
{
|
||||
prefs.vectorTerrainBaseLayersNoiseOffset = EditorGUILayout.Vector2Field("Noise Offset", prefs.vectorTerrainBaseLayersNoiseOffset);
|
||||
prefs.vectorTerrainBaseLayersNoiseScale = EditorGUILayout.FloatField("Noise Scale", prefs.vectorTerrainBaseLayersNoiseScale);
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.vectorTerrainBaseLayers.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add Base Layer")) prefs.vectorTerrainBaseLayers.Add(null);
|
||||
}
|
||||
|
||||
private static void DrawVectorTerrainLayerFeature(Rect rect, int index, bool isactive, bool isfocused)
|
||||
{
|
||||
Rect r = new Rect(rect)
|
||||
{
|
||||
height = TerrainLayerLineHeight - 2
|
||||
};
|
||||
|
||||
RealWorldTerrainVectorTerrainLayerFeature layer = prefs.vectorTerrainLayers[index];
|
||||
GUI.Label(r, "Layer " + (index + 1) + ": ");
|
||||
r.y += TerrainLayerLineHeight;
|
||||
|
||||
if (layer.terrainLayers == null) layer.terrainLayers = new List<TerrainLayer>();
|
||||
if (layer.terrainLayers.Count == 0) layer.terrainLayers.Add(null);
|
||||
|
||||
int removeIndex = -1;
|
||||
|
||||
for (int i = 0; i < layer.terrainLayers.Count; i++)
|
||||
{
|
||||
TerrainLayer terrainLayer = layer.terrainLayers[i];
|
||||
layer.terrainLayers[i] = EditorGUI.ObjectField(new Rect(r.x, r.y, r.width - 20, r.height), new GUIContent("Terrain Layer"), terrainLayer, typeof(TerrainLayer), false) as TerrainLayer;
|
||||
if (GUI.Button(new Rect(r.xMax - 20, r.y, 20, r.height), "X")) removeIndex = i;
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
|
||||
if (layer.terrainLayers.Count > 1)
|
||||
{
|
||||
EditorGUI.LabelField(r, "Noise Offset");
|
||||
float labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 20;
|
||||
float halfWidth = (r.width - labelWidth) / 2;
|
||||
layer.noiseOffset.x = EditorGUI.FloatField(new Rect(r.x + labelWidth, r.y, halfWidth, r.height), "X", layer.noiseOffset.x);
|
||||
layer.noiseOffset.y = EditorGUI.FloatField(new Rect(r.x + labelWidth + halfWidth, r.y, halfWidth, r.height), "Y", layer.noiseOffset.y);
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
r.y += TerrainLayerLineHeight;
|
||||
layer.noiseScale = EditorGUI.FloatField(r, "Noise Scale", layer.noiseScale);
|
||||
r.y += TerrainLayerLineHeight;
|
||||
}
|
||||
|
||||
if (GUI.Button(r, "Add TerrainLayer"))
|
||||
{
|
||||
layer.terrainLayers.Add(null);
|
||||
layer.UpdateHeight();
|
||||
}
|
||||
r.y += TerrainLayerLineHeight;
|
||||
|
||||
if (removeIndex != -1)
|
||||
{
|
||||
layer.terrainLayers.RemoveAt(removeIndex);
|
||||
layer.UpdateHeight();
|
||||
}
|
||||
|
||||
if (layer.rules == null) layer.rules = new List<RealWorldTerrainVectorTerrainLayerFeature.Rule>();
|
||||
|
||||
removeIndex = -1;
|
||||
for (int i = 0; i < layer.rules.Count; i++)
|
||||
{
|
||||
int ret = DrawVectorLayerData(layer.rules[i], i, ref r);
|
||||
if (ret == -1) removeIndex = i;
|
||||
else if (ret == 1) layer.UpdateHeight();
|
||||
}
|
||||
|
||||
if (removeIndex != -1)
|
||||
{
|
||||
layer.rules.RemoveAt(removeIndex);
|
||||
layer.UpdateHeight();
|
||||
}
|
||||
|
||||
if (GUI.Button(r, "Add Rule"))
|
||||
{
|
||||
layer.rules.Add(new RealWorldTerrainVectorTerrainLayerFeature.Rule());
|
||||
layer.UpdateHeight();
|
||||
}
|
||||
}
|
||||
|
||||
private static float HeightVectorTerrainLayerFeature(int index)
|
||||
{
|
||||
if (index < 0 || index >= prefs.vectorTerrainLayers.Count) return 0;
|
||||
RealWorldTerrainVectorTerrainLayerFeature layer = prefs.vectorTerrainLayers[index];
|
||||
return layer.height;
|
||||
}
|
||||
|
||||
private static void RemoveVectorTerrainLayerFeature(ReorderableList list)
|
||||
{
|
||||
prefs.vectorTerrainLayers.RemoveAt(list.index);
|
||||
}
|
||||
|
||||
private static void TerrainLayersUI()
|
||||
{
|
||||
EditorGUILayout.HelpBox("The ability to generate Terrain Layers is in beta. If you have any problems or have suggestions for improving this feature, please contact us (support@infinity-code.com).", MessageType.Info);
|
||||
EditorGUILayout.HelpBox("Important: you can specify materials only for new terrains. During regeneration, modified Terrain Layers will not be assigned. This is some kind of bug in Unity Editor. We are working on finding a way around this.", MessageType.Warning);
|
||||
|
||||
MapboxAccessToken();
|
||||
TextureMaxLevelUI();
|
||||
DrawVectorTerrainBaseLayers();
|
||||
|
||||
if (prefs.vectorTerrainLayers == null) prefs.vectorTerrainLayers = new List<RealWorldTerrainVectorTerrainLayerFeature>();
|
||||
|
||||
if (terrainLayersList == null)
|
||||
{
|
||||
terrainLayersList = new ReorderableList(prefs.vectorTerrainLayers, typeof(RealWorldTerrainVectorTerrainLayerFeature), true, true, true, true);
|
||||
terrainLayersList.drawElementCallback += DrawVectorTerrainLayerFeature;
|
||||
terrainLayersList.drawHeaderCallback += r => GUI.Label(r, "Layers");
|
||||
terrainLayersList.onAddCallback += AddVectorTerrainLayerFeature;
|
||||
terrainLayersList.onRemoveCallback += RemoveVectorTerrainLayerFeature;
|
||||
terrainLayersList.elementHeightCallback += HeightVectorTerrainLayerFeature;
|
||||
}
|
||||
|
||||
terrainLayersList.DoLayoutList();
|
||||
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e48b6a827433d84e9505d9925afc5d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,256 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static readonly string[] labelsTextureSize = { "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192", "12288", "16384", "20480", "26624" };
|
||||
private static readonly int[] valuesTextureSize = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 12288, 16384, 20480, 26624 };
|
||||
|
||||
private static int providerIndex;
|
||||
private static string[] providersTitle;
|
||||
private static RealWorldTerrainTextureProviderManager.Provider[] providers;
|
||||
private static bool showCustomProviderTokens;
|
||||
private static bool showTextures = true;
|
||||
|
||||
public static void InitTextureProviders()
|
||||
{
|
||||
providersTitle = RealWorldTerrainTextureProviderManager.GetProvidersTitle();
|
||||
providers = RealWorldTerrainTextureProviderManager.GetProviders();
|
||||
|
||||
if (prefs.mapType == null) prefs.mapType = RealWorldTerrainTextureProviderManager.FindMapType(prefs.mapTypeID);
|
||||
providerIndex = prefs.mapType.provider.index;
|
||||
}
|
||||
|
||||
private static void PrecalculateMaxLevel()
|
||||
{
|
||||
int tx = 0;
|
||||
int ty = 0;
|
||||
int textureLevel = 0;
|
||||
|
||||
if (prefs.textureResultType == RealWorldTerrainTextureResultType.regularTexture)
|
||||
{
|
||||
tx = prefs.textureSize.x * prefs.terrainCount.x / 256;
|
||||
ty = prefs.textureSize.y * prefs.terrainCount.y / 256;
|
||||
}
|
||||
else if (prefs.textureResultType == RealWorldTerrainTextureResultType.hugeTexture)
|
||||
{
|
||||
tx = prefs.hugeTexturePageSize * prefs.hugeTextureCols * prefs.terrainCount.x / 256;
|
||||
ty = prefs.hugeTexturePageSize * prefs.hugeTextureRows * prefs.terrainCount.y / 256;
|
||||
}
|
||||
else if (prefs.textureResultType == RealWorldTerrainTextureResultType.terrainLayers)
|
||||
{
|
||||
tx = prefs.controlTextureResolution * prefs.terrainCount.x / 256;
|
||||
ty = prefs.controlTextureResolution * prefs.terrainCount.y / 256;
|
||||
}
|
||||
|
||||
for (int z = 5; z < 22; z++)
|
||||
{
|
||||
double stx, sty, etx, ety;
|
||||
RealWorldTerrainGeo.LatLongToTile(prefs.leftLongitude, prefs.topLatitude, z, out stx, out sty);
|
||||
RealWorldTerrainGeo.LatLongToTile(prefs.rightLongitude, prefs.bottomLatitude, z, out etx, out ety);
|
||||
|
||||
if (etx < stx) etx += 1 << z;
|
||||
|
||||
if (etx - stx > tx && ety - sty > ty)
|
||||
{
|
||||
textureLevel = z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (textureLevel == 0) textureLevel = 22;
|
||||
|
||||
EditorGUILayout.HelpBox("Texture level = " + textureLevel + " will be used.", MessageType.Info);
|
||||
}
|
||||
|
||||
private static void RegularTextureUI()
|
||||
{
|
||||
TextureSourceUI();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Texture width");
|
||||
prefs.textureSize.x = EditorGUILayout.IntPopup(prefs.textureSize.x, labelsTextureSize, valuesTextureSize);
|
||||
GUILayout.Label("height");
|
||||
prefs.textureSize.y = EditorGUILayout.IntPopup(prefs.textureSize.y, labelsTextureSize, valuesTextureSize);
|
||||
DrawHelpButton("Texture size for each terrains.");
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (prefs.textureSize.x > 8192 || prefs.textureSize.y > 8192)
|
||||
{
|
||||
#if !HUGETEXTURE
|
||||
EditorGUILayout.HelpBox("To use textures with side sizes larger than 8192 px, you must have a Huge Texture asset in the project.", MessageType.Error);
|
||||
if (GUILayout.Button("Huge Texture")) Process.Start("https://assetstore.unity.com/packages/tools/input-management/huge-texture-163576");
|
||||
#else
|
||||
EditorGUILayout.HelpBox("To use textures with side sizes larger than 8192 px switch to Result Type - Huge Texture.", MessageType.Error);
|
||||
if (GUILayout.Button("Set Result Type - Huge Texture"))
|
||||
{
|
||||
prefs.textureResultType = RealWorldTerrainTextureResultType.hugeTexture;
|
||||
prefs.hugeTexturePageSize = 1024;
|
||||
prefs.hugeTextureCols = Mathf.CeilToInt(prefs.textureSize.x / (float)prefs.hugeTexturePageSize);
|
||||
prefs.hugeTextureRows = Mathf.CeilToInt(prefs.textureSize.y / (float)prefs.hugeTexturePageSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
prefs.textureMipMaps = Toggle(prefs.textureMipMaps, "Mipmaps", false, "Mipmaps are lists of progressively smaller versions of an image, used to optimize performance on real-time 3D engines. Objects that are far away from the Camera use smaller Texture versions.");
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
prefs.textureFileType = (RealWorldTerrainTextureFileType)EnumPopup("Format", prefs.textureFileType, "Texture format. PNG is highly recommended to avoid double quality loss due to compression.");
|
||||
if (prefs.textureFileType == RealWorldTerrainTextureFileType.jpg) prefs.textureFileQuality = EditorGUILayout.IntSlider("Quality", prefs.textureFileQuality, 0, 100);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
TextureMaxLevelUI();
|
||||
}
|
||||
|
||||
private static void TextureUI()
|
||||
{
|
||||
prefs.textureResultType = (RealWorldTerrainTextureResultType)EnumPopup("Result Type", prefs.textureResultType, "The type of the resulting texture.");
|
||||
|
||||
if (prefs.textureResultType == RealWorldTerrainTextureResultType.regularTexture) RegularTextureUI();
|
||||
else if (prefs.textureResultType == RealWorldTerrainTextureResultType.hugeTexture) HugeTextureGUI();
|
||||
else if (prefs.textureResultType == RealWorldTerrainTextureResultType.terrainLayers) TerrainLayersUI();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
private static void TextureMaxLevelUI()
|
||||
{
|
||||
List<string> levels = new List<string> { "Auto" };
|
||||
for (int i = 5; i < 23; i++) levels.Add(i.ToString());
|
||||
int index = prefs.maxTextureLevel;
|
||||
if (index != 0) index -= 4;
|
||||
index = EditorGUILayout.Popup("Max level", index, levels.ToArray());
|
||||
prefs.maxTextureLevel = index;
|
||||
if (index != 0) prefs.maxTextureLevel += 4;
|
||||
else
|
||||
{
|
||||
PrecalculateMaxLevel();
|
||||
prefs.reduceTextures = Toggle(prefs.reduceTextures, "Reduce size of textures, with no levels of tiles?", true,
|
||||
"Reducing the size of the texture, reduces the time texture generation and memory usage.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void TextureSourceUI()
|
||||
{
|
||||
TextureProviderUI();
|
||||
|
||||
if (prefs.mapType.provider.types.Length > 1)
|
||||
{
|
||||
GUIContent[] availableTypes = prefs.mapType.provider.types.Select(t => new GUIContent(t.title)).ToArray();
|
||||
int mti = prefs.mapType.index;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
mti = EditorGUILayout.Popup(new GUIContent("Type", "Type of map texture"), mti, availableTypes);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
prefs.mapType = prefs.mapType.provider.types[mti];
|
||||
prefs.mapTypeID = prefs.mapType.fullID;
|
||||
}
|
||||
}
|
||||
|
||||
TextureProviderExtraFields();
|
||||
TextureProviderHelp();
|
||||
}
|
||||
|
||||
private static void TextureProviderExtraFields()
|
||||
{
|
||||
RealWorldTerrainTextureProviderManager.IExtraField[] extraFields = prefs.mapType.extraFields;
|
||||
if (extraFields != null)
|
||||
{
|
||||
foreach (RealWorldTerrainTextureProviderManager.IExtraField field in extraFields)
|
||||
{
|
||||
if (field is RealWorldTerrainTextureProviderManager.ToggleExtraGroup) TextureProviderToggleExtraGroup(field as RealWorldTerrainTextureProviderManager.ToggleExtraGroup);
|
||||
else if (field is RealWorldTerrainTextureProviderManager.ExtraField) TextureProviderExtraField(field as RealWorldTerrainTextureProviderManager.ExtraField);
|
||||
}
|
||||
}
|
||||
|
||||
extraFields = prefs.mapType.provider.extraFields;
|
||||
if (extraFields != null)
|
||||
{
|
||||
foreach (RealWorldTerrainTextureProviderManager.IExtraField field in extraFields)
|
||||
{
|
||||
if (field is RealWorldTerrainTextureProviderManager.ToggleExtraGroup) TextureProviderToggleExtraGroup(field as RealWorldTerrainTextureProviderManager.ToggleExtraGroup);
|
||||
else if (field is RealWorldTerrainTextureProviderManager.ExtraField) TextureProviderExtraField(field as RealWorldTerrainTextureProviderManager.ExtraField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TextureProviderExtraField(RealWorldTerrainTextureProviderManager.ExtraField field)
|
||||
{
|
||||
field.value = EditorGUILayout.TextField(field.title, field.value);
|
||||
}
|
||||
|
||||
private static void TextureProviderHelp()
|
||||
{
|
||||
string[] help = prefs.mapType.help;
|
||||
if (help != null)
|
||||
{
|
||||
foreach (string field in help)
|
||||
{
|
||||
EditorGUILayout.HelpBox(field, MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
help = prefs.mapType.provider.help;
|
||||
if (help != null)
|
||||
{
|
||||
foreach (string field in help)
|
||||
{
|
||||
EditorGUILayout.HelpBox(field, MessageType.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TextureProviderToggleExtraGroup(RealWorldTerrainTextureProviderManager.ToggleExtraGroup @group)
|
||||
{
|
||||
@group.value = EditorGUILayout.Toggle(@group.title, @group.value);
|
||||
EditorGUI.BeginDisabledGroup(@group.value);
|
||||
|
||||
if (@group.fields != null)
|
||||
{
|
||||
foreach (RealWorldTerrainTextureProviderManager.IExtraField field in @group.fields)
|
||||
{
|
||||
if (field is RealWorldTerrainTextureProviderManager.ToggleExtraGroup) TextureProviderToggleExtraGroup(field as RealWorldTerrainTextureProviderManager.ToggleExtraGroup);
|
||||
else if (field is RealWorldTerrainTextureProviderManager.ExtraField) TextureProviderExtraField(field as RealWorldTerrainTextureProviderManager.ExtraField);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
private static void TextureProviderUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
providerIndex = Popup("Provider", providerIndex, providersTitle, "Source of tiles for generating texture.");
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
prefs.mapType = providers[providerIndex].types[0];
|
||||
prefs.mapTypeID = prefs.mapType.fullID;
|
||||
}
|
||||
|
||||
if (prefs.mapType.isCustom)
|
||||
{
|
||||
prefs.textureProviderURL = EditorGUILayout.TextField(prefs.textureProviderURL);
|
||||
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showCustomProviderTokens = Foldout(showCustomProviderTokens, "Available tokens");
|
||||
if (showCustomProviderTokens)
|
||||
{
|
||||
GUILayout.Label("{zoom}");
|
||||
GUILayout.Label("{x}");
|
||||
GUILayout.Label("{y}");
|
||||
GUILayout.Label("{quad}");
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2af5474c91bbe340bfb60ba389fdc6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using InfinityCode.RealWorldTerrain.Editors;
|
||||
using InfinityCode.RealWorldTerrain.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static void ToolbarUI()
|
||||
{
|
||||
GUIStyle buttonStyle = new GUIStyle(EditorStyles.toolbarButton);
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
ToolbarFileUI(buttonStyle);
|
||||
|
||||
if (GUILayout.Button("History", buttonStyle, GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
RealWorldTerrainHistoryWindow.OpenWindow();
|
||||
}
|
||||
|
||||
ToolbarUpdateUI(buttonStyle);
|
||||
|
||||
if (GUILayout.Button("Settings", buttonStyle, GUILayout.ExpandWidth(false))) RealWorldTerrainSettingsWindow.OpenWindow();
|
||||
|
||||
ToolbarHelpUI(buttonStyle);
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
private static void ToolbarFileUI(GUIStyle buttonStyle)
|
||||
{
|
||||
if (GUILayout.Button("File", buttonStyle, GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
GenericMenu menu = new GenericMenu();
|
||||
menu.AddItem(new GUIContent("Import Prefs"), false, () =>
|
||||
{
|
||||
string filename = EditorUtility.OpenFilePanel("Import Prefs", Application.dataPath, "xml");
|
||||
if (!string.IsNullOrEmpty(filename)) prefs.LoadFromXML(filename);
|
||||
});
|
||||
menu.AddItem(new GUIContent("Export Prefs"), false, () =>
|
||||
{
|
||||
string filename = EditorUtility.SaveFilePanel("Import Prefs", Application.dataPath, "Prefs", "xml");
|
||||
if (!string.IsNullOrEmpty(filename)) File.WriteAllText(filename, prefs.ToXML(new XmlDocument()).OuterXml, Encoding.UTF8);
|
||||
});
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ToolbarHelpUI(GUIStyle buttonStyle)
|
||||
{
|
||||
if (GUILayout.Button("Help", buttonStyle, GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
GenericMenu menu = new GenericMenu();
|
||||
|
||||
menu.AddItem(new GUIContent("Documentation"), false, RealWorldTerrainLinks.OpenLocalDocumentation);
|
||||
menu.AddItem(new GUIContent("Changelog"), false, RealWorldTerrainLinks.OpenChangelog);
|
||||
menu.AddSeparator("");
|
||||
menu.AddItem(new GUIContent("Asset Store"), false, RealWorldTerrainLinks.OpenAssetStore);
|
||||
menu.AddItem(new GUIContent("Homepage"), false, RealWorldTerrainLinks.OpenHomepage);
|
||||
menu.AddItem(new GUIContent("Support"), false, RealWorldTerrainLinks.OpenSupport);
|
||||
menu.AddItem(new GUIContent("Forum"), false, RealWorldTerrainLinks.OpenForum);
|
||||
menu.AddItem(new GUIContent("Discord"), false, RealWorldTerrainLinks.OpenDiscord);
|
||||
menu.AddSeparator("");
|
||||
menu.AddItem(new GUIContent("Check Updates"), false, RealWorldTerrainUpdaterWindow.OpenWindow);
|
||||
menu.AddItem(new GUIContent("About"), false, RealWorldTerrainAboutWindow.OpenWindow);
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ToolbarUpdateUI(GUIStyle buttonStyle)
|
||||
{
|
||||
if (!RealWorldTerrainUpdaterWindow.hasNewVersion)
|
||||
{
|
||||
GUILayout.Label("", buttonStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
Color defColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = new Color(1, 0.5f, 0.5f);
|
||||
if (GUILayout.Button("New version available!!! Click here to update.", buttonStyle))
|
||||
{
|
||||
wnd.Close();
|
||||
RealWorldTerrainUpdaterWindow.OpenWindow();
|
||||
}
|
||||
|
||||
GUI.backgroundColor = defColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c295bc603ee4e545b6c21c00fa1faa7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,99 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private static List<string> availableTreeType;
|
||||
|
||||
private static void StandardTreeEngineFields()
|
||||
{
|
||||
prefs.treeDensity = EditorGUILayout.IntField("Density (%)", prefs.treeDensity);
|
||||
if (prefs.treeDensity < 1) prefs.treeDensity = 1;
|
||||
if (prefs.treePrefabs == null) prefs.treePrefabs = new List<GameObject>();
|
||||
EditorGUILayout.LabelField("Tree Prefabs");
|
||||
for (int i = 0; i < prefs.treePrefabs.Count; i++)
|
||||
{
|
||||
prefs.treePrefabs[i] =
|
||||
(GameObject)
|
||||
EditorGUILayout.ObjectField(i + 1 + ":", prefs.treePrefabs[i], typeof(GameObject), false);
|
||||
}
|
||||
|
||||
GameObject newTree =
|
||||
(GameObject)
|
||||
EditorGUILayout.ObjectField(prefs.treePrefabs.Count + 1 + ":", null, typeof(GameObject), false);
|
||||
if (newTree != null) prefs.treePrefabs.Add(newTree);
|
||||
prefs.treePrefabs.RemoveAll(go => go == null);
|
||||
}
|
||||
|
||||
private static void VegetationStudioTreeEngineFields()
|
||||
{
|
||||
#if VEGETATION_STUDIO || VEGETATION_STUDIO_PRO
|
||||
#if !VEGETATION_STUDIO_PRO
|
||||
prefs.vegetationStudioPackage = EditorGUILayout.ObjectField("Package", prefs.vegetationStudioPackage, typeof(AwesomeTechnologies.VegetationPackage), false) as AwesomeTechnologies.VegetationPackage;
|
||||
#else
|
||||
prefs.vegetationStudioPackage = EditorGUILayout.ObjectField("Package", prefs.vegetationStudioPackage, typeof(AwesomeTechnologies.VegetationSystem.VegetationPackagePro), false) as AwesomeTechnologies.VegetationSystem.VegetationPackagePro;
|
||||
#endif
|
||||
if (prefs.vegetationStudioTreeTypes == null) prefs.vegetationStudioTreeTypes = new List<int>{1};
|
||||
|
||||
int removeIndex = -1;
|
||||
for (int i = 0; i < prefs.vegetationStudioTreeTypes.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
prefs.vegetationStudioTreeTypes[i] = EditorGUILayout.IntSlider("Vegetation Type " + (i + 1) + ": ", prefs.vegetationStudioTreeTypes[i], 1, 32);
|
||||
if (prefs.vegetationStudioTreeTypes.Count > 1 && GUILayout.Button("X", GUILayout.ExpandWidth(false))) removeIndex = i;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
if (removeIndex != -1) prefs.vegetationStudioTreeTypes.RemoveAt(removeIndex);
|
||||
if (GUILayout.Button("Add item")) prefs.vegetationStudioTreeTypes.Add(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void InitTreeEngines()
|
||||
{
|
||||
availableTreeType = new List<string>();
|
||||
availableTreeType.Add("Standard");
|
||||
#if VEGETATION_STUDIO || VEGETATION_STUDIO_PRO
|
||||
availableTreeType.Add("Vegetation Studio");
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void SelectTreeEngine()
|
||||
{
|
||||
if (availableTreeType.Count > 1)
|
||||
{
|
||||
int treeEngineIndex = availableTreeType.IndexOf(prefs.treeEngine);
|
||||
if (treeEngineIndex == -1) treeEngineIndex = 0;
|
||||
treeEngineIndex = EditorGUILayout.Popup("Tree engine ", treeEngineIndex, availableTreeType.ToArray());
|
||||
prefs.treeEngine = availableTreeType[treeEngineIndex];
|
||||
}
|
||||
else prefs.treeEngine = availableTreeType[0];
|
||||
}
|
||||
|
||||
private static void TreesUI()
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
prefs.generateTrees = EditorGUILayout.Toggle("Generate trees", prefs.generateTrees);
|
||||
|
||||
if (!prefs.generateTrees)
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
return;
|
||||
}
|
||||
|
||||
SelectTreeEngine();
|
||||
|
||||
if (prefs.treeEngine == "Standard") StandardTreeEngineFields();
|
||||
else if (prefs.treeEngine == "Vegetation Studio") VegetationStudioTreeEngineFields();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3da84962a2c31344baf3ec8849e2b863
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,362 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using InfinityCode.RealWorldTerrain.Net;
|
||||
using InfinityCode.RealWorldTerrain.Phases;
|
||||
using InfinityCode.RealWorldTerrain.Windows;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public static partial class RealWorldTerrainWindowUI
|
||||
{
|
||||
private const int LabelWidth = 170;
|
||||
|
||||
public static int iProgress;
|
||||
public static string phasetitle = "";
|
||||
|
||||
private static GUIStyle _oddStyle;
|
||||
private static GUIStyle _evenStyle;
|
||||
|
||||
private static string mapboxAPI;
|
||||
private static Vector2 scrollPos = Vector2.zero;
|
||||
|
||||
private static readonly string[] labels2n = { "32", "64", "128", "256", "512", "1024", "2048", "4096" };
|
||||
private static readonly int[] values2n = { 32, 64, 128, 256, 512, 1024, 2048, 4096 };
|
||||
private static readonly string[] labels2n1 = { "33", "65", "129", "257", "513", "1025", "2049", "4097" };
|
||||
private static readonly int[] values2n1 = { 33, 65, 129, 257, 513, 1025, 2049, 4097 };
|
||||
|
||||
public static GUIStyle evenStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_evenStyle == null) _evenStyle = new GUIStyle();
|
||||
return _evenStyle;
|
||||
}
|
||||
}
|
||||
|
||||
public static GUIStyle oddStyle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_oddStyle == null)
|
||||
{
|
||||
_oddStyle = new GUIStyle();
|
||||
_oddStyle.normal.background = new Texture2D(1, 1);
|
||||
_oddStyle.normal.background.SetPixel(0, 0, new Color(0.5f, 0.5f, 0.5f, 0.2f));
|
||||
_oddStyle.normal.background.Apply();
|
||||
}
|
||||
|
||||
return _oddStyle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static RealWorldTerrainGenerateType generateType
|
||||
{
|
||||
get { return RealWorldTerrainWindow.generateType; }
|
||||
}
|
||||
|
||||
private static RealWorldTerrainPhase phase
|
||||
{
|
||||
get { return RealWorldTerrainPhase.activePhase; }
|
||||
}
|
||||
|
||||
private static RealWorldTerrainPrefs prefs
|
||||
{
|
||||
get { return RealWorldTerrainWindow.prefs; }
|
||||
}
|
||||
|
||||
private static RealWorldTerrainWindow wnd
|
||||
{
|
||||
get { return RealWorldTerrainWindow.wnd; }
|
||||
}
|
||||
|
||||
public static double DoubleField(string label, double value, string tooltip, string href = "")
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
value = EditorGUILayout.DoubleField(label, value);
|
||||
|
||||
if (GUILayout.Button(new GUIContent(RealWorldTerrainResources.helpIcon, tooltip),
|
||||
RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
if (href != "") Application.OpenURL(href);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void DrawHelpButton(string tooltip = null, string href = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(tooltip)) return;
|
||||
|
||||
GUIContent content = new GUIContent(RealWorldTerrainResources.helpIcon, tooltip);
|
||||
if (GUILayout.Button(content, RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false))
|
||||
&& !string.IsNullOrEmpty(href))
|
||||
{
|
||||
Application.OpenURL(href);
|
||||
}
|
||||
}
|
||||
|
||||
public static System.Enum EnumPopup(string label, System.Enum selected, string tooltip, string href = "")
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
Enum res = EditorGUILayout.EnumPopup(label, selected);
|
||||
DrawHelpButton(tooltip, href);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static float FloatField(string label, float value, string tooltip, string href = "")
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
value = EditorGUILayout.FloatField(label, value);
|
||||
DrawHelpButton(tooltip, href);
|
||||
GUILayout.EndHorizontal();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static bool Foldout(bool value, string text)
|
||||
{
|
||||
return GUILayout.Toggle(value, text, EditorStyles.foldout);
|
||||
}
|
||||
|
||||
public static int IntPopup(string label, int value, string[] displayedOptions, int[] optionValues, string tooltip, string href)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
value = EditorGUILayout.IntPopup(label, value, displayedOptions, optionValues);
|
||||
|
||||
DrawHelpButton(tooltip, href);
|
||||
GUILayout.EndHorizontal();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int IntPopup(string label, int value, string[] displayedOptions, int[] optionValues, string tooltip, string[] hrefs)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
value = EditorGUILayout.IntPopup(label, value, displayedOptions, optionValues);
|
||||
string href = null;
|
||||
if (hrefs != null && hrefs.Length > value) href = hrefs[value];
|
||||
DrawHelpButton(tooltip, href);
|
||||
GUILayout.EndHorizontal();
|
||||
return value;
|
||||
}
|
||||
|
||||
public static int IntField(string label, int value, string tooltip, string href = null)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
value = EditorGUILayout.IntField(label, value);
|
||||
DrawHelpButton(tooltip, href);
|
||||
GUILayout.EndHorizontal();
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void MapboxAccessToken()
|
||||
{
|
||||
if (mapboxAPI == null) mapboxAPI = RealWorldTerrainPrefs.LoadPref("MapboxAPI", "");
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
mapboxAPI = EditorGUILayout.TextField("Mapbox Access Token", mapboxAPI);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (mapboxAPI == "") RealWorldTerrainPrefs.DeletePref("MapboxAPI");
|
||||
else RealWorldTerrainPrefs.SetPref("MapboxAPI", mapboxAPI);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(mapboxAPI))
|
||||
{
|
||||
GUILayout.Box(new GUIContent(RealWorldTerrainResources.warningIcon, "Required"), RealWorldTerrainResources.helpStyle, GUILayout.ExpandWidth(false));
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
if (GUILayout.Button("Get Mapbox Access Token")) Process.Start("https://www.mapbox.com/studio/account/tokens/");
|
||||
}
|
||||
|
||||
public static void OnEnable()
|
||||
{
|
||||
InitTextureProviders();
|
||||
InitBuildingEngines();
|
||||
InitRoadEngines();
|
||||
InitGrassEngines();
|
||||
InitTreeEngines();
|
||||
InitRiverEngines();
|
||||
}
|
||||
|
||||
public static void OnGUI()
|
||||
{
|
||||
if (!RealWorldTerrainWindow.isCapturing) OnIdleGUI();
|
||||
else OnGenerate();
|
||||
}
|
||||
|
||||
private static void OnGenerate()
|
||||
{
|
||||
if (phase != null && phase is RealWorldTerrainDownloadingPhase)
|
||||
{
|
||||
int completed = Mathf.FloorToInt(RealWorldTerrainDownloadManager.totalSizeMB * RealWorldTerrainWindow.progress);
|
||||
GUILayout.Label(phasetitle + " (" + completed + " of " + RealWorldTerrainDownloadManager.totalSizeMB + " mb)");
|
||||
}
|
||||
else GUILayout.Label(phasetitle);
|
||||
|
||||
Rect r = EditorGUILayout.BeginVertical();
|
||||
iProgress = Mathf.FloorToInt(RealWorldTerrainWindow.progress * 100);
|
||||
EditorGUI.ProgressBar(r, RealWorldTerrainWindow.progress, iProgress + "%");
|
||||
GUILayout.Space(16);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
if (GUILayout.Button("Cancel")) RealWorldTerrainWindow.CancelCapture();
|
||||
|
||||
GUILayout.Label("Warning: Keep this window open.");
|
||||
}
|
||||
|
||||
private static void OnIdleButtons()
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Start")) RealWorldTerrainWindow.StartCapture();
|
||||
if (RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.full)
|
||||
{
|
||||
if (GUILayout.Button("Memory Usage", GUILayout.ExpandWidth(false))) RealWorldTerrainMemoryUsageWindow.OpenWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Switch to Full", GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
RealWorldTerrainWindow.generateType = RealWorldTerrainGenerateType.full;
|
||||
RealWorldTerrainWindow.generateTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear Cache", GUILayout.ExpandWidth(false))) RealWorldTerrainWindow.ClearCache();
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
private static void OnIdleGUI()
|
||||
{
|
||||
ToolbarUI();
|
||||
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
|
||||
EditorGUIUtility.labelWidth = LabelWidth;
|
||||
|
||||
bool isFull = RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.full;
|
||||
bool isTerrain = isFull || RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.terrain;
|
||||
bool isTexture = isFull || RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.texture;
|
||||
bool isAdditional = isFull || RealWorldTerrainWindow.generateType == RealWorldTerrainGenerateType.additional;
|
||||
bool isRawOutput = prefs.resultType == RealWorldTerrainResultType.gaiaStamp || prefs.resultType == RealWorldTerrainResultType.rawFile;
|
||||
|
||||
if (isFull) AreaUI();
|
||||
|
||||
if (isTerrain)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
showTerrains = EditorGUILayout.Foldout(showTerrains, "Terrains");
|
||||
|
||||
if (showTerrains) TerrainUI();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
ElevationProviderUI();
|
||||
}
|
||||
|
||||
if (isTexture && !isRawOutput)
|
||||
{
|
||||
if (isFull)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (prefs.generateTextures) showTextures = GUILayout.Toggle(showTextures, "", EditorStyles.foldout, GUILayout.ExpandWidth(false));
|
||||
prefs.generateTextures = GUILayout.Toggle(prefs.generateTextures, "Textures");
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (showTextures && prefs.generateTextures) TextureUI();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
EditorGUILayout.LabelField("Textures");
|
||||
prefs.generateTextures = true;
|
||||
|
||||
TextureUI();
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
|
||||
if (isFull && !isRawOutput)
|
||||
{
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
showPOI = EditorGUILayout.Foldout(showPOI, "POI");
|
||||
DrawHelpButton("Here you can specify a point of interest, which will be created on the terrains.");
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (showPOI) PoiUI();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
if (isAdditional && !isRawOutput) OsmUI();
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
OnIdleButtons();
|
||||
}
|
||||
|
||||
public static Object ObjectField(string label, Object obj, Type type, string tooltip = null, string href = null)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
obj = EditorGUILayout.ObjectField(label, obj, type, false);
|
||||
DrawHelpButton(tooltip, href);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static int Popup(string label, int selectedIndex, string[] displayedOptions, string tooltip = null, string href = null)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
int res = EditorGUILayout.Popup(label, selectedIndex, displayedOptions);
|
||||
DrawHelpButton(tooltip, href);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
return res;
|
||||
}
|
||||
|
||||
private static bool Toggle(bool value, string text, string tooltip = null, string href = null)
|
||||
{
|
||||
return Toggle(value, text, true, tooltip, href);
|
||||
}
|
||||
|
||||
private static bool Toggle(string text, bool value, bool left, string tooltip = null, string href = null)
|
||||
{
|
||||
return Toggle(value, text, left, tooltip, href);
|
||||
}
|
||||
|
||||
private static bool Toggle(bool value, string text, bool left, string tooltip = null, string href = null)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
if (left) value = GUILayout.Toggle(value, text);
|
||||
else value = EditorGUILayout.Toggle(text, value);
|
||||
DrawHelpButton(tooltip, href);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static Vector3 Vector3Field(string label, Vector3 value, string tooltip = null, string href = null)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
Vector3 res = EditorGUILayout.Vector3Field(label, value);
|
||||
DrawHelpButton(tooltip, href);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void MinMaxSlider(string label, ref float minValue, ref float maxValue, int minLimit, int maxLimit, string tooltip = null, string href = null)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.MinMaxSlider(label, ref minValue, ref maxValue, minLimit, maxLimit);
|
||||
DrawHelpButton(tooltip, href);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01806f7a456c6f44b8d61036ece4952c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user