From 09c0b2eed74a77010ba686061b147c9cace88ed6 Mon Sep 17 00:00:00 2001 From: Jakob Stendahl Date: Sat, 7 Oct 2017 22:57:48 +0200 Subject: Trur æ la te VCS, ikke meninga, men æ trur itj de e nå problem egt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- td/.idea/.idea.td/.idea/contentModel.xml | 9 + td/.idea/.idea.td/.idea/modules.xml | 8 + td/.idea/.idea.td/.idea/vcs.xml | 6 + td/.idea/.idea.td/.idea/workspace.xml | 1141 +++++++++++++++++++ td/.idea/.idea.td/riderModule.iml | 14 + td/Assets/Materials/projectile.mat | Bin 0 -> 5020 bytes td/Assets/Materials/projectile.mat.meta | 9 + td/Assets/Plugins.meta | 9 + td/Assets/Plugins/Editor.meta | 9 + td/Assets/Plugins/Editor/JetBrains.meta | 9 + td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs | 1164 ++++++++++++++++++++ .../Plugins/Editor/JetBrains/Unity3DRider.cs.meta | 12 + td/Assets/Prefabs/Castle.prefab | Bin 0 -> 9164 bytes td/Assets/Prefabs/Castle.prefab.meta | 9 + td/Assets/Prefabs/Towers/projectiles.meta | 9 + td/Assets/Prefabs/Towers/projectiles/bullet.prefab | Bin 0 -> 7752 bytes .../Prefabs/Towers/projectiles/bullet.prefab.meta | 9 + td/Assets/Scripts/Enemy.cs | 31 +- td/Assets/Scripts/EnemySpawner.cs | 37 +- td/Assets/Scripts/Projectile.cs | 42 + td/Assets/Scripts/Projectile.cs.meta | 12 + td/Assets/Scripts/cameraHandler.cs | 66 +- td/Assets/Scripts/castle.cs | 23 + td/Assets/Scripts/castle.cs.meta | 12 + td/Assets/Scripts/developerMode.cs | 56 +- td/Assets/Scripts/enableChild.cs | 2 +- td/Assets/Scripts/gameStats.cs | 56 +- td/Assets/Scripts/mainGUI.cs | 122 +- td/Assets/Scripts/player.cs | 53 +- td/Assets/Scripts/tower.cs | 112 +- td/Assets/Scripts/waveSpawner.cs | 44 +- 31 files changed, 2793 insertions(+), 292 deletions(-) create mode 100644 td/.idea/.idea.td/.idea/contentModel.xml create mode 100644 td/.idea/.idea.td/.idea/modules.xml create mode 100644 td/.idea/.idea.td/.idea/vcs.xml create mode 100644 td/.idea/.idea.td/.idea/workspace.xml create mode 100644 td/.idea/.idea.td/riderModule.iml create mode 100644 td/Assets/Materials/projectile.mat create mode 100644 td/Assets/Materials/projectile.mat.meta create mode 100644 td/Assets/Plugins.meta create mode 100644 td/Assets/Plugins/Editor.meta create mode 100644 td/Assets/Plugins/Editor/JetBrains.meta create mode 100644 td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs create mode 100644 td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs.meta create mode 100644 td/Assets/Prefabs/Castle.prefab create mode 100644 td/Assets/Prefabs/Castle.prefab.meta create mode 100644 td/Assets/Prefabs/Towers/projectiles.meta create mode 100644 td/Assets/Prefabs/Towers/projectiles/bullet.prefab create mode 100644 td/Assets/Prefabs/Towers/projectiles/bullet.prefab.meta create mode 100644 td/Assets/Scripts/Projectile.cs create mode 100644 td/Assets/Scripts/Projectile.cs.meta create mode 100644 td/Assets/Scripts/castle.cs create mode 100644 td/Assets/Scripts/castle.cs.meta diff --git a/td/.idea/.idea.td/.idea/contentModel.xml b/td/.idea/.idea.td/.idea/contentModel.xml new file mode 100644 index 0000000..4379302 --- /dev/null +++ b/td/.idea/.idea.td/.idea/contentModel.xml @@ -0,0 +1,9 @@ + + + + + Temp + Library + + + \ No newline at end of file diff --git a/td/.idea/.idea.td/.idea/modules.xml b/td/.idea/.idea.td/.idea/modules.xml new file mode 100644 index 0000000..471a22f --- /dev/null +++ b/td/.idea/.idea.td/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/td/.idea/.idea.td/.idea/vcs.xml b/td/.idea/.idea.td/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/td/.idea/.idea.td/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/td/.idea/.idea.td/.idea/workspace.xml b/td/.idea/.idea.td/.idea/workspace.xml new file mode 100644 index 0000000..ad4a00d --- /dev/null +++ b/td/.idea/.idea.td/.idea/workspace.xml @@ -0,0 +1,1141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + project + + + + + + + + + + + + + + + + project + + + true + + + + DIRECTORY + + false + + + + + + + + + + + + + + + + + + 1507402155822 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/td/.idea/.idea.td/riderModule.iml b/td/.idea/.idea.td/riderModule.iml new file mode 100644 index 0000000..ce4aad6 --- /dev/null +++ b/td/.idea/.idea.td/riderModule.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/td/Assets/Materials/projectile.mat b/td/Assets/Materials/projectile.mat new file mode 100644 index 0000000..aa97624 Binary files /dev/null and b/td/Assets/Materials/projectile.mat differ diff --git a/td/Assets/Materials/projectile.mat.meta b/td/Assets/Materials/projectile.mat.meta new file mode 100644 index 0000000..86f15cd --- /dev/null +++ b/td/Assets/Materials/projectile.mat.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 83ba8edd0e67d40d49d0da9f29fb697b +timeCreated: 1507300359 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Plugins.meta b/td/Assets/Plugins.meta new file mode 100644 index 0000000..9f5adca --- /dev/null +++ b/td/Assets/Plugins.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fb5264dd1c52f48429aac93affb7b259 +folderAsset: yes +timeCreated: 1507403604 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Plugins/Editor.meta b/td/Assets/Plugins/Editor.meta new file mode 100644 index 0000000..a7793dd --- /dev/null +++ b/td/Assets/Plugins/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2a4d3360e5ae541efbf0c892fcfe9314 +folderAsset: yes +timeCreated: 1507403604 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Plugins/Editor/JetBrains.meta b/td/Assets/Plugins/Editor/JetBrains.meta new file mode 100644 index 0000000..01e6324 --- /dev/null +++ b/td/Assets/Plugins/Editor/JetBrains.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ee3d259c0e31346acbb8138c78ea81a9 +folderAsset: yes +timeCreated: 1507403604 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs b/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs new file mode 100644 index 0000000..a87d402 --- /dev/null +++ b/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs @@ -0,0 +1,1164 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Version: 2.0.4.2575 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +using Application = UnityEngine.Application; +using Debug = UnityEngine.Debug; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Text; +using System.Xml.Linq; +using System; +using UnityEditor; +using UnityEngine; + +namespace Plugins.Editor.JetBrains +{ + public class RiderAssetPostprocessor : AssetPostprocessor + { + public static void OnGeneratedCSProjectFiles() + { + if (!RiderPlugin.Enabled) + return; + var currentDirectory = Directory.GetCurrentDirectory(); + var projectFiles = Directory.GetFiles(currentDirectory, "*.csproj"); + + foreach (var file in projectFiles) + { + UpgradeProjectFile(file); + } + + var slnFile = Directory.GetFiles(currentDirectory, "*.sln").First(); + RiderPlugin.Log(RiderPlugin.LoggingLevel.Verbose, string.Format("Post-processing {0}", slnFile)); + string content = File.ReadAllText(slnFile); + var lines = content.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); + var sb = new StringBuilder(); + foreach (var line in lines) + { + if (line.StartsWith("Project(")) + { + MatchCollection mc = Regex.Matches(line, "\"([^\"]*)\""); + //RiderPlugin.Log(RiderPlugin.LoggingLevel.Info, "mc[1]: "+mc[1].Value); + //RiderPlugin.Log(RiderPlugin.LoggingLevel.Info, "mc[2]: "+mc[2].Value); + var to = GetFileNameWithoutExtension(mc[2].Value.Substring(1, mc[2].Value.Length-1)); // remove quotes + //RiderPlugin.Log(RiderPlugin.LoggingLevel.Info, "to:" + to); + //RiderPlugin.Log(RiderPlugin.LoggingLevel.Info, line); + var newLine = line.Substring(0, mc[1].Index + 1) + to + line.Substring(mc[1].Index + mc[1].Value.Length - 1); + sb.Append(newLine); + //RiderPlugin.Log(RiderPlugin.LoggingLevel.Info, newLine); + } + else + { + sb.Append(line); + } + sb.Append(Environment.NewLine); + } + File.WriteAllText(slnFile, sb.ToString()); + } + + private static string GetFileNameWithoutExtension(string path) + { + if (string.IsNullOrEmpty(path)) + return null; + int length; + return (length = path.LastIndexOf('.')) == -1 ? path : path.Substring(0, length); + } + + private static void UpgradeProjectFile(string projectFile) + { + RiderPlugin.Log(RiderPlugin.LoggingLevel.Verbose, string.Format("Post-processing {0}", projectFile)); + var doc = XDocument.Load(projectFile); + var projectContentElement = doc.Root; + XNamespace xmlns = projectContentElement.Name.NamespaceName; // do not use var + + FixTargetFrameworkVersion(projectContentElement, xmlns); + FixSystemXml(projectContentElement, xmlns); + SetLangVersion(projectContentElement, xmlns); + // Unity_5_6_OR_NEWER switched to nunit 3.5 + // Fix helps only for Windows, on mac and linux I get https://youtrack.jetbrains.com/issue/RSRP-459932 +#if UNITY_5_6_OR_NEWER && UNITY_STANDALONE_WIN + ChangeNunitReference(new FileInfo(projectFile).DirectoryName, projectContentElement, xmlns); +#endif + +#if !UNITY_2017_1_OR_NEWER // Unity 2017.1 and later has this features by itself + SetManuallyDefinedComilingSettings(projectFile, projectContentElement, xmlns); + SetXCodeDllReference("UnityEditor.iOS.Extensions.Xcode.dll", xmlns, projectContentElement); + SetXCodeDllReference("UnityEditor.iOS.Extensions.Common.dll", xmlns, projectContentElement); +#endif + doc.Save(projectFile); + } + + private static void FixSystemXml(XElement projectContentElement, XNamespace xmlns) + { + var el = projectContentElement + .Elements(xmlns+"ItemGroup") + .Elements(xmlns+"Reference") + .FirstOrDefault(a => a.Attribute("Include").Value=="System.XML"); + if (el != null) + { + el.Attribute("Include").Value = "System.Xml"; + } + } + + private static void ChangeNunitReference(string baseDir, XElement projectContentElement, XNamespace xmlns) + { + var el = projectContentElement + .Elements(xmlns+"ItemGroup") + .Elements(xmlns+"Reference") + .FirstOrDefault(a => a.Attribute("Include").Value=="nunit.framework"); + if (el != null) + { + var hintPath = el.Elements(xmlns + "HintPath").FirstOrDefault(); + if (hintPath != null) + { + string unityAppBaseFolder = Path.GetDirectoryName(EditorApplication.applicationPath); + var path = Path.Combine(unityAppBaseFolder, "Data/Managed/nunit.framework.dll"); + if (new FileInfo(path).Exists) + hintPath.Value = path; + } + } + } + +#if !UNITY_2017_1_OR_NEWER // Unity 2017.1 and later has this features by itself + private const string UNITY_PLAYER_PROJECT_NAME = "Assembly-CSharp.csproj"; + private const string UNITY_EDITOR_PROJECT_NAME = "Assembly-CSharp-Editor.csproj"; + private const string UNITY_UNSAFE_KEYWORD = "-unsafe"; + private const string UNITY_DEFINE_KEYWORD = "-define:"; + private const string PLAYER_PROJECT_MANUAL_CONFIG_RELATIVE_FILE_PATH = "smcs.rsp"; + private static readonly string PLAYER_PROJECT_MANUAL_CONFIG_ABSOLUTE_FILE_PATH = Path.Combine(UnityEngine.Application.dataPath, PLAYER_PROJECT_MANUAL_CONFIG_RELATIVE_FILE_PATH); + private const string EDITOR_PROJECT_MANUAL_CONFIG_RELATIVE_FILE_PATH = "gmcs.rsp"; + private static readonly string EDITOR_PROJECT_MANUAL_CONFIG_ABSOLUTE_FILE_PATH = Path.Combine(UnityEngine.Application.dataPath, EDITOR_PROJECT_MANUAL_CONFIG_RELATIVE_FILE_PATH); + + private static void SetManuallyDefinedComilingSettings(string projectFile, XElement projectContentElement, XNamespace xmlns) + { + string configPath; + + if (IsPlayerProjectFile(projectFile)) + configPath = PLAYER_PROJECT_MANUAL_CONFIG_ABSOLUTE_FILE_PATH; + else if (IsEditorProjectFile(projectFile)) + configPath = EDITOR_PROJECT_MANUAL_CONFIG_ABSOLUTE_FILE_PATH; + else + configPath = null; + + if(!string.IsNullOrEmpty(configPath)) + ApplyManualCompilingSettings(configPath + , projectContentElement + , xmlns); + } + + private static void ApplyManualCompilingSettings(string configFilePath, XElement projectContentElement, XNamespace xmlns) + { + if (File.Exists(configFilePath)) + { + var configText = File.ReadAllText(configFilePath); + if (configText.Contains(UNITY_UNSAFE_KEYWORD)) + { + // Add AllowUnsafeBlocks to the .csproj. Unity doesn't generate it (although VSTU does). + // Strictly necessary to compile unsafe code + ApplyAllowUnsafeBlocks(projectContentElement, xmlns); + } + if (configText.Contains(UNITY_DEFINE_KEYWORD)) + { + // defines could be + // 1) -define:DEFINE1,DEFINE2 + // 2) -define:DEFINE1;DEFINE2 + // 3) -define:DEFINE1 -define:DEFINE2 + // 4) -define:DEFINE1,DEFINE2;DEFINE3 + // tested on "-define:DEF1;DEF2 -define:DEF3,DEF4;DEFFFF \n -define:DEF5" + // result: DEF1, DEF2, DEF3, DEF4, DEFFFF, DEF5 + + var definesList = new List(); + var compileFlags = configText.Split(' ', '\n'); + foreach (var flag in compileFlags) + { + var f = flag.Trim(); + if (f.Contains(UNITY_DEFINE_KEYWORD)) + { + var defineEndPos = f.IndexOf(UNITY_DEFINE_KEYWORD) + UNITY_DEFINE_KEYWORD.Length; + var definesSubString = f.Substring(defineEndPos,f.Length - defineEndPos); + definesSubString = definesSubString.Replace(";", ","); + definesList.AddRange(definesSubString.Split(',')); + } + } + + ApplyCustomDefines(definesList.ToArray(), projectContentElement, xmlns); + } + } + } + + private static void ApplyCustomDefines(string[] customDefines, XElement projectContentElement, XNamespace xmlns) + { + var definesString = string.Join(";", customDefines); + + var DefineConstants = projectContentElement + .Elements(xmlns+"PropertyGroup") + .Elements(xmlns+"DefineConstants") + .FirstOrDefault(definesConsts=> !string.IsNullOrEmpty(definesConsts.Value)); + + if (DefineConstants != null) + { + DefineConstants.SetValue(DefineConstants.Value + ";" + definesString); + } + } + + private static void ApplyAllowUnsafeBlocks(XElement projectContentElement, XNamespace xmlns) + { + projectContentElement.AddFirst( + new XElement(xmlns + "PropertyGroup", new XElement(xmlns + "AllowUnsafeBlocks", true))); + } + + private static bool IsPlayerProjectFile(string projectFile) + { + return Path.GetFileName(projectFile) == UNITY_PLAYER_PROJECT_NAME; + } + + private static bool IsEditorProjectFile(string projectFile) + { + return Path.GetFileName(projectFile) == UNITY_EDITOR_PROJECT_NAME; + } + + private static void SetXCodeDllReference(string name, XNamespace xmlns, XElement projectContentElement) + { + string unityAppBaseFolder = Path.GetDirectoryName(EditorApplication.applicationPath); + + var xcodeDllPath = Path.Combine(unityAppBaseFolder, Path.Combine("Data/PlaybackEngines/iOSSupport", name)); + if (!File.Exists(xcodeDllPath)) + xcodeDllPath = Path.Combine(unityAppBaseFolder, Path.Combine("PlaybackEngines/iOSSupport", name)); + + if (File.Exists(xcodeDllPath)) + { + var itemGroup = new XElement(xmlns + "ItemGroup"); + var reference = new XElement(xmlns + "Reference"); + reference.Add(new XAttribute("Include", Path.GetFileNameWithoutExtension(xcodeDllPath))); + reference.Add(new XElement(xmlns + "HintPath", xcodeDllPath)); + itemGroup.Add(reference); + projectContentElement.Add(itemGroup); + } + } +#endif + // Helps resolve System.Linq under mono 4 - RIDER-573 + private static void FixTargetFrameworkVersion(XElement projectElement, XNamespace xmlns) + { + var targetFrameworkVersion = projectElement.Elements(xmlns + "PropertyGroup") + .Elements(xmlns + "TargetFrameworkVersion") + .FirstOrDefault(); // Processing csproj files, which are not Unity-generated #56 + if (targetFrameworkVersion != null) + { + targetFrameworkVersion.SetValue("v"+RiderPlugin.TargetFrameworkVersion); + } + } + + private static void SetLangVersion(XElement projectElement, XNamespace xmlns) + { + // Add LangVersion to the .csproj. Unity doesn't generate it (although VSTU does). + // Not strictly necessary, as the Unity plugin for Rider will work it out, but setting + // it makes Rider work if it's not installed. + var langVersion = projectElement.Elements(xmlns + "PropertyGroup").Elements(xmlns + "LangVersion") + .FirstOrDefault(); // Processing csproj files, which are not Unity-generated #56 + if (langVersion != null) + { + langVersion.SetValue(GetLanguageLevel()); + } + else + { + projectElement.AddFirst(new XElement(xmlns + "PropertyGroup", + new XElement(xmlns + "LangVersion", GetLanguageLevel()))); + } + } + + private static string GetLanguageLevel() + { + // https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src + if (Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "CSharp70Support"))) + return "7"; + if (Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "CSharp60Support"))) + return "6"; + + // Unity 5.5 supports C# 6, but only when targeting .NET 4.6. The enum doesn't exist pre Unity 5.5 +#if !UNITY_5_6_OR_NEWER + if ((int)PlayerSettings.apiCompatibilityLevel >= 3) + #else + if ((int) PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.selectedBuildTargetGroup) >= 3) +#endif + return "6"; + + return "4"; + } + } +} + +namespace Plugins.Editor.JetBrains +{ + [InitializeOnLoad] + public static class RiderPlugin + { + private static bool Initialized; + private static string SlnFile; + + public static void Log(LoggingLevel level, string initialText) + { + if (level < SelectedLoggingLevel) return; + + var text = "[Rider] [" + level + "] " + initialText; + + switch (level) + { + case LoggingLevel.Warning: + Debug.LogWarning(text); + break; + default: + Debug.Log(text); + break; + } + } + + private static string GetDefaultApp() + { + var alreadySetPath = GetExternalScriptEditor(); + if (!string.IsNullOrEmpty(alreadySetPath) && RiderPathExist(alreadySetPath)) + return alreadySetPath; + + return RiderPath; + } + + private static string[] GetAllRiderPaths() + { + switch (SystemInfoRiderPlugin.operatingSystemFamily) + { + case OperatingSystemFamily.Windows: + string[] folders = + { + @"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\JetBrains", Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + @"Microsoft\Windows\Start Menu\Programs\JetBrains Toolbox") + }; + + var newPathLnks = folders.Select(b => new DirectoryInfo(b)).Where(a => a.Exists) + .SelectMany(c => c.GetFiles("*Rider*.lnk")).ToArray(); + if (newPathLnks.Any()) + { + var newPaths = newPathLnks + .Select(newPathLnk => new FileInfo(ShortcutResolver.Resolve(newPathLnk.FullName))) + .Where(fi => File.Exists(fi.FullName)) + .ToArray() + .OrderByDescending(fi => FileVersionInfo.GetVersionInfo(fi.FullName).ProductVersion) + .Select(a => a.FullName).ToArray(); + + return newPaths; + } + break; + + case OperatingSystemFamily.MacOSX: + // "/Applications/*Rider*.app" + //"~/Applications/JetBrains Toolbox/*Rider*.app" + string[] foldersMac = + { + "/Applications", Path.Combine(Environment.GetEnvironmentVariable("HOME"), "Applications/JetBrains Toolbox") + }; + var newPathsMac = foldersMac.Select(b => new DirectoryInfo(b)).Where(a => a.Exists) + .SelectMany(c => c.GetDirectories("*Rider*.app")) + .Select(a => a.FullName).ToArray(); + return newPathsMac; + } + return new string[0]; + } + + private static string TargetFrameworkVersionDefault + { + get + { + var defaultValue = "4.5"; + if (SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.Windows) + { + var dir = new DirectoryInfo(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework"); + if (dir.Exists) + { + var availableVersions = dir.GetDirectories("v*").Select(a => a.Name.Substring(1)) + .Where(v => TryCatch(v, s => { })).ToArray(); + if (availableVersions.Any() && !availableVersions.Contains(defaultValue)) + { + defaultValue = availableVersions.OrderBy(a => new Version(a)).Last(); + } + } + } + return defaultValue; + } + } + + public static string TargetFrameworkVersion + { + get + { + return EditorPrefs.GetString("Rider_TargetFrameworkVersion", + EditorPrefs.GetBool("Rider_TargetFrameworkVersion45", true) ? TargetFrameworkVersionDefault : "3.5"); + } + set + { + TryCatch(value, val => + { + EditorPrefs.SetString("Rider_TargetFrameworkVersion", val); + }); + } + } + + private static bool TryCatch(string value, Action action) + { + try + { + new Version(value); // mono 2.6 doesn't support Version.TryParse + action(value); + return true; + } + catch (ArgumentException) + { + } // can't put loggin here because ot fire on every symbol + catch (FormatException) + { + } + return false; + } + + public static string RiderPath + { + get { return EditorPrefs.GetString("Rider_RiderPath", GetAllRiderPaths().FirstOrDefault()); } + set { EditorPrefs.SetString("Rider_RiderPath", value); } + } + + public enum LoggingLevel + { + Verbose = 0, + Info = 1, + Warning = 2 + } + + public static LoggingLevel SelectedLoggingLevel + { + get { return (LoggingLevel) EditorPrefs.GetInt("Rider_SelectedLoggingLevel", 1); } + set { EditorPrefs.SetInt("Rider_SelectedLoggingLevel", (int) value); } + } + + public static bool RiderInitializedOnce + { + get { return EditorPrefs.GetBool("RiderInitializedOnce", false); } + set { EditorPrefs.SetBool("RiderInitializedOnce", value); } + } + + internal static bool Enabled + { + get + { + var defaultApp = GetExternalScriptEditor(); + return !string.IsNullOrEmpty(defaultApp) && Path.GetFileName(defaultApp).ToLower().Contains("rider"); + } + } + + static RiderPlugin() + { + var riderPath = GetDefaultApp(); + if (!RiderPathExist(riderPath)) + return; + + AddRiderToRecentlyUsedScriptApp(riderPath, "RecentlyUsedScriptApp"); + if (!RiderInitializedOnce) + { + SetExternalScriptEditor(riderPath); + RiderInitializedOnce = true; + } + if (Enabled) + { + InitRiderPlugin(); + } + } + + private static void InitRiderPlugin() + { + var projectDirectory = Directory.GetParent(Application.dataPath).FullName; + + var projectName = Path.GetFileName(projectDirectory); + SlnFile = Path.Combine(projectDirectory, string.Format("{0}.sln", projectName)); + + InitializeEditorInstanceJson(projectDirectory); + + Log(LoggingLevel.Info, "Rider plugin initialized. You may change the amount of Rider Debug output via Edit -> Preferences -> Rider -> Logging Level"); + Initialized = true; + } + + private static void AddRiderToRecentlyUsedScriptApp(string userAppPath, string recentAppsKey) + { + for (int index = 0; index < 10; ++index) + { + string path = EditorPrefs.GetString(recentAppsKey + (object) index); + if (File.Exists(path) && Path.GetFileName(path).ToLower().Contains("rider")) + return; + } + EditorPrefs.SetString(recentAppsKey + 9, userAppPath); + } + + private static string GetExternalScriptEditor() + { + return EditorPrefs.GetString("kScriptsDefaultApp"); + } + + private static void SetExternalScriptEditor(string path) + { + EditorPrefs.SetString("kScriptsDefaultApp", path); + } + + private static bool RiderPathExist(string path) + { + if (string.IsNullOrEmpty(path)) + return false; + // windows or mac + var fileInfo = new FileInfo(path); + if (!fileInfo.Name.ToLower().Contains("rider")) + return false; + var directoryInfo = new DirectoryInfo(path); + return fileInfo.Exists || (SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.MacOSX && + directoryInfo.Exists); + } + + /// + /// Creates and deletes Library/EditorInstance.json containing version and process ID + /// + /// Path to the project root directory + private static void InitializeEditorInstanceJson(string projectDirectory) + { + // Only manage EditorInstance.json for 4.x and 5.x - it's a native feature for 2017.x +#if !UNITY_2017_1_OR_NEWER + Log(LoggingLevel.Verbose, "Writing Library/EditorInstance.json"); + + var library = Path.Combine(projectDirectory, "Library"); + var editorInstanceJsonPath = Path.Combine(library, "EditorInstance.json"); + + File.WriteAllText(editorInstanceJsonPath, string.Format(@"{{ + ""process_id"": {0}, + ""version"": ""{1}"" +}}", Process.GetCurrentProcess().Id, Application.unityVersion)); + + AppDomain.CurrentDomain.DomainUnload += (sender, args) => + { + Log(LoggingLevel.Verbose, "Deleting Library/EditorInstance.json"); + File.Delete(editorInstanceJsonPath); + }; +#endif + } + + /// + /// Asset Open Callback (from Unity) + /// + /// + /// Called when Unity is about to open an asset. + /// + [UnityEditor.Callbacks.OnOpenAssetAttribute()] + static bool OnOpenedAsset(int instanceID, int line) + { + if (Enabled) + { + if (!Initialized) + { + // make sure the plugin was initialized first. + // this can happen in case "Rider" was set as the default scripting app only after this plugin was imported. + InitRiderPlugin(); + RiderAssetPostprocessor.OnGeneratedCSProjectFiles(); + } + + string appPath = Path.GetDirectoryName(Application.dataPath); + + // determine asset that has been double clicked in the project view + var selected = EditorUtility.InstanceIDToObject(instanceID); + + var assetFilePath = Path.Combine(appPath, AssetDatabase.GetAssetPath(selected)); + if (!(selected.GetType().ToString() == "UnityEditor.MonoScript" || + selected.GetType().ToString() == "UnityEngine.Shader" || + (selected.GetType().ToString() == "UnityEngine.TextAsset" && +#if UNITY_5 || UNITY_5_5_OR_NEWER + EditorSettings.projectGenerationUserExtensions.Contains(Path.GetExtension(assetFilePath).Substring(1)) +#else + EditorSettings.externalVersionControl.Contains(Path.GetExtension(assetFilePath).Substring(1)) +#endif + ))) + return false; + + SyncSolution(); // added to handle opening file, which was just recently created. + if (!DetectPortAndOpenFile(line, assetFilePath, + SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.Windows)) + { + var args = string.Format("{0}{1}{0} --line {2} {0}{3}{0}", "\"", SlnFile, line, assetFilePath); + return CallRider(args); + } + return true; + } + + return false; + } + + + private static bool DetectPortAndOpenFile(int line, string filePath, bool isWindows) + { + if (SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.Windows) + { + var process = GetRiderProcess(); + if (process == null) + return false; + } + + int[] ports = Enumerable.Range(63342, 20).ToArray(); + var res = ports.Any(port => + { + var aboutUrl = string.Format("http://localhost:{0}/api/about/", port); + var aboutUri = new Uri(aboutUrl); + + using (var client = new WebClient()) + { + client.Headers.Add("origin", string.Format("http://localhost:{0}", port)); + client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded"; + + try + { + var responce = CallHttpApi(aboutUri, client); + if (responce.ToLower().Contains("rider")) + { + return HttpOpenFile(line, filePath, isWindows, port, client); + } + } + catch (Exception e) + { + Log(LoggingLevel.Verbose, string.Format("Exception in DetectPortAndOpenFile: {0}", e)); + } + } + return false; + }); + return res; + } + + private static bool HttpOpenFile(int line, string filePath, bool isWindows, int port, WebClient client) + { + var url = string.Format("http://localhost:{0}/api/file?file={1}{2}", port, filePath, + line < 0 + ? "&p=0" + : "&line=" + line); // &p is needed to workaround https://youtrack.jetbrains.com/issue/IDEA-172350 + if (isWindows) + url = string.Format(@"http://localhost:{0}/api/file/{1}{2}", port, filePath, line < 0 ? "" : ":" + line); + + var uri = new Uri(url); + Log(LoggingLevel.Verbose, string.Format("HttpRequestOpenFile({0})", uri.AbsoluteUri)); + + CallHttpApi(uri, client); + ActivateWindow(); + return true; + } + + private static string CallHttpApi(Uri uri, WebClient client) + { + var responseString = client.DownloadString(uri.AbsoluteUri); + Log(LoggingLevel.Verbose, string.Format("CallHttpApi {0} response: {1}", uri.AbsoluteUri, responseString)); + return responseString; + } + + private static bool CallRider(string args) + { + var defaultApp = GetDefaultApp(); + if (!RiderPathExist(defaultApp)) + { + return false; + } + + var proc = new Process(); + if (SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.MacOSX) + { + proc.StartInfo.FileName = "open"; + proc.StartInfo.Arguments = string.Format("-n {0}{1}{0} --args {2}", "\"", "/" + defaultApp, args); + Log(LoggingLevel.Verbose, string.Format("{0} {1}", proc.StartInfo.FileName, proc.StartInfo.Arguments)); + } + else + { + proc.StartInfo.FileName = defaultApp; + proc.StartInfo.Arguments = args; + Log(LoggingLevel.Verbose, string.Format("{2}{0}{2}" + " {1}", proc.StartInfo.FileName, proc.StartInfo.Arguments, "\"")); + } + + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; + proc.StartInfo.CreateNoWindow = true; + proc.StartInfo.RedirectStandardOutput = true; + proc.Start(); + + ActivateWindow(); + return true; + } + + private static void ActivateWindow() + { + if (SystemInfoRiderPlugin.operatingSystemFamily == OperatingSystemFamily.Windows) + { + try + { + var process = GetRiderProcess(); + if (process != null) + { + // Collect top level windows + var topLevelWindows = User32Dll.GetTopLevelWindowHandles(); + // Get process main window title + var windowHandle = topLevelWindows.FirstOrDefault(hwnd => User32Dll.GetWindowProcessId(hwnd) == process.Id); + Log(LoggingLevel.Info, string.Format("ActivateWindow: {0} {1}", process.Id, windowHandle)); + if (windowHandle != IntPtr.Zero) + { + //User32Dll.ShowWindow(windowHandle, 9); //SW_RESTORE = 9 + User32Dll.SetForegroundWindow(windowHandle); + } + } + } + catch (Exception e) + { + Log(LoggingLevel.Warning, "Exception on ActivateWindow: " + e); + } + } + } + + private static Process GetRiderProcess() + { + var process = Process.GetProcesses().FirstOrDefault(p => + { + string processName; + try + { + processName = + p.ProcessName; // some processes like kaspersky antivirus throw exception on attempt to get ProcessName + } + catch (Exception) + { + return false; + } + + return !p.HasExited && processName.ToLower().Contains("rider"); + }); + return process; + } + + // The default "Open C# Project" menu item will use the external script editor to load the .sln + // file, but unless Unity knows the external script editor can properly load solutions, it will + // also launch MonoDevelop (or the OS registered app for .sln files). This menu item side steps + // that issue, and opens the solution in Rider without opening MonoDevelop as well. + // Unity 2017.1 and later recognise Rider as an app that can load solutions, so this menu isn't + // needed in newer versions. + [MenuItem("Assets/Open C# Project in Rider", false, 1000)] + static void MenuOpenProject() + { + // Force the project files to be sync + SyncSolution(); + + // Load Project + CallRider(string.Format("{0}{1}{0}", "\"", SlnFile)); + } + + [MenuItem("Assets/Open C# Project in Rider", true, 1000)] + static bool ValidateMenuOpenProject() + { + return Enabled; + } + + /// + /// Force Unity To Write Project File + /// + private static void SyncSolution() + { + System.Type T = System.Type.GetType("UnityEditor.SyncVS,UnityEditor"); + System.Reflection.MethodInfo SyncSolution = T.GetMethod("SyncSolution", + System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + SyncSolution.Invoke(null, null); + } + + /// + /// JetBrains Rider Integration Preferences Item + /// + /// + /// Contains all 3 toggles: Enable/Disable; Debug On/Off; Writing Launch File On/Off + /// + [PreferenceItem("Rider")] + static void RiderPreferencesItem() + { + EditorGUILayout.BeginVertical(); + EditorGUI.BeginChangeCheck(); + + var alternatives = GetAllRiderPaths(); + if (alternatives.Any()) + { + int index = Array.IndexOf(alternatives, RiderPath); + var alts = alternatives.Select(s => s.Replace("/", ":")) + .ToArray(); // hack around https://fogbugz.unity3d.com/default.asp?940857_tirhinhe3144t4vn + RiderPath = alternatives[EditorGUILayout.Popup("Rider executable:", index == -1 ? 0 : index, alts)]; + if (EditorGUILayout.Toggle(new GUIContent("Rider is default editor"), Enabled)) + { + SetExternalScriptEditor(RiderPath); + EditorGUILayout.HelpBox("Unckecking will restore default external editor.", MessageType.None); + } + else + { + SetExternalScriptEditor(string.Empty); + EditorGUILayout.HelpBox("Checking will set Rider as default external editor", MessageType.None); + } + + } + var help = @"TargetFramework >= 4.5 is strongly recommended. + - Without 4.5: + - Rider will fail to resolve System.Linq on Mac/Linux + - Rider will fail to resolve Firebase Analytics. + - With 4.5 Rider may show ambiguous references in UniRx. +All those problems will go away after Unity upgrades to mono4."; + + TargetFrameworkVersion = + EditorGUILayout.TextField( + new GUIContent("TargetFrameworkVersion", + help), TargetFrameworkVersion); + EditorGUILayout.HelpBox(help, MessageType.None); + + EditorGUI.EndChangeCheck(); + + EditorGUI.BeginChangeCheck(); + + var loggingMsg = + @"Sets the amount of Rider Debug output. If you are about to report an issue, please select Verbose logging level and attach Unity console output to the issue."; + SelectedLoggingLevel = (LoggingLevel) EditorGUILayout.EnumPopup(new GUIContent("Logging Level", loggingMsg), SelectedLoggingLevel); + EditorGUILayout.HelpBox(loggingMsg, MessageType.None); + + EditorGUI.EndChangeCheck(); + + var url = "https://github.com/JetBrains/resharper-unity"; + LinkButton(url, url); + +/* if (GUILayout.Button("reset RiderInitializedOnce = false")) + { + RiderInitializedOnce = false; + }*/ + + EditorGUILayout.EndVertical(); + } + + private static void LinkButton(string caption, string url) + { + var style = GUI.skin.label; + style.richText = true; + caption = string.Format("{0}", caption); + + bool bClicked = GUILayout.Button(caption, style); + + var rect = GUILayoutUtility.GetLastRect(); + rect.width = style.CalcSize(new GUIContent(caption)).x; + EditorGUIUtility.AddCursorRect(rect, MouseCursor.Link); + + if (bClicked) + Application.OpenURL(url); + } + + #region SystemInfoRiderPlugin + static class SystemInfoRiderPlugin + { + public static OperatingSystemFamily operatingSystemFamily + { + get + { +#if UNITY_5_5_OR_NEWER +return SystemInfo.operatingSystemFamily; +#else + if (SystemInfo.operatingSystem.StartsWith("Mac", StringComparison.InvariantCultureIgnoreCase)) + { + return OperatingSystemFamily.MacOSX; + } + if (SystemInfo.operatingSystem.StartsWith("Win", StringComparison.InvariantCultureIgnoreCase)) + { + return OperatingSystemFamily.Windows; + } + if (SystemInfo.operatingSystem.StartsWith("Lin", StringComparison.InvariantCultureIgnoreCase)) + { + return OperatingSystemFamily.Linux; + } + return OperatingSystemFamily.Other; +#endif + } + } + } +#if !UNITY_5_5_OR_NEWER + enum OperatingSystemFamily + { + Other, + MacOSX, + Windows, + Linux, + } +#endif + #endregion + + static class User32Dll + { + + /// + /// Gets the ID of the process that owns the window. + /// Note that creating a wrapper for that is very expensive because it causes an enumeration of all the system processes to happen. + /// + public static int GetWindowProcessId(IntPtr hwnd) + { + uint dwProcessId; + GetWindowThreadProcessId(hwnd, out dwProcessId); + return unchecked((int) dwProcessId); + } + + /// + /// Lists the handles of all the top-level windows currently available in the system. + /// + public static List GetTopLevelWindowHandles() + { + var retval = new List(); + EnumWindowsProc callback = (hwnd, param) => + { + retval.Add(hwnd); + return 1; + }; + EnumWindows(Marshal.GetFunctionPointerForDelegate(callback), IntPtr.Zero); + GC.KeepAlive(callback); + return retval; + } + + public delegate Int32 EnumWindowsProc(IntPtr hwnd, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, + ExactSpelling = true)] + public static extern Int32 EnumWindows(IntPtr lpEnumFunc, IntPtr lParam); + + [DllImport("user32.dll", SetLastError = true)] + static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + [DllImport("user32.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, + ExactSpelling = true)] + public static extern Int32 SetForegroundWindow(IntPtr hWnd); + + [DllImport("user32.dll", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, + ExactSpelling = true)] + public static extern UInt32 ShowWindow(IntPtr hWnd, Int32 nCmdShow); + } + + static class ShortcutResolver + { + #region Signitures imported from http://pinvoke.net + + [DllImport("shfolder.dll", CharSet = CharSet.Auto)] + internal static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath); + + [Flags()] + enum SLGP_FLAGS + { + /// Retrieves the standard short (8.3 format) file name + SLGP_SHORTPATH = 0x1, + + /// Retrieves the Universal Naming Convention (UNC) path name of the file + SLGP_UNCPRIORITY = 0x2, + + /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded + SLGP_RAWPATH = 0x4 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + struct WIN32_FIND_DATAW + { + public uint dwFileAttributes; + public long ftCreationTime; + public long ftLastAccessTime; + public long ftLastWriteTime; + public uint nFileSizeHigh; + public uint nFileSizeLow; + public uint dwReserved0; + public uint dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string cFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string cAlternateFileName; + } + + [Flags()] + enum SLR_FLAGS + { + /// + /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, + /// the high-order word of fFlags can be set to a time-out value that specifies the + /// maximum amount of time to be spent resolving the link. The function returns if the + /// link cannot be resolved within the time-out duration. If the high-order word is set + /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds + /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out + /// duration, in milliseconds. + /// + SLR_NO_UI = 0x1, + + /// Obsolete and no longer used + SLR_ANY_MATCH = 0x2, + + /// If the link object has changed, update its path and list of identifiers. + /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine + /// whether or not the link object has changed. + SLR_UPDATE = 0x4, + + /// Do not update the link information + SLR_NOUPDATE = 0x8, + + /// Do not execute the search heuristics + SLR_NOSEARCH = 0x10, + + /// Do not use distributed link tracking + SLR_NOTRACK = 0x20, + + /// Disable distributed link tracking. By default, distributed link tracking tracks + /// removable media across multiple devices based on the volume name. It also uses the + /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter + /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. + SLR_NOLINKINFO = 0x40, + + /// Call the Microsoft Windows Installer + SLR_INVOKE_MSI = 0x80 + } + + + /// The IShellLink interface allows Shell links to be created, modified, and resolved + [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] + interface IShellLinkW + { + /// Retrieves the path and file name of a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags); + + /// Retrieves the list of item identifiers for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetIDList(out IntPtr ppidl); + + /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetIDList(IntPtr pidl); + + /// Retrieves the description string for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); + + /// Sets the description for a Shell link object. The description can be any application-defined string + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + + /// Retrieves the name of the working directory for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + + /// Sets the name of the working directory for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + + /// Retrieves the command-line arguments associated with a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + + /// Sets the command-line arguments for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + + /// Retrieves the hot key for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetHotkey(out short pwHotkey); + + /// Sets a hot key for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetHotkey(short wHotkey); + + /// Retrieves the show command for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetShowCmd(out int piShowCmd); + + /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetShowCmd(int iShowCmd); + + /// Retrieves the location (path and index) of the icon for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); + + /// Sets the location (path and index) of the icon for a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + + /// Sets the relative path to the Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); + + /// Attempts to find the target of a Shell link, even if it has been moved or renamed + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); + + /// Sets the path and file name of a Shell link object + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersist + { + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetClassID(out Guid pClassID); + } + + + [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersistFile : IPersist + { + [MethodImpl(MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + new void GetClassID(out Guid pClassID); + + [MethodImpl(MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + int IsDirty(); + + [MethodImpl(MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode); + + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [In, MarshalAs(UnmanagedType.Bool)] bool fRemember); + + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + + [MethodImpl (MethodImplOptions.InternalCall | MethodImplOptions.PreserveSig, MethodCodeType = MethodCodeType.Runtime)] + void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); + } + + const uint STGM_READ = 0; + const int MAX_PATH = 260; + + // CLSID_ShellLink from ShlGuid.h + [ + ComImport(), + Guid("00021401-0000-0000-C000-000000000046") + ] + public class ShellLink + { + } + + #endregion + + public static string Resolve(string filename) + { + ShellLink link = new ShellLink(); + ((IPersistFile) link).Load(filename, STGM_READ); + // If I can get hold of the hwnd call resolve first. This handles moved and renamed files. + // ((IShellLinkW)link).Resolve(hwnd, 0) + StringBuilder sb = new StringBuilder(MAX_PATH); + WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); + ((IShellLinkW) link).GetPath(sb, sb.Capacity, out data, 0); + return sb.ToString(); + } + } + } +} + +// Developed using JetBrains Rider =) diff --git a/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs.meta b/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs.meta new file mode 100644 index 0000000..519e0e0 --- /dev/null +++ b/td/Assets/Plugins/Editor/JetBrains/Unity3DRider.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aa3e49e597a704f07b686414e3192b11 +timeCreated: 1507403604 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Prefabs/Castle.prefab b/td/Assets/Prefabs/Castle.prefab new file mode 100644 index 0000000..3da320a Binary files /dev/null and b/td/Assets/Prefabs/Castle.prefab differ diff --git a/td/Assets/Prefabs/Castle.prefab.meta b/td/Assets/Prefabs/Castle.prefab.meta new file mode 100644 index 0000000..612183d --- /dev/null +++ b/td/Assets/Prefabs/Castle.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a94082cb0c354452eb9646dcb2c8d658 +timeCreated: 1507302352 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Prefabs/Towers/projectiles.meta b/td/Assets/Prefabs/Towers/projectiles.meta new file mode 100644 index 0000000..b66e7d3 --- /dev/null +++ b/td/Assets/Prefabs/Towers/projectiles.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1fd8e4afa918142cf86708ca153cfa3c +folderAsset: yes +timeCreated: 1507240769 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Prefabs/Towers/projectiles/bullet.prefab b/td/Assets/Prefabs/Towers/projectiles/bullet.prefab new file mode 100644 index 0000000..9d02c80 Binary files /dev/null and b/td/Assets/Prefabs/Towers/projectiles/bullet.prefab differ diff --git a/td/Assets/Prefabs/Towers/projectiles/bullet.prefab.meta b/td/Assets/Prefabs/Towers/projectiles/bullet.prefab.meta new file mode 100644 index 0000000..80854b9 --- /dev/null +++ b/td/Assets/Prefabs/Towers/projectiles/bullet.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: cc0aabf9df00e4ec0a1bde5c8f2cb499 +timeCreated: 1507300388 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Scripts/Enemy.cs b/td/Assets/Scripts/Enemy.cs index 4542902..3074003 100644 --- a/td/Assets/Scripts/Enemy.cs +++ b/td/Assets/Scripts/Enemy.cs @@ -1,5 +1,4 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using UnityEngine; public class Enemy : MonoBehaviour { @@ -7,28 +6,28 @@ public class Enemy : MonoBehaviour { * Currently it follows the pathway, and dies when reacing the end */ [Header("Attributes")] - public float speed; // Speed multiplier - public int initialHp; // HealthPoints - public int damage; - public List waypoints; // Pathway waypoints, should be set by the spawner + public float Speed; // Speed multiplier + public int InitialHp; // HealthPoints + public int Damage; + public List Waypoints; // Pathway waypoints, should be set by the spawner [Header("Scripting vars")] - public player player; // Reference to the player object, should be set when instantiating + public Player Player; // Reference to the player object, should be set when instantiating - Vector3 waypointPos; // Current waypoint position - int waypointNum = -1; // Using minus one so that first addition returns 0, first element in array + private Vector3 _waypointPos; // Current waypoint position + private int _waypointNum = -1; // Using minus one so that first addition returns 0, first element in array void Update () { - if ( (transform.position == waypointPos && waypointNum + 1 < waypoints.Count) || waypointNum == -1) { - waypointNum++; - waypointPos = new Vector3 (waypoints [waypointNum].x, 0.483f, waypoints [waypointNum].z); + if ( (transform.position == _waypointPos && _waypointNum + 1 < Waypoints.Count) || _waypointNum == -1) { + _waypointNum++; + _waypointPos = new Vector3 (Waypoints [_waypointNum].x, 0.483f, Waypoints [_waypointNum].z); } - float transformStep = speed * Time.deltaTime; - transform.position = Vector3.MoveTowards (transform.position, waypointPos, transformStep); + float transformStep = Speed * Time.deltaTime; + transform.position = Vector3.MoveTowards (transform.position, _waypointPos, transformStep); // Selfdestruct if object reached the end - if (waypointNum + 1 >= waypoints.Count) { - player.decreaseHealth (damage); + if (_waypointNum + 1 >= Waypoints.Count) { + Player.DecreaseHealth (Damage); Destroy (gameObject); return; } diff --git a/td/Assets/Scripts/EnemySpawner.cs b/td/Assets/Scripts/EnemySpawner.cs index ee0d3d6..7ee8680 100644 --- a/td/Assets/Scripts/EnemySpawner.cs +++ b/td/Assets/Scripts/EnemySpawner.cs @@ -6,42 +6,41 @@ public class EnemySpawner : MonoBehaviour { /* This is a class that spawns an enemy with a random interval * it is not very good, but is what it needs to be for testing purposes */ // TODO Add wave system with increasing difficulty - - public Enemy enemyPrefab; - public Transform pathWay; + public Enemy EnemyPrefab; + public Transform PathWay; [Header("Scripting vars")] - public player player; // Reference to the player object, should be set when instantiating + public Player Player; // Reference to the player object, should be set when instantiating - private Transform parentObject; + private Transform _parentObject; - List waypoints = new List(); - int next = 1; - int n = 0; + List _waypoints = new List(); + int _next = 1; + int _n = 0; void Awake() { - foreach (Transform child in pathWay) { - waypoints.Add (child.position); + foreach (Transform child in PathWay) { + _waypoints.Add (child.position); } } void Start() { - parentObject = transform.Find ("enemies").gameObject.GetComponent (); + _parentObject = transform.Find ("enemies").gameObject.GetComponent (); } void Update () { - n++; + _n++; - if (n == next) { - n = 0; - next = (int)Random.Range (50, 400); + if (_n == _next) { + _n = 0; + _next = (int)Random.Range (50, 400); - Enemy newEnemy = Instantiate (enemyPrefab, new Vector3(0, 0, 0), Quaternion.identity, parentObject); + Enemy newEnemy = Instantiate (EnemyPrefab, new Vector3(0, 0, 0), Quaternion.identity, _parentObject); Enemy script = newEnemy.GetComponent (); Transform transform = newEnemy.GetComponent (); - script.waypoints = waypoints; - script.speed = Random.Range (0.3f, 1.2f); - script.player = player; + script.Waypoints = _waypoints; + script.Speed = Random.Range (0.3f, 1.2f); + script.Player = Player; transform.position = new Vector3 (0.93f, 0.483f, 0f); } diff --git a/td/Assets/Scripts/Projectile.cs b/td/Assets/Scripts/Projectile.cs new file mode 100644 index 0000000..0cdef16 --- /dev/null +++ b/td/Assets/Scripts/Projectile.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class Projectile : MonoBehaviour { + + public float Speed = 70f; + public int PointsPerHit; + [Header("Scripting vars")] + public Player Player; // Reference to the player object, should be set when instantiating + private Transform _target; + + public void Seek(Transform target) { + _target = target; + } + + + void Update () { + + if (_target == null) { + Destroy (gameObject); + return; + } + + Vector3 direction = _target.position - transform.position; + float distanceThisFrame = Speed * Time.deltaTime; + + if (direction.magnitude <= distanceThisFrame) { + HitTarget (); + return; + } + + transform.Translate (direction.normalized * distanceThisFrame, Space.World); + + + } + + void HitTarget() { + Player.ScoreAdd (PointsPerHit); + Destroy (_target.gameObject); + Destroy (gameObject); + } + +} diff --git a/td/Assets/Scripts/Projectile.cs.meta b/td/Assets/Scripts/Projectile.cs.meta new file mode 100644 index 0000000..a95b993 --- /dev/null +++ b/td/Assets/Scripts/Projectile.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4a1928566183240ea8566b659c4b3d5f +timeCreated: 1507300755 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Scripts/cameraHandler.cs b/td/Assets/Scripts/cameraHandler.cs index c1c4cae..1655509 100644 --- a/td/Assets/Scripts/cameraHandler.cs +++ b/td/Assets/Scripts/cameraHandler.cs @@ -1,8 +1,6 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; +using UnityEngine; -public class cameraHandler : MonoBehaviour { +public class CameraHandler : MonoBehaviour { // TODO Fiks panning, ser idiotisk ut nå så jeg har satt panSpeed til 0. (I editoren) public float PanSpeed = 20f; @@ -14,17 +12,17 @@ public class cameraHandler : MonoBehaviour { public static readonly float[] BoundsZ = new float[]{-8f, 8f}; public static readonly float[] ZoomBounds = new float[]{1f, 5f}; - private Camera cam; + private Camera _cam; - private bool panActive; - private Vector3 lastPanPosition; - private int panFingerId; // Touch mode only + private bool _panActive; + private Vector3 _lastPanPosition; + private int _panFingerId; // Touch mode only - private bool zoomActive; - private Vector2[] lastZoomPositions; // Touch mode only + private bool _zoomActive; + private Vector2[] _lastZoomPositions; // Touch mode only void Awake() { - cam = GetComponent(); + _cam = GetComponent(); } void Update() { @@ -46,43 +44,43 @@ public class cameraHandler : MonoBehaviour { switch(Input.touchCount) { case 1: // Panning - zoomActive = false; + _zoomActive = false; // If the touch began, capture its position and its finger ID. // Otherwise, if the finger ID of the touch doesn't match, skip it. Touch touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { - lastPanPosition = touch.position; - panFingerId = touch.fingerId; - panActive = true; - } else if (touch.fingerId == panFingerId && touch.phase == TouchPhase.Moved) { + _lastPanPosition = touch.position; + _panFingerId = touch.fingerId; + _panActive = true; + } else if (touch.fingerId == _panFingerId && touch.phase == TouchPhase.Moved) { PanCamera(touch.position); } break; case 2: // Zooming - panActive = false; + _panActive = false; Vector2[] newPositions = new Vector2[]{Input.GetTouch(0).position, Input.GetTouch(1).position}; - if (!zoomActive) { - lastZoomPositions = newPositions; - zoomActive = true; + if (!_zoomActive) { + _lastZoomPositions = newPositions; + _zoomActive = true; } else { // Zoom based on the distance between the new positions compared to the // distance between the previous positions. float newDistance = Vector2.Distance(newPositions[0], newPositions[1]); - float oldDistance = Vector2.Distance(lastZoomPositions[0], lastZoomPositions[1]); + float oldDistance = Vector2.Distance(_lastZoomPositions[0], _lastZoomPositions[1]); float offset = newDistance - oldDistance; ZoomCamera(offset, ZoomSpeedTouch); - lastZoomPositions = newPositions; + _lastZoomPositions = newPositions; } break; default: - panActive = false; - zoomActive = false; + _panActive = false; + _zoomActive = false; break; } } @@ -92,41 +90,41 @@ public class cameraHandler : MonoBehaviour { // On mouse up, disable panning. // If there is no mouse being pressed, do nothing. if (Input.GetMouseButtonDown(0)) { - panActive = true; - lastPanPosition = Input.mousePosition; + _panActive = true; + _lastPanPosition = Input.mousePosition; } else if (Input.GetMouseButtonUp(0)) { - panActive = false; + _panActive = false; } else if (Input.GetMouseButton(0)) { PanCamera(Input.mousePosition); } // Check for scrolling to zoom the camera float scroll = Input.GetAxis("Mouse ScrollWheel"); - zoomActive = true; + _zoomActive = true; ZoomCamera(scroll, ZoomSpeedMouse); - zoomActive = false; + _zoomActive = false; } void ZoomCamera(float offset, float speed) { - if (!zoomActive || offset == 0) { + if (!_zoomActive || offset == 0) { return; } - cam.orthographicSize = Mathf.Clamp(cam.orthographicSize - (offset * speed), ZoomBounds[0], ZoomBounds[1]); + _cam.orthographicSize = Mathf.Clamp(_cam.orthographicSize - (offset * speed), ZoomBounds[0], ZoomBounds[1]); } void PanCamera(Vector3 newPanPosition) { - if (!panActive) { + if (!_panActive) { return; } // Translate the camera position based on the new input position - Vector3 offset = cam.ScreenToViewportPoint(lastPanPosition - newPanPosition); + Vector3 offset = _cam.ScreenToViewportPoint(_lastPanPosition - newPanPosition); Vector3 move = new Vector3(offset.x * PanSpeed, offset.y * PanSpeed, 0f); transform.Translate(move, Space.World); ClampToBounds(); - lastPanPosition = newPanPosition; + _lastPanPosition = newPanPosition; } void ClampToBounds() { diff --git a/td/Assets/Scripts/castle.cs b/td/Assets/Scripts/castle.cs new file mode 100644 index 0000000..5c8835c --- /dev/null +++ b/td/Assets/Scripts/castle.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Castle : MonoBehaviour { + + private void Update () { + //CheckThing(); + } + + private void CheckThing() { + GameObject[] enemies = GameObject.FindGameObjectsWithTag ("enemy"); + + foreach (var enemy in enemies) { + var distanceToEnemy = Vector3.Distance (transform.position, enemy.transform.position); + if (distanceToEnemy <= 0) { + Debug.Log("INTRUDER!"); + } + } + } + + +} diff --git a/td/Assets/Scripts/castle.cs.meta b/td/Assets/Scripts/castle.cs.meta new file mode 100644 index 0000000..246ac0b --- /dev/null +++ b/td/Assets/Scripts/castle.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c6004dcebebd0498389086d43a3bd6fa +timeCreated: 1507302323 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/td/Assets/Scripts/developerMode.cs b/td/Assets/Scripts/developerMode.cs index 4f241cf..a71d4c7 100644 --- a/td/Assets/Scripts/developerMode.cs +++ b/td/Assets/Scripts/developerMode.cs @@ -3,49 +3,49 @@ using System.Collections.Generic; using UnityEngine.UI; using UnityEngine; -public class developerMode : MonoBehaviour { +public class DeveloperMode : MonoBehaviour { - public string output = ""; - public string stack = ""; - public bool cheatsAllowed; + public string Output = ""; + public string Stack = ""; + public bool CheatsAllowed; - GameObject pnlCanvas; - GameObject pnlCheats; - Button btnToggleCheats; - Text lblConsoleLog; + GameObject _pnlCanvas; + GameObject _pnlCheats; + Button _btnToggleCheats; + Text _lblConsoleLog; - bool developerModeActive; - bool cheatMenuOpen; + bool _developerModeActive; + bool _cheatMenuOpen; void Start () { /* Panels */ - pnlCanvas = this.gameObject.transform.GetChild (0).gameObject; - pnlCheats = pnlCanvas.transform.Find ("cheatMenu").gameObject; + _pnlCanvas = this.gameObject.transform.GetChild (0).gameObject; + _pnlCheats = _pnlCanvas.transform.Find ("cheatMenu").gameObject; /* Buttons */ /* Button handlers */ /* Lablels */ - lblConsoleLog = pnlCanvas.transform.Find ("consoleLog").gameObject.GetComponent (); + _lblConsoleLog = _pnlCanvas.transform.Find ("consoleLog").gameObject.GetComponent (); /* Do setup */ - lblConsoleLog.text = ""; + _lblConsoleLog.text = ""; - if (cheatsAllowed) { - btnToggleCheats = pnlCanvas.transform.Find ("toggleCheats").gameObject.GetComponent