├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── CameraTools.sln ├── CameraTools ├── CCInputUtils.cs ├── CTAtmosphericAudioController.cs ├── CTPartAudioController.cs ├── CTPersistantFIeld.cs ├── CamTools.cs ├── CameraKeyframe.cs ├── CameraPath.cs ├── CameraTools.csproj ├── CameraTransformation.cs ├── Curve3D.cs ├── Distribution │ └── GameData │ │ └── CameraTools │ │ ├── ATM_CameraTools.cfg │ │ ├── CameraTools.version │ │ ├── Changelog.txt │ │ ├── License.txt │ │ ├── Plugins │ │ └── CameraTools.dll │ │ ├── Sounds │ │ ├── sonicBoom.wav │ │ ├── windhowl.wav │ │ ├── windloop.wav │ │ └── windtear.wav │ │ ├── Textures │ │ └── icon.png │ │ ├── paths.cfg │ │ └── settings.cfg ├── LocalDev │ ├── 7za_dir.txt │ ├── dist_dir.txt │ ├── ksp_dir.txt │ ├── ksp_dir2.txt │ ├── mono_exe.txt │ └── pdb2mdb_exe.txt ├── Properties │ └── AssemblyInfo.cs ├── RotationAnimation.cs ├── Vector3Animation.cs └── bin │ └── Release │ └── CameraTools.dll └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | ## private libraries 5 | Assembly* 6 | System* 7 | mscorlib.dll 8 | Mono* 9 | TrackIR* 10 | Unity* 11 | TDx* 12 | 13 | # User-specific files 14 | *.suo 15 | *.user 16 | *.sln.docstates 17 | 18 | # Build results 19 | [Dd]ebug/ 20 | [Dd]ebugPublic/ 21 | #[Rr]elease/ 22 | x64/ 23 | build/ 24 | bld/ 25 | # [Bb]in/ 26 | [Oo]bj/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | #NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | *.ncrunch* 104 | _NCrunch_* 105 | .*crunch*.local.xml 106 | 107 | # MightyMoose 108 | *.mm.* 109 | AutoTest.Net/ 110 | 111 | # Web workbench (sass) 112 | .sass-cache/ 113 | 114 | # Installshield output folder 115 | [Ee]xpress/ 116 | 117 | # DocProject is a documentation generator add-in 118 | DocProject/buildhelp/ 119 | DocProject/Help/*.HxT 120 | DocProject/Help/*.HxC 121 | DocProject/Help/*.hhc 122 | DocProject/Help/*.hhk 123 | DocProject/Help/*.hhp 124 | DocProject/Help/Html2 125 | DocProject/Help/html 126 | 127 | # Click-Once directory 128 | publish/ 129 | 130 | # Publish Web Output 131 | *.[Pp]ublish.xml 132 | *.azurePubxml 133 | 134 | # NuGet Packages Directory 135 | packages/ 136 | ## TODO: If the tool you use requires repositories.config uncomment the next line 137 | #!packages/repositories.config 138 | 139 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 140 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file to a newer 167 | # Visual Studio version. Backup files are not needed, because we have git ;-) 168 | _UpgradeReport_Files/ 169 | Backup*/ 170 | UpgradeLog*.XML 171 | UpgradeLog*.htm 172 | 173 | # SQL Server files 174 | *.mdf 175 | *.ldf 176 | 177 | # Business Intelligence projects 178 | *.rdl.data 179 | *.bim.layout 180 | *.bim_*.settings 181 | 182 | # Microsoft Fakes 183 | FakesAssemblies/ 184 | 185 | # ========================= 186 | # Operating System Files 187 | # ========================= 188 | 189 | # OSX 190 | # ========================= 191 | 192 | .DS_Store 193 | .AppleDouble 194 | .LSOverride 195 | 196 | # Icon must ends with two \r. 197 | Icon 198 | # Thumbnails 199 | ._* 200 | 201 | # Files that might appear on external disk 202 | .Spotlight-V100 203 | .Trashes 204 | 205 | # Windows 206 | # ========================= 207 | 208 | # Windows image file caches 209 | Thumbs.db 210 | ehthumbs.db 211 | 212 | # Folder config file 213 | Desktop.ini 214 | 215 | # Recycle Bin used on file shares 216 | $RECYCLE.BIN/ 217 | 218 | # Windows Installer files 219 | *.cab 220 | *.msi 221 | *.msm 222 | *.msp 223 | 224 | *.zip 225 | *.bat 226 | 227 | KSPAssets.dll 228 | KSPCore.dll 229 | KSPUtil.dll 230 | SaveUpgradePipeline.Core.dll 231 | Vectrosity.dll 232 | 233 | /CameraTools/libs 234 | /.vs/config 235 | /CameraTools.sln.DotSettings 236 | /.vs/CameraTools/v15/sqlite3/storage.ide 237 | /.vs/CameraTools 238 | /.vs 239 | /CameraTools/bin/Release/KSPTrackIR.dll 240 | /CameraTools/bin/Release/KSPAssets.XmlSerializers.dll 241 | /CameraTools/bin/Release/Ionic.Zip.dll 242 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | All changes below here are by BahamutoD with the exception of my recompile. 3 | 4 | v1.6.0 recompiled for 1.1.3 by westamastaflash 5 | - 1.1 compat and path tool 6 | - fix loading paths/deleting paths, fix deleting selected key 7 | - set spatial blend to 3d audio 8 | 9 | v1.5.1 10 | - Dogfight mode auto-resets when a new target is selected or active vessel is switched 11 | - Auto targeting option with BDArmory AI pilot target 12 | 13 | v1.5 14 | - Dogfight chase mode 15 | - Autozoom margin slider 16 | 17 | v1.4.2 18 | - Slight UI tweak 19 | - Incremental buttons for manual offset 20 | 21 | v1.4.1 22 | - Ability to save persistant settings 23 | - Fixed part audio too loud when stationary 24 | - Fixed inability to select auto position without unchecking manual position 25 | - Stopped sonic boom being played when vessel breaks sound barrier after wavefront already passed camera 26 | - Increased sonic boom volume 27 | - Temporary fix for silent atmospheric audio when >~600m/s 28 | 29 | v1.4 30 | - Atmospheric audio effects (toggleable) 31 | - Camera shake (adjustable) 32 | 33 | v1.3 34 | - 1.0+ Compatibility 35 | - Manual camera position now persists after resetting camera 36 | - Bind activate/reset key by recording instead of typing button name 37 | - Camera no longer resets when pausing 38 | 39 | 40 | v1.2 41 | - Added Orbit frame of reference 42 | - Fixed issues with setting camera offset to vertically launching vehicles 43 | 44 | v1.1 45 | - 0.25 update 46 | - Added ability to set location -before- activating camera 47 | - Fixed text fields in GUI (it won't fight you when entering negatives or decimals) 48 | - Fixed Toolbar Icon 49 | - Greatly reduced motion of stationary camera when vessel is accelerating/turning 50 | 51 | 52 | v1.0 53 | - Initial release -------------------------------------------------------------------------------- /CameraTools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraTools", "CameraTools\CameraTools.csproj", "{446E2470-00DC-4835-B62D-9DB8A7D41F4A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x86 = Debug|x86 12 | Release|Any CPU = Release|Any CPU 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Debug|x86.ActiveCfg = Debug|x86 19 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Debug|x86.Build.0 = Debug|x86 20 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Release|x86.ActiveCfg = Release|x86 23 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A}.Release|x86.Build.0 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(MonoDevelopProperties) = preSolution 29 | StartupItem = CameraTools.csproj 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /CameraTools/CCInputUtils.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18449 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | using System; 11 | using UnityEngine; 12 | 13 | namespace CameraTools 14 | { 15 | public class CCInputUtils 16 | { 17 | public static string GetInputString() 18 | { 19 | //keyCodes 20 | string[] names = System.Enum.GetNames(typeof(KeyCode)); 21 | int numberOfKeycodes = names.Length; 22 | 23 | for(int i = 0; i < numberOfKeycodes; i++) 24 | { 25 | string output = names[i]; 26 | 27 | if(output.Contains("Keypad")) 28 | { 29 | output = "["+output.Substring(6).ToLower()+"]"; 30 | } 31 | else if(output.Contains("Alpha")) 32 | { 33 | output = output.Substring(5); 34 | } 35 | else //lower case key 36 | { 37 | output = output.ToLower(); 38 | } 39 | 40 | //modifiers 41 | if(output.Contains("control")) 42 | { 43 | output = output.Split('c')[0] + " ctrl"; 44 | } 45 | else if(output.Contains("alt")) 46 | { 47 | output = output.Split('a')[0] + " alt"; 48 | } 49 | else if(output.Contains("shift")) 50 | { 51 | output = output.Split ('s')[0] + " shift"; 52 | } 53 | else if(output.Contains("command")) 54 | { 55 | output = output.Split('c')[0]+" cmd"; 56 | } 57 | 58 | 59 | //special keys 60 | else if(output == "backslash") 61 | { 62 | output = @"\"; 63 | } 64 | else if(output == "backquote") 65 | { 66 | output = "`"; 67 | } 68 | else if(output == "[period]") 69 | { 70 | output = "[.]"; 71 | } 72 | else if(output == "[plus]") 73 | { 74 | output = "[+]"; 75 | } 76 | else if(output == "[multiply]") 77 | { 78 | output = "[*]"; 79 | } 80 | else if(output == "[divide]") 81 | { 82 | output = "[/]"; 83 | } 84 | else if(output == "[minus]") 85 | { 86 | output = "[-]"; 87 | } 88 | else if(output == "[enter]") 89 | { 90 | output = "enter"; 91 | } 92 | else if(output.Contains("page")) 93 | { 94 | output = output.Insert(4, " "); 95 | } 96 | else if(output.Contains("arrow")) 97 | { 98 | output = output.Split('a')[0]; 99 | } 100 | else if(output == "capslock") 101 | { 102 | output = "caps lock"; 103 | } 104 | else if(output == "minus") 105 | { 106 | output = "-"; 107 | } 108 | 109 | //test if input is valid 110 | try 111 | { 112 | if(Input.GetKey(output)) 113 | { 114 | return output; 115 | } 116 | } 117 | catch(System.Exception) 118 | { 119 | } 120 | 121 | } 122 | 123 | //mouse 124 | for(int m = 0; m < 6; m++) 125 | { 126 | string inputString = "mouse "+m; 127 | try 128 | { 129 | if(Input.GetKey(inputString)) 130 | { 131 | return inputString; 132 | } 133 | } 134 | catch(UnityException) 135 | { 136 | Debug.Log ("Invalid mouse: "+inputString); 137 | } 138 | } 139 | 140 | //joysticks 141 | for(int j = 1; j < 12; j++) 142 | { 143 | for(int b = 0; b<20; b++) 144 | { 145 | string inputString = "joystick "+j+" button "+b; 146 | try 147 | { 148 | if(Input.GetKey(inputString)) 149 | { 150 | return inputString; 151 | } 152 | } 153 | catch(UnityException) 154 | { 155 | return string.Empty; 156 | } 157 | 158 | } 159 | } 160 | 161 | return string.Empty; 162 | } 163 | 164 | 165 | } 166 | } 167 | 168 | -------------------------------------------------------------------------------- /CameraTools/CTAtmosphericAudioController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace CameraTools 4 | { 5 | public class CTAtmosphericAudioController : MonoBehaviour 6 | { 7 | AudioSource windAudioSource; 8 | AudioSource windHowlAudioSource; 9 | AudioSource windTearAudioSource; 10 | 11 | AudioSource sonicBoomSource; 12 | 13 | Vessel vessel; 14 | 15 | bool playedBoom = false; 16 | 17 | void Awake() 18 | { 19 | vessel = GetComponent(); 20 | windAudioSource = gameObject.AddComponent(); 21 | windAudioSource.minDistance = 10; 22 | windAudioSource.maxDistance = 10000; 23 | windAudioSource.dopplerLevel = .35f; 24 | windAudioSource.spatialBlend = 1; 25 | AudioClip windclip = GameDatabase.Instance.GetAudioClip("CameraTools/Sounds/windloop"); 26 | if(!windclip) 27 | { 28 | Destroy (this); 29 | return; 30 | } 31 | windAudioSource.clip = windclip; 32 | 33 | windHowlAudioSource = gameObject.AddComponent(); 34 | windHowlAudioSource.minDistance = 10; 35 | windHowlAudioSource.maxDistance = 7000; 36 | windHowlAudioSource.dopplerLevel = .5f; 37 | windHowlAudioSource.pitch = 0.25f; 38 | windHowlAudioSource.clip = GameDatabase.Instance.GetAudioClip("CameraTools/Sounds/windhowl"); 39 | windHowlAudioSource.spatialBlend = 1; 40 | 41 | windTearAudioSource = gameObject.AddComponent(); 42 | windTearAudioSource.minDistance = 10; 43 | windTearAudioSource.maxDistance = 5000; 44 | windTearAudioSource.dopplerLevel = 0.45f; 45 | windTearAudioSource.pitch = 0.65f; 46 | windTearAudioSource.clip = GameDatabase.Instance.GetAudioClip("CameraTools/Sounds/windtear"); 47 | windTearAudioSource.spatialBlend = 1; 48 | 49 | sonicBoomSource = new GameObject().AddComponent(); 50 | sonicBoomSource.transform.parent = vessel.transform; 51 | sonicBoomSource.transform.localPosition = Vector3.zero; 52 | sonicBoomSource.minDistance = 50; 53 | sonicBoomSource.maxDistance = 20000; 54 | sonicBoomSource.dopplerLevel = 0; 55 | sonicBoomSource.clip = GameDatabase.Instance.GetAudioClip("CameraTools/Sounds/sonicBoom"); 56 | sonicBoomSource.volume = Mathf.Clamp01(vessel.GetTotalMass()/4f); 57 | sonicBoomSource.Stop(); 58 | sonicBoomSource.spatialBlend = 1; 59 | 60 | float angleToCam = Vector3.Angle(vessel.srf_velocity, FlightCamera.fetch.mainCamera.transform.position - vessel.transform.position); 61 | angleToCam = Mathf.Clamp(angleToCam, 1, 180); 62 | if(vessel.srfSpeed / (angleToCam) < 3.67f) 63 | { 64 | playedBoom = true; 65 | } 66 | 67 | CamTools.OnResetCTools += OnResetCTools; 68 | } 69 | 70 | 71 | void FixedUpdate() 72 | { 73 | if(!vessel) 74 | { 75 | return; 76 | } 77 | if(Time.timeScale > 0 && vessel.dynamicPressurekPa > 0) 78 | { 79 | float srfSpeed = (float)vessel.srfSpeed; 80 | srfSpeed = Mathf.Min(srfSpeed, 550f); 81 | float angleToCam = Vector3.Angle(vessel.srf_velocity, FlightCamera.fetch.mainCamera.transform.position - vessel.transform.position); 82 | angleToCam = Mathf.Clamp(angleToCam, 1, 180); 83 | 84 | 85 | float lagAudioFactor = (75000 / (Vector3.Distance(vessel.transform.position, FlightCamera.fetch.mainCamera.transform.position) * srfSpeed * angleToCam / 90)); 86 | lagAudioFactor = Mathf.Clamp(lagAudioFactor * lagAudioFactor * lagAudioFactor, 0, 4); 87 | lagAudioFactor += srfSpeed / 230; 88 | 89 | float waveFrontFactor = ((3.67f * angleToCam)/srfSpeed); 90 | waveFrontFactor = Mathf.Clamp(waveFrontFactor * waveFrontFactor * waveFrontFactor, 0, 2); 91 | 92 | 93 | if(vessel.srfSpeed > CamTools.speedOfSound) 94 | { 95 | waveFrontFactor = (srfSpeed / (angleToCam) < 3.67f) ? waveFrontFactor + ((srfSpeed/(float)CamTools.speedOfSound)*waveFrontFactor) : 0; 96 | if(waveFrontFactor > 0) 97 | { 98 | if(!playedBoom) 99 | { 100 | sonicBoomSource.transform.position = vessel.transform.position + (-vessel.srf_velocity); 101 | sonicBoomSource.PlayOneShot(sonicBoomSource.clip); 102 | } 103 | playedBoom = true; 104 | } 105 | else 106 | { 107 | 108 | } 109 | } 110 | else if(CamTools.speedOfSound / (angleToCam) < 3.67f) 111 | { 112 | playedBoom = true; 113 | } 114 | 115 | lagAudioFactor *= waveFrontFactor; 116 | 117 | float sqrAccel = (float)vessel.acceleration.sqrMagnitude; 118 | 119 | //windloop 120 | if(!windAudioSource.isPlaying) 121 | { 122 | windAudioSource.Play(); 123 | //Debug.Log("vessel dynamic pressure: " + vessel.dynamicPressurekPa); 124 | } 125 | float pressureFactor = Mathf.Clamp01((float)vessel.dynamicPressurekPa / 50f); 126 | float massFactor = Mathf.Clamp01(vessel.GetTotalMass() / 60f); 127 | float gFactor = Mathf.Clamp(sqrAccel / 225, 0, 1.5f); 128 | windAudioSource.volume = massFactor * pressureFactor * gFactor * lagAudioFactor; 129 | 130 | 131 | //windhowl 132 | if(!windHowlAudioSource.isPlaying) 133 | { 134 | windHowlAudioSource.Play(); 135 | } 136 | float pressureFactor2 = Mathf.Clamp01((float)vessel.dynamicPressurekPa / 20f); 137 | float massFactor2 = Mathf.Clamp01(vessel.GetTotalMass() / 30f); 138 | windHowlAudioSource.volume = pressureFactor2 * massFactor2 * lagAudioFactor; 139 | windHowlAudioSource.maxDistance = Mathf.Clamp(lagAudioFactor * 2500, windTearAudioSource.minDistance, 16000); 140 | 141 | //windtear 142 | if(!windTearAudioSource.isPlaying) 143 | { 144 | windTearAudioSource.Play(); 145 | } 146 | float pressureFactor3 = Mathf.Clamp01((float)vessel.dynamicPressurekPa / 40f); 147 | float massFactor3 = Mathf.Clamp01(vessel.GetTotalMass() / 10f); 148 | //float gFactor3 = Mathf.Clamp(sqrAccel / 325, 0.25f, 1f); 149 | windTearAudioSource.volume = pressureFactor3 * massFactor3; 150 | 151 | windTearAudioSource.minDistance = lagAudioFactor * 1; 152 | windTearAudioSource.maxDistance = Mathf.Clamp(lagAudioFactor * 2500, windTearAudioSource.minDistance, 16000); 153 | 154 | } 155 | else 156 | { 157 | if(windAudioSource.isPlaying) 158 | { 159 | windAudioSource.Stop(); 160 | } 161 | 162 | if(windHowlAudioSource.isPlaying) 163 | { 164 | windHowlAudioSource.Stop(); 165 | } 166 | 167 | if(windTearAudioSource.isPlaying) 168 | { 169 | windTearAudioSource.Stop(); 170 | } 171 | } 172 | } 173 | 174 | void OnDestroy() 175 | { 176 | if(sonicBoomSource) 177 | { 178 | Destroy(sonicBoomSource.gameObject); 179 | } 180 | CamTools.OnResetCTools -= OnResetCTools; 181 | } 182 | 183 | void OnResetCTools() 184 | { 185 | Destroy(windAudioSource); 186 | Destroy(windHowlAudioSource); 187 | Destroy(windTearAudioSource); 188 | 189 | Destroy(this); 190 | } 191 | } 192 | } 193 | 194 | -------------------------------------------------------------------------------- /CameraTools/CTPartAudioController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | namespace CameraTools 3 | { 4 | public class CTPartAudioController : MonoBehaviour 5 | { 6 | Vessel vessel; 7 | Part part; 8 | 9 | public AudioSource audioSource; 10 | 11 | 12 | float origMinDist = 1; 13 | float origMaxDist = 1; 14 | 15 | float modMinDist = 10; 16 | float modMaxDist = 10000; 17 | 18 | AudioRolloffMode origRolloffMode; 19 | 20 | void Awake() 21 | { 22 | part = GetComponentInParent(); 23 | vessel = part.vessel; 24 | 25 | CamTools.OnResetCTools += OnResetCTools; 26 | } 27 | 28 | void Start() 29 | { 30 | if(!audioSource) 31 | { 32 | Destroy(this); 33 | return; 34 | } 35 | 36 | origMinDist = audioSource.minDistance; 37 | origMaxDist = audioSource.maxDistance; 38 | origRolloffMode = audioSource.rolloffMode; 39 | audioSource.rolloffMode = AudioRolloffMode.Logarithmic; 40 | audioSource.spatialBlend = 1; 41 | 42 | } 43 | 44 | void FixedUpdate() 45 | { 46 | if(!audioSource) 47 | { 48 | Destroy(this); 49 | return; 50 | } 51 | 52 | if(!part || !vessel) 53 | { 54 | Destroy(this); 55 | return; 56 | } 57 | 58 | 59 | float angleToCam = Vector3.Angle(vessel.srf_velocity, FlightCamera.fetch.mainCamera.transform.position - vessel.transform.position); 60 | angleToCam = Mathf.Clamp(angleToCam, 1, 180); 61 | 62 | float srfSpeed = (float)vessel.srfSpeed; 63 | srfSpeed = Mathf.Min(srfSpeed, 550f); 64 | 65 | float lagAudioFactor = (75000 / (Vector3.Distance(vessel.transform.position, FlightCamera.fetch.mainCamera.transform.position) * srfSpeed * angleToCam / 90)); 66 | lagAudioFactor = Mathf.Clamp(lagAudioFactor * lagAudioFactor * lagAudioFactor, 0, 4); 67 | lagAudioFactor += srfSpeed / 230; 68 | 69 | float waveFrontFactor = ((3.67f * angleToCam)/srfSpeed); 70 | waveFrontFactor = Mathf.Clamp(waveFrontFactor * waveFrontFactor * waveFrontFactor, 0, 2); 71 | if(vessel.srfSpeed > CamTools.speedOfSound) 72 | { 73 | waveFrontFactor = (srfSpeed / (angleToCam) < 3.67f) ? waveFrontFactor + ((srfSpeed/(float)CamTools.speedOfSound)*waveFrontFactor): 0; 74 | } 75 | 76 | lagAudioFactor *= waveFrontFactor; 77 | 78 | audioSource.minDistance = Mathf.Lerp(origMinDist, modMinDist * lagAudioFactor, Mathf.Clamp01((float)vessel.srfSpeed/30)); 79 | audioSource.maxDistance = Mathf.Lerp(origMaxDist,Mathf.Clamp(modMaxDist * lagAudioFactor, audioSource.minDistance, 16000), Mathf.Clamp01((float)vessel.srfSpeed/30)); 80 | 81 | } 82 | 83 | void OnDestroy() 84 | { 85 | CamTools.OnResetCTools -= OnResetCTools; 86 | 87 | 88 | } 89 | 90 | void OnResetCTools() 91 | { 92 | audioSource.minDistance = origMinDist; 93 | audioSource.maxDistance = origMaxDist; 94 | audioSource.rolloffMode = origRolloffMode; 95 | Destroy(this); 96 | } 97 | 98 | 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /CameraTools/CTPersistantFIeld.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CameraTools 4 | { 5 | [AttributeUsage(AttributeTargets.Field)] 6 | public class CTPersistantField : Attribute 7 | { 8 | public static string settingsURL = "GameData/CameraTools/settings.cfg"; 9 | 10 | public CTPersistantField() 11 | { 12 | 13 | } 14 | 15 | public static void Save() 16 | { 17 | ConfigNode fileNode = ConfigNode.Load(settingsURL); 18 | ConfigNode settings = fileNode.GetNode("CToolsSettings"); 19 | 20 | 21 | foreach(var field in typeof(CamTools).GetFields()) 22 | { 23 | if(!field.IsDefined(typeof(CTPersistantField), false)) continue; 24 | 25 | settings.SetValue(field.Name, field.GetValue(CamTools.fetch).ToString(), true); 26 | } 27 | 28 | fileNode.Save(settingsURL); 29 | } 30 | 31 | public static void Load() 32 | { 33 | ConfigNode fileNode = ConfigNode.Load(settingsURL); 34 | ConfigNode settings = fileNode.GetNode("CToolsSettings"); 35 | 36 | foreach(var field in typeof(CamTools).GetFields()) 37 | { 38 | if(!field.IsDefined(typeof(CTPersistantField), false)) continue; 39 | 40 | if(settings.HasValue(field.Name)) 41 | { 42 | object parsedValue = ParseValue(field.FieldType, settings.GetValue(field.Name)); 43 | if(parsedValue != null) 44 | { 45 | field.SetValue(CamTools.fetch, parsedValue); 46 | } 47 | } 48 | } 49 | } 50 | 51 | public static object ParseValue(Type type, string value) 52 | { 53 | if(type == typeof(string)) 54 | { 55 | return value; 56 | } 57 | 58 | if(type == typeof(bool)) 59 | { 60 | return bool.Parse(value); 61 | } 62 | else if(type.IsEnum) 63 | { 64 | return Enum.Parse(type, value); 65 | } 66 | else if(type == typeof(float)) 67 | { 68 | return float.Parse(value); 69 | } 70 | else if(type == typeof(Single)) 71 | { 72 | return Single.Parse(value); 73 | } 74 | 75 | 76 | UnityEngine.Debug.LogError("CameraTools failed to parse settings field of type "+type.ToString()+" and value "+value); 77 | 78 | return null; 79 | } 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /CameraTools/CamTools.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using System.Reflection; 6 | using KSP.UI.Screens; 7 | namespace CameraTools 8 | { 9 | [KSPAddon(KSPAddon.Startup.Flight, false)] 10 | public class CamTools : MonoBehaviour 11 | { 12 | public static CamTools fetch; 13 | 14 | GameObject cameraParent; 15 | Vessel vessel; 16 | Vector3 origPosition; 17 | Quaternion origRotation; 18 | Transform origParent; 19 | float origNearClip; 20 | FlightCamera flightCamera; 21 | 22 | Part camTarget = null; 23 | 24 | [CTPersistantField] 25 | public ReferenceModes referenceMode = ReferenceModes.Surface; 26 | Vector3 cameraUp = Vector3.up; 27 | 28 | string fmUpKey = "[7]"; 29 | string fmDownKey = "[1]"; 30 | string fmForwardKey = "[8]"; 31 | string fmBackKey = "[5]"; 32 | string fmLeftKey = "[4]"; 33 | string fmRightKey = "[6]"; 34 | string fmZoomInKey = "[9]"; 35 | string fmZoomOutKey = "[3]"; 36 | // 37 | 38 | 39 | //current camera setting 40 | bool cameraToolActive = false; 41 | 42 | 43 | //GUI 44 | public static bool guiEnabled = false; 45 | public static bool hasAddedButton = false; 46 | bool updateFOV = false; 47 | float windowWidth = 250; 48 | float windowHeight = 400; 49 | float draggableHeight = 40; 50 | float leftIndent = 12; 51 | float entryHeight = 20; 52 | 53 | [CTPersistantField] 54 | public ToolModes toolMode = ToolModes.StationaryCamera; 55 | 56 | Rect windowRect = new Rect(0,0,0,0); 57 | bool gameUIToggle = true; 58 | float incrButtonWidth = 26; 59 | 60 | //stationary camera vars 61 | [CTPersistantField] 62 | public bool autoFlybyPosition = false; 63 | [CTPersistantField] 64 | public bool autoFOV = false; 65 | float manualFOV = 60; 66 | float currentFOV = 60; 67 | Vector3 manualPosition = Vector3.zero; 68 | [CTPersistantField] 69 | public float freeMoveSpeed = 10; 70 | string guiFreeMoveSpeed = "10"; 71 | [CTPersistantField] 72 | public float keyZoomSpeed = 1; 73 | string guiKeyZoomSpeed = "1"; 74 | float zoomFactor = 1; 75 | [CTPersistantField] 76 | public float zoomExp = 1; 77 | [CTPersistantField] 78 | public bool enableKeypad = false; 79 | [CTPersistantField] 80 | public float maxRelV = 2500; 81 | 82 | bool setPresetOffset = false; 83 | Vector3 presetOffset = Vector3.zero; 84 | bool hasSavedRotation = false; 85 | Quaternion savedRotation; 86 | [CTPersistantField] 87 | public bool manualOffset = false; 88 | [CTPersistantField] 89 | public float manualOffsetForward = 500; 90 | [CTPersistantField] 91 | public float manualOffsetRight = 50; 92 | [CTPersistantField] 93 | public float manualOffsetUp = 5; 94 | string guiOffsetForward = "500"; 95 | string guiOffsetRight = "50"; 96 | string guiOffsetUp = "5"; 97 | 98 | Vector3 lastVesselPosition = Vector3.zero; 99 | Vector3 lastTargetPosition = Vector3.zero; 100 | bool hasTarget = false; 101 | 102 | [CTPersistantField] 103 | public bool useOrbital = false; 104 | 105 | [CTPersistantField] 106 | public bool targetCoM = false; 107 | 108 | bool hasDied = false; 109 | float diedTime = 0; 110 | //vessel reference mode 111 | Vector3 initialVelocity = Vector3.zero; 112 | Vector3 initialPosition = Vector3.zero; 113 | Orbit initialOrbit = null; 114 | double initialUT; 115 | 116 | //retaining position and rotation after vessel destruction 117 | Vector3 lastPosition; 118 | Quaternion lastRotation; 119 | 120 | 121 | //click waiting stuff 122 | bool waitingForTarget = false; 123 | bool waitingForPosition = false; 124 | 125 | bool mouseUp = false; 126 | 127 | //Keys 128 | [CTPersistantField] 129 | public string cameraKey = "home"; 130 | [CTPersistantField] 131 | public string revertKey = "end"; 132 | 133 | //recording input for key binding 134 | bool isRecordingInput = false; 135 | bool isRecordingActivate = false; 136 | bool isRecordingRevert = false; 137 | 138 | Vector3 resetPositionFix;//fixes position movement after setting and resetting camera 139 | 140 | //floating origin shift handler 141 | Vector3d lastOffset = FloatingOrigin.fetch.offset; 142 | 143 | AudioSource[] audioSources; 144 | float[] originalAudioSourceDoppler; 145 | bool hasSetDoppler = false; 146 | 147 | [CTPersistantField] 148 | public bool useAudioEffects = true; 149 | 150 | //camera shake 151 | Vector3 shakeOffset = Vector3.zero; 152 | float shakeMagnitude = 0; 153 | [CTPersistantField] 154 | public float shakeMultiplier = 1; 155 | 156 | public delegate void ResetCTools(); 157 | public static event ResetCTools OnResetCTools; 158 | public static double speedOfSound = 330; 159 | 160 | //dogfight cam 161 | Vessel dogfightPrevTarget; 162 | Vessel dogfightTarget; 163 | [CTPersistantField] 164 | float dogfightDistance = 30; 165 | [CTPersistantField] 166 | float dogfightOffsetX = 10; 167 | [CTPersistantField] 168 | float dogfightOffsetY = 4; 169 | float dogfightMaxOffset = 50; 170 | float dogfightLerp = 20; 171 | [CTPersistantField] 172 | float autoZoomMargin = 20; 173 | List loadedVessels; 174 | bool showingVesselList = false; 175 | bool dogfightLastTarget = false; 176 | Vector3 dogfightLastTargetPosition; 177 | Vector3 dogfightLastTargetVelocity; 178 | bool dogfightVelocityChase = false; 179 | //bdarmory 180 | bool hasBDAI = false; 181 | [CTPersistantField] 182 | public bool useBDAutoTarget = false; 183 | object aiComponent = null; 184 | FieldInfo bdAiTargetField; 185 | 186 | 187 | //pathing 188 | int selectedPathIndex = -1; 189 | List availablePaths; 190 | CameraPath currentPath 191 | { 192 | get 193 | { 194 | if(selectedPathIndex >= 0 && selectedPathIndex < availablePaths.Count) 195 | { 196 | return availablePaths[selectedPathIndex]; 197 | } 198 | else 199 | { 200 | return null; 201 | } 202 | } 203 | } 204 | int currentKeyframeIndex = -1; 205 | float currentKeyframeTime; 206 | string currKeyTimeString; 207 | bool showKeyframeEditor = false; 208 | float pathStartTime; 209 | bool isPlayingPath = false; 210 | float pathTime 211 | { 212 | get 213 | { 214 | return Time.time - pathStartTime; 215 | } 216 | } 217 | Vector2 keysScrollPos; 218 | 219 | void Awake() 220 | { 221 | if(fetch) 222 | { 223 | Destroy(fetch); 224 | } 225 | 226 | fetch = this; 227 | 228 | Load(); 229 | 230 | guiOffsetForward = manualOffsetForward.ToString(); 231 | guiOffsetRight = manualOffsetRight.ToString(); 232 | guiOffsetUp = manualOffsetUp.ToString(); 233 | guiKeyZoomSpeed = keyZoomSpeed.ToString(); 234 | guiFreeMoveSpeed = freeMoveSpeed.ToString(); 235 | } 236 | 237 | void Start() 238 | { 239 | windowRect = new Rect(Screen.width-windowWidth-40, 0, windowWidth, windowHeight); 240 | flightCamera = FlightCamera.fetch; 241 | cameraToolActive = false; 242 | SaveOriginalCamera(); 243 | 244 | AddToolbarButton(); 245 | 246 | GameEvents.onHideUI.Add(GameUIDisable); 247 | GameEvents.onShowUI.Add(GameUIEnable); 248 | //GameEvents.onGamePause.Add (PostDeathRevert); 249 | GameEvents.OnVesselRecoveryRequested.Add(PostDeathRevert); 250 | GameEvents.onFloatingOriginShift.Add(OnFloatingOriginShift); 251 | GameEvents.onGameSceneLoadRequested.Add(PostDeathRevert); 252 | 253 | cameraParent = new GameObject("StationaryCameraParent"); 254 | //cameraParent.SetActive(true); 255 | //cameraParent = (GameObject) Instantiate(cameraParent, Vector3.zero, Quaternion.identity); 256 | 257 | if(FlightGlobals.ActiveVessel != null) 258 | { 259 | cameraParent.transform.position = FlightGlobals.ActiveVessel.transform.position; 260 | vessel = FlightGlobals.ActiveVessel; 261 | 262 | CheckForBDAI(FlightGlobals.ActiveVessel); 263 | } 264 | bdAiTargetField = GetAITargetField(); 265 | GameEvents.onVesselChange.Add(SwitchToVessel); 266 | } 267 | 268 | void OnDestroy() 269 | { 270 | GameEvents.onVesselChange.Remove(SwitchToVessel); 271 | } 272 | 273 | void Update() 274 | { 275 | if(!isRecordingInput) 276 | { 277 | if(Input.GetKeyDown(KeyCode.KeypadDivide)) 278 | { 279 | guiEnabled = !guiEnabled; 280 | } 281 | 282 | if(Input.GetKeyDown(revertKey)) 283 | { 284 | RevertCamera(); 285 | } 286 | else if(Input.GetKeyDown(cameraKey)) 287 | { 288 | if(toolMode == ToolModes.StationaryCamera) 289 | { 290 | if(!cameraToolActive) 291 | { 292 | SaveOriginalCamera(); 293 | StartStationaryCamera(); 294 | } 295 | else 296 | { 297 | //RevertCamera(); 298 | StartStationaryCamera(); 299 | } 300 | } 301 | else if(toolMode == ToolModes.DogfightCamera) 302 | { 303 | if(!cameraToolActive) 304 | { 305 | SaveOriginalCamera(); 306 | StartDogfightCamera(); 307 | } 308 | else 309 | { 310 | StartDogfightCamera(); 311 | } 312 | } 313 | else if(toolMode == ToolModes.Pathing) 314 | { 315 | if(!cameraToolActive) 316 | { 317 | SaveOriginalCamera(); 318 | } 319 | StartPathingCam(); 320 | PlayPathingCam(); 321 | } 322 | } 323 | 324 | 325 | } 326 | 327 | if(Input.GetMouseButtonUp(0)) 328 | { 329 | mouseUp = true; 330 | } 331 | 332 | 333 | //get target transform from mouseClick 334 | if(waitingForTarget && mouseUp && Input.GetKeyDown(KeyCode.Mouse0)) 335 | { 336 | Part tgt = GetPartFromMouse(); 337 | if(tgt!=null) 338 | { 339 | camTarget = tgt; 340 | hasTarget = true; 341 | } 342 | else 343 | { 344 | Vector3 pos = GetPosFromMouse(); 345 | if(pos != Vector3.zero) 346 | { 347 | lastTargetPosition = pos; 348 | hasTarget = true; 349 | } 350 | } 351 | 352 | waitingForTarget = false; 353 | } 354 | 355 | //set position from mouseClick 356 | if(waitingForPosition && mouseUp && Input.GetKeyDown(KeyCode.Mouse0)) 357 | { 358 | Vector3 pos = GetPosFromMouse(); 359 | if(pos!=Vector3.zero)// && isStationaryCamera) 360 | { 361 | presetOffset = pos; 362 | setPresetOffset = true; 363 | } 364 | else Debug.Log ("No pos from mouse click"); 365 | 366 | waitingForPosition = false; 367 | } 368 | 369 | 370 | 371 | } 372 | 373 | public void ShakeCamera(float magnitude) 374 | { 375 | shakeMagnitude = Mathf.Max(shakeMagnitude, magnitude); 376 | } 377 | 378 | 379 | int posCounter = 0;//debug 380 | void FixedUpdate() 381 | { 382 | if(!FlightGlobals.ready) 383 | { 384 | return; 385 | } 386 | 387 | if(FlightGlobals.ActiveVessel != null && (vessel==null || vessel!=FlightGlobals.ActiveVessel)) 388 | { 389 | vessel = FlightGlobals.ActiveVessel; 390 | } 391 | 392 | if(vessel != null) 393 | { 394 | lastVesselPosition = vessel.transform.position; 395 | } 396 | 397 | 398 | //stationary camera 399 | if(cameraToolActive) 400 | { 401 | if(toolMode == ToolModes.StationaryCamera) 402 | { 403 | UpdateStationaryCamera(); 404 | } 405 | else if(toolMode == ToolModes.DogfightCamera) 406 | { 407 | UpdateDogfightCamera(); 408 | } 409 | else if(toolMode == ToolModes.Pathing) 410 | { 411 | UpdatePathingCam(); 412 | } 413 | } 414 | else 415 | { 416 | if(!autoFOV) 417 | { 418 | zoomFactor = Mathf.Exp(zoomExp)/Mathf.Exp(1); 419 | } 420 | } 421 | 422 | if(toolMode == ToolModes.DogfightCamera) 423 | { 424 | if(dogfightTarget && dogfightTarget.isActiveVessel) 425 | { 426 | dogfightTarget = null; 427 | if(cameraToolActive) 428 | { 429 | RevertCamera(); 430 | } 431 | } 432 | } 433 | 434 | 435 | if(hasDied && Time.time-diedTime > 2) 436 | { 437 | RevertCamera(); 438 | } 439 | } 440 | 441 | void StartDogfightCamera() 442 | { 443 | if(FlightGlobals.ActiveVessel == null) 444 | { 445 | Debug.Log("No active vessel."); 446 | return; 447 | } 448 | 449 | 450 | 451 | if(!dogfightTarget) 452 | { 453 | dogfightVelocityChase = true; 454 | } 455 | else 456 | { 457 | dogfightVelocityChase = false; 458 | } 459 | 460 | dogfightPrevTarget = dogfightTarget; 461 | 462 | hasDied = false; 463 | vessel = FlightGlobals.ActiveVessel; 464 | cameraUp = -FlightGlobals.getGeeForceAtPosition(vessel.CoM).normalized; 465 | 466 | flightCamera.SetTargetNone(); 467 | flightCamera.transform.parent = cameraParent.transform; 468 | flightCamera.DeactivateUpdate(); 469 | cameraParent.transform.position = vessel.transform.position+vessel.rb_velocity*Time.fixedDeltaTime; 470 | 471 | cameraToolActive = true; 472 | 473 | ResetDoppler(); 474 | if(OnResetCTools != null) 475 | { 476 | OnResetCTools(); 477 | } 478 | 479 | SetDoppler(false); 480 | AddAtmoAudioControllers(false); 481 | } 482 | 483 | void UpdateDogfightCamera() 484 | { 485 | if(!vessel || (!dogfightTarget && !dogfightLastTarget && !dogfightVelocityChase)) 486 | { 487 | RevertCamera(); 488 | return; 489 | } 490 | 491 | 492 | if(dogfightTarget) 493 | { 494 | dogfightLastTarget = true; 495 | dogfightLastTargetPosition = dogfightTarget.CoM; 496 | dogfightLastTargetVelocity = dogfightTarget.rb_velocity; 497 | } 498 | else if(dogfightLastTarget) 499 | { 500 | dogfightLastTargetPosition += dogfightLastTargetVelocity * Time.fixedDeltaTime; 501 | } 502 | 503 | cameraParent.transform.position = (vessel.CoM - (vessel.rb_velocity * Time.fixedDeltaTime)); 504 | 505 | if(dogfightVelocityChase) 506 | { 507 | if(vessel.srfSpeed > 1) 508 | { 509 | dogfightLastTargetPosition = vessel.CoM + (vessel.srf_velocity.normalized * 5000); 510 | } 511 | else 512 | { 513 | dogfightLastTargetPosition = vessel.CoM + (vessel.ReferenceTransform.up * 5000); 514 | } 515 | } 516 | 517 | Vector3 offsetDirection = Vector3.Cross(cameraUp, dogfightLastTargetPosition - vessel.CoM).normalized; 518 | Vector3 camPos = vessel.CoM + ((vessel.CoM - dogfightLastTargetPosition).normalized * dogfightDistance) + (dogfightOffsetX * offsetDirection) + (dogfightOffsetY * cameraUp); 519 | 520 | Vector3 localCamPos = cameraParent.transform.InverseTransformPoint(camPos); 521 | flightCamera.transform.localPosition = Vector3.Lerp(flightCamera.transform.localPosition, localCamPos, dogfightLerp * Time.fixedDeltaTime); 522 | 523 | //rotation 524 | Quaternion vesselLook = Quaternion.LookRotation(vessel.CoM-flightCamera.transform.position, cameraUp); 525 | Quaternion targetLook = Quaternion.LookRotation(dogfightLastTargetPosition-flightCamera.transform.position, cameraUp); 526 | Quaternion camRot = Quaternion.Lerp(vesselLook, targetLook, 0.5f); 527 | flightCamera.transform.rotation = Quaternion.Lerp(flightCamera.transform.rotation, camRot, dogfightLerp * Time.fixedDeltaTime); 528 | 529 | //autoFov 530 | if(autoFOV) 531 | { 532 | float targetFoV; 533 | if(dogfightVelocityChase) 534 | { 535 | targetFoV = Mathf.Clamp((7000 / (dogfightDistance + 100)) - 14 + autoZoomMargin, 2, 60); 536 | } 537 | else 538 | { 539 | float angle = Vector3.Angle((dogfightLastTargetPosition + (dogfightLastTargetVelocity * Time.fixedDeltaTime)) - flightCamera.transform.position, (vessel.CoM + (vessel.rb_velocity * Time.fixedDeltaTime)) - flightCamera.transform.position); 540 | targetFoV = Mathf.Clamp(angle + autoZoomMargin, 0.1f, 60f); 541 | } 542 | manualFOV = targetFoV; 543 | } 544 | //FOV 545 | if(!autoFOV) 546 | { 547 | zoomFactor = Mathf.Exp(zoomExp) / Mathf.Exp(1); 548 | manualFOV = 60 / zoomFactor; 549 | updateFOV = (currentFOV != manualFOV); 550 | if(updateFOV) 551 | { 552 | currentFOV = Mathf.Lerp(currentFOV, manualFOV, 0.1f); 553 | flightCamera.SetFoV(currentFOV); 554 | updateFOV = false; 555 | } 556 | } 557 | else 558 | { 559 | currentFOV = Mathf.Lerp(currentFOV, manualFOV, 0.1f); 560 | flightCamera.SetFoV(currentFOV); 561 | zoomFactor = 60 / currentFOV; 562 | } 563 | 564 | //free move 565 | if(enableKeypad) 566 | { 567 | if(Input.GetKey(fmUpKey)) 568 | { 569 | dogfightOffsetY += freeMoveSpeed * Time.fixedDeltaTime; 570 | dogfightOffsetY = Mathf.Clamp(dogfightOffsetY, -dogfightMaxOffset, dogfightMaxOffset); 571 | } 572 | else if(Input.GetKey(fmDownKey)) 573 | { 574 | dogfightOffsetY -= freeMoveSpeed * Time.fixedDeltaTime; 575 | dogfightOffsetY = Mathf.Clamp(dogfightOffsetY, -dogfightMaxOffset, dogfightMaxOffset); 576 | } 577 | if(Input.GetKey(fmForwardKey)) 578 | { 579 | dogfightDistance -= freeMoveSpeed * Time.fixedDeltaTime; 580 | dogfightDistance = Mathf.Clamp(dogfightDistance, 1f, 100f); 581 | } 582 | else if(Input.GetKey(fmBackKey)) 583 | { 584 | dogfightDistance += freeMoveSpeed * Time.fixedDeltaTime; 585 | dogfightDistance = Mathf.Clamp(dogfightDistance, 1f, 100f); 586 | } 587 | if(Input.GetKey(fmLeftKey)) 588 | { 589 | dogfightOffsetX -= freeMoveSpeed * Time.fixedDeltaTime; 590 | dogfightOffsetX = Mathf.Clamp(dogfightOffsetX, -dogfightMaxOffset, dogfightMaxOffset); 591 | } 592 | else if(Input.GetKey(fmRightKey)) 593 | { 594 | dogfightOffsetX += freeMoveSpeed * Time.fixedDeltaTime; 595 | dogfightOffsetX = Mathf.Clamp(dogfightOffsetX, -dogfightMaxOffset, dogfightMaxOffset); 596 | } 597 | 598 | //keyZoom 599 | if(!autoFOV) 600 | { 601 | if(Input.GetKey(fmZoomInKey)) 602 | { 603 | zoomExp = Mathf.Clamp(zoomExp + (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 604 | } 605 | else if(Input.GetKey(fmZoomOutKey)) 606 | { 607 | zoomExp = Mathf.Clamp(zoomExp - (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 608 | } 609 | } 610 | else 611 | { 612 | if(Input.GetKey(fmZoomInKey)) 613 | { 614 | autoZoomMargin = Mathf.Clamp(autoZoomMargin + (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 615 | } 616 | else if(Input.GetKey(fmZoomOutKey)) 617 | { 618 | autoZoomMargin = Mathf.Clamp(autoZoomMargin - (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 619 | } 620 | } 621 | } 622 | 623 | //vessel camera shake 624 | if(shakeMultiplier > 0) 625 | { 626 | foreach(var v in FlightGlobals.Vessels) 627 | { 628 | if(!v || !v.loaded || v.packed || v.isActiveVessel) continue; 629 | VesselCameraShake(v); 630 | } 631 | } 632 | UpdateCameraShake(); 633 | 634 | if(hasBDAI && useBDAutoTarget) 635 | { 636 | Vessel newAITarget = GetAITargetedVessel(); 637 | if(newAITarget) 638 | { 639 | dogfightTarget = newAITarget; 640 | } 641 | } 642 | 643 | if(dogfightTarget != dogfightPrevTarget) 644 | { 645 | //RevertCamera(); 646 | StartDogfightCamera(); 647 | } 648 | } 649 | 650 | void UpdateStationaryCamera() 651 | { 652 | if(useAudioEffects) 653 | { 654 | speedOfSound = 233 * Math.Sqrt(1 + (FlightGlobals.getExternalTemperature(vessel.GetWorldPos3D(), vessel.mainBody) / 273.15)); 655 | //Debug.Log("speed of sound: " + speedOfSound); 656 | } 657 | 658 | if(posCounter < 3) 659 | { 660 | posCounter++; 661 | Debug.Log("flightCamera position: " + flightCamera.transform.position); 662 | flightCamera.transform.position = resetPositionFix; 663 | if(hasSavedRotation) 664 | { 665 | flightCamera.transform.rotation = savedRotation; 666 | } 667 | } 668 | if(flightCamera.Target != null) flightCamera.SetTargetNone(); //dont go to next vessel if vessel is destroyed 669 | 670 | if (camTarget != null) 671 | { 672 | Vector3 lookPosition = camTarget.transform.position; 673 | if(targetCoM) 674 | { 675 | lookPosition = camTarget.vessel.CoM; 676 | } 677 | 678 | lookPosition += 2*camTarget.vessel.rb_velocity * Time.fixedDeltaTime; 679 | if(targetCoM) 680 | { 681 | lookPosition += camTarget.vessel.rb_velocity * Time.fixedDeltaTime; 682 | } 683 | 684 | flightCamera.transform.rotation = Quaternion.LookRotation(lookPosition - flightCamera.transform.position, cameraUp); 685 | lastTargetPosition = lookPosition; 686 | } 687 | else if(hasTarget) 688 | { 689 | flightCamera.transform.rotation = Quaternion.LookRotation(lastTargetPosition - flightCamera.transform.position, cameraUp); 690 | } 691 | 692 | 693 | 694 | if(vessel != null) 695 | { 696 | cameraParent.transform.position = manualPosition + (vessel.CoM - vessel.rb_velocity * Time.fixedDeltaTime); 697 | 698 | if(referenceMode == ReferenceModes.Surface) 699 | { 700 | flightCamera.transform.position -= Time.fixedDeltaTime * Mathf.Clamp((float)vessel.srf_velocity.magnitude, 0, maxRelV) * vessel.srf_velocity.normalized; 701 | } 702 | else if(referenceMode == ReferenceModes.Orbit) 703 | { 704 | flightCamera.transform.position -= Time.fixedDeltaTime * Mathf.Clamp((float)vessel.obt_velocity.magnitude, 0, maxRelV) * vessel.obt_velocity.normalized; 705 | } 706 | else if(referenceMode == ReferenceModes.InitialVelocity) 707 | { 708 | Vector3 camVelocity = Vector3.zero; 709 | if(useOrbital && initialOrbit != null) 710 | { 711 | camVelocity = (initialOrbit.getOrbitalVelocityAtUT(Planetarium.GetUniversalTime()).xzy - vessel.GetObtVelocity()); 712 | } 713 | else 714 | { 715 | camVelocity = (initialVelocity - vessel.srf_velocity); 716 | } 717 | flightCamera.transform.position += camVelocity * Time.fixedDeltaTime; 718 | } 719 | } 720 | 721 | 722 | //mouse panning, moving 723 | Vector3 forwardLevelAxis = (Quaternion.AngleAxis(-90, cameraUp) * flightCamera.transform.right).normalized; 724 | Vector3 rightAxis = (Quaternion.AngleAxis(90, forwardLevelAxis) * cameraUp).normalized; 725 | 726 | //free move 727 | if(enableKeypad) 728 | { 729 | if(Input.GetKey(fmUpKey)) 730 | { 731 | manualPosition += cameraUp * freeMoveSpeed * Time.fixedDeltaTime; 732 | } 733 | else if(Input.GetKey(fmDownKey)) 734 | { 735 | manualPosition -= cameraUp * freeMoveSpeed * Time.fixedDeltaTime; 736 | } 737 | if(Input.GetKey(fmForwardKey)) 738 | { 739 | manualPosition += forwardLevelAxis * freeMoveSpeed * Time.fixedDeltaTime; 740 | } 741 | else if(Input.GetKey(fmBackKey)) 742 | { 743 | manualPosition -= forwardLevelAxis * freeMoveSpeed * Time.fixedDeltaTime; 744 | } 745 | if(Input.GetKey(fmLeftKey)) 746 | { 747 | manualPosition -= flightCamera.transform.right * freeMoveSpeed * Time.fixedDeltaTime; 748 | } 749 | else if(Input.GetKey(fmRightKey)) 750 | { 751 | manualPosition += flightCamera.transform.right * freeMoveSpeed * Time.fixedDeltaTime; 752 | } 753 | 754 | //keyZoom 755 | if(!autoFOV) 756 | { 757 | if(Input.GetKey(fmZoomInKey)) 758 | { 759 | zoomExp = Mathf.Clamp(zoomExp + (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 760 | } 761 | else if(Input.GetKey(fmZoomOutKey)) 762 | { 763 | zoomExp = Mathf.Clamp(zoomExp - (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 764 | } 765 | } 766 | else 767 | { 768 | if(Input.GetKey(fmZoomInKey)) 769 | { 770 | autoZoomMargin = Mathf.Clamp(autoZoomMargin + (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 771 | } 772 | else if(Input.GetKey(fmZoomOutKey)) 773 | { 774 | autoZoomMargin = Mathf.Clamp(autoZoomMargin - (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 775 | } 776 | } 777 | } 778 | 779 | 780 | if(camTarget == null && Input.GetKey(KeyCode.Mouse1)) 781 | { 782 | flightCamera.transform.rotation *= Quaternion.AngleAxis(Input.GetAxis("Mouse X") * 1.7f, Vector3.up); //*(Mathf.Abs(Mouse.delta.x)/7) 783 | flightCamera.transform.rotation *= Quaternion.AngleAxis(-Input.GetAxis("Mouse Y") * 1.7f, Vector3.right); 784 | flightCamera.transform.rotation = Quaternion.LookRotation(flightCamera.transform.forward, cameraUp); 785 | } 786 | if(Input.GetKey(KeyCode.Mouse2)) 787 | { 788 | manualPosition += flightCamera.transform.right * Input.GetAxis("Mouse X") * 2; 789 | manualPosition += forwardLevelAxis * Input.GetAxis("Mouse Y") * 2; 790 | } 791 | manualPosition += cameraUp * 10 * Input.GetAxis("Mouse ScrollWheel"); 792 | 793 | //autoFov 794 | if(camTarget != null && autoFOV) 795 | { 796 | float cameraDistance = Vector3.Distance(camTarget.transform.position, flightCamera.transform.position); 797 | float targetFoV = Mathf.Clamp((7000 / (cameraDistance + 100)) - 14 + autoZoomMargin, 2, 60); 798 | //flightCamera.SetFoV(targetFoV); 799 | manualFOV = targetFoV; 800 | } 801 | //FOV 802 | if(!autoFOV) 803 | { 804 | zoomFactor = Mathf.Exp(zoomExp) / Mathf.Exp(1); 805 | manualFOV = 60 / zoomFactor; 806 | updateFOV = (currentFOV != manualFOV); 807 | if(updateFOV) 808 | { 809 | currentFOV = Mathf.Lerp(currentFOV, manualFOV, 0.1f); 810 | flightCamera.SetFoV(currentFOV); 811 | updateFOV = false; 812 | } 813 | } 814 | else 815 | { 816 | currentFOV = Mathf.Lerp(currentFOV, manualFOV, 0.1f); 817 | flightCamera.SetFoV(currentFOV); 818 | zoomFactor = 60 / currentFOV; 819 | } 820 | lastPosition = flightCamera.transform.position; 821 | lastRotation = flightCamera.transform.rotation; 822 | 823 | 824 | 825 | //vessel camera shake 826 | if(shakeMultiplier > 0) 827 | { 828 | foreach(var v in FlightGlobals.Vessels) 829 | { 830 | if(!v || !v.loaded || v.packed) continue; 831 | VesselCameraShake(v); 832 | } 833 | } 834 | UpdateCameraShake(); 835 | } 836 | 837 | 838 | void LateUpdate() 839 | { 840 | 841 | //retain pos and rot after vessel destruction 842 | if (cameraToolActive && flightCamera.transform.parent != cameraParent.transform) 843 | { 844 | flightCamera.SetTargetNone(); 845 | flightCamera.transform.parent = null; 846 | flightCamera.transform.position = lastPosition; 847 | flightCamera.transform.rotation = lastRotation; 848 | hasDied = true; 849 | diedTime = Time.time; 850 | } 851 | 852 | } 853 | 854 | void UpdateCameraShake() 855 | { 856 | if(shakeMultiplier > 0) 857 | { 858 | if(shakeMagnitude > 0.1f) 859 | { 860 | Vector3 shakeAxis = UnityEngine.Random.onUnitSphere; 861 | shakeOffset = Mathf.Sin(shakeMagnitude * 20 * Time.time) * (shakeMagnitude / 10) * shakeAxis; 862 | } 863 | 864 | 865 | flightCamera.transform.rotation = Quaternion.AngleAxis((shakeMultiplier/2) * shakeMagnitude / 50f, Vector3.ProjectOnPlane(UnityEngine.Random.onUnitSphere, flightCamera.transform.forward)) * flightCamera.transform.rotation; 866 | } 867 | 868 | shakeMagnitude = Mathf.Lerp(shakeMagnitude, 0, 5*Time.fixedDeltaTime); 869 | } 870 | 871 | public void VesselCameraShake(Vessel vessel) 872 | { 873 | //shake 874 | float camDistance = Vector3.Distance(flightCamera.transform.position, vessel.CoM); 875 | 876 | float distanceFactor = 50f / camDistance; 877 | float fovFactor = 2f / zoomFactor; 878 | float thrustFactor = GetTotalThrust() / 1000f; 879 | 880 | float atmosphericFactor = (float)vessel.dynamicPressurekPa / 2f; 881 | 882 | float angleToCam = Vector3.Angle(vessel.srf_velocity, FlightCamera.fetch.mainCamera.transform.position - vessel.transform.position); 883 | angleToCam = Mathf.Clamp(angleToCam, 1, 180); 884 | 885 | float srfSpeed = (float)vessel.srfSpeed; 886 | 887 | float lagAudioFactor = (75000 / (Vector3.Distance(vessel.transform.position, FlightCamera.fetch.mainCamera.transform.position) * srfSpeed * angleToCam / 90)); 888 | lagAudioFactor = Mathf.Clamp(lagAudioFactor * lagAudioFactor * lagAudioFactor, 0, 4); 889 | lagAudioFactor += srfSpeed / 230; 890 | 891 | float waveFrontFactor = ((3.67f * angleToCam) / srfSpeed); 892 | waveFrontFactor = Mathf.Clamp(waveFrontFactor * waveFrontFactor * waveFrontFactor, 0, 2); 893 | if(vessel.srfSpeed > 330) 894 | { 895 | waveFrontFactor = (srfSpeed / (angleToCam) < 3.67f) ? srfSpeed / 15 : 0; 896 | } 897 | 898 | lagAudioFactor *= waveFrontFactor; 899 | 900 | lagAudioFactor = Mathf.Clamp01(lagAudioFactor) * distanceFactor * fovFactor; 901 | 902 | atmosphericFactor *= lagAudioFactor; 903 | 904 | thrustFactor *= distanceFactor * fovFactor * lagAudioFactor; 905 | 906 | ShakeCamera(atmosphericFactor + thrustFactor); 907 | } 908 | 909 | float GetTotalThrust() 910 | { 911 | float total = 0; 912 | foreach(var engine in vessel.FindPartModulesImplementing()) 913 | { 914 | total += engine.finalThrust; 915 | } 916 | return total; 917 | } 918 | 919 | void AddAtmoAudioControllers(bool includeActiveVessel) 920 | { 921 | if(!useAudioEffects) 922 | { 923 | return; 924 | } 925 | 926 | foreach(var vessel in FlightGlobals.Vessels) 927 | { 928 | if(!vessel || !vessel.loaded || vessel.packed || (!includeActiveVessel && vessel.isActiveVessel)) 929 | { 930 | continue; 931 | } 932 | 933 | vessel.gameObject.AddComponent(); 934 | } 935 | } 936 | 937 | void SetDoppler(bool includeActiveVessel) 938 | { 939 | if(hasSetDoppler) 940 | { 941 | return; 942 | } 943 | 944 | if(!useAudioEffects) 945 | { 946 | return; 947 | } 948 | 949 | audioSources = FindObjectsOfType(); 950 | originalAudioSourceDoppler = new float[audioSources.Length]; 951 | 952 | for(int i = 0; i < audioSources.Length; i++) 953 | { 954 | originalAudioSourceDoppler[i] = audioSources[i].dopplerLevel; 955 | 956 | if(!includeActiveVessel) 957 | { 958 | Part p = audioSources[i].GetComponentInParent(); 959 | if(p && p.vessel.isActiveVessel) continue; 960 | } 961 | 962 | audioSources[i].dopplerLevel = 1; 963 | audioSources[i].velocityUpdateMode = AudioVelocityUpdateMode.Fixed; 964 | audioSources[i].bypassEffects = false; 965 | audioSources[i].spatialBlend = 1; 966 | 967 | if(audioSources[i].gameObject.GetComponentInParent()) 968 | { 969 | //Debug.Log("Added CTPartAudioController to :" + audioSources[i].name); 970 | CTPartAudioController pa = audioSources[i].gameObject.AddComponent(); 971 | pa.audioSource = audioSources[i]; 972 | } 973 | } 974 | 975 | hasSetDoppler = true; 976 | } 977 | 978 | void ResetDoppler() 979 | { 980 | if(!hasSetDoppler) 981 | { 982 | return; 983 | } 984 | 985 | for(int i = 0; i < audioSources.Length; i++) 986 | { 987 | if(audioSources[i] != null) 988 | { 989 | audioSources[i].dopplerLevel = originalAudioSourceDoppler[i]; 990 | audioSources[i].velocityUpdateMode = AudioVelocityUpdateMode.Auto; 991 | } 992 | } 993 | 994 | 995 | 996 | hasSetDoppler = false; 997 | } 998 | 999 | 1000 | void StartStationaryCamera() 1001 | { 1002 | Debug.Log ("flightCamera position init: "+flightCamera.transform.position); 1003 | if(FlightGlobals.ActiveVessel != null) 1004 | { 1005 | hasDied = false; 1006 | vessel = FlightGlobals.ActiveVessel; 1007 | cameraUp = -FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D()).normalized; 1008 | if(FlightCamera.fetch.mode == FlightCamera.Modes.ORBITAL || (FlightCamera.fetch.mode == FlightCamera.Modes.AUTO && FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL)) 1009 | { 1010 | cameraUp = Vector3.up; 1011 | } 1012 | 1013 | flightCamera.SetTargetNone(); 1014 | flightCamera.transform.parent = cameraParent.transform; 1015 | flightCamera.DeactivateUpdate(); 1016 | cameraParent.transform.position = vessel.transform.position+vessel.rb_velocity*Time.fixedDeltaTime; 1017 | manualPosition = Vector3.zero; 1018 | 1019 | 1020 | hasTarget = (camTarget != null) ? true : false; 1021 | 1022 | 1023 | Vector3 rightAxis = -Vector3.Cross(vessel.srf_velocity, vessel.upAxis).normalized; 1024 | //Vector3 upAxis = flightCamera.transform.up; 1025 | 1026 | 1027 | if(autoFlybyPosition) 1028 | { 1029 | setPresetOffset = false; 1030 | Vector3 velocity = vessel.srf_velocity; 1031 | if(referenceMode == ReferenceModes.Orbit) velocity = vessel.obt_velocity; 1032 | 1033 | Vector3 clampedVelocity = Mathf.Clamp((float) vessel.srfSpeed, 0, maxRelV) * velocity.normalized; 1034 | float clampedSpeed = clampedVelocity.magnitude; 1035 | float sideDistance = Mathf.Clamp(20 + (clampedSpeed/10), 20, 150); 1036 | float distanceAhead = Mathf.Clamp(4 * clampedSpeed, 30, 3500); 1037 | 1038 | flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp); 1039 | 1040 | 1041 | if(referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 0) 1042 | { 1043 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized); 1044 | } 1045 | else if(referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 0) 1046 | { 1047 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized); 1048 | } 1049 | else 1050 | { 1051 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up); 1052 | } 1053 | 1054 | 1055 | if(flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE) 1056 | { 1057 | flightCamera.transform.position += (sideDistance * rightAxis) + (15 * cameraUp); 1058 | } 1059 | else if(flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL) 1060 | { 1061 | flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (15 * Vector3.up); 1062 | } 1063 | 1064 | 1065 | } 1066 | else if(manualOffset) 1067 | { 1068 | setPresetOffset = false; 1069 | float sideDistance = manualOffsetRight; 1070 | float distanceAhead = manualOffsetForward; 1071 | 1072 | 1073 | flightCamera.transform.rotation = Quaternion.LookRotation(vessel.transform.position - flightCamera.transform.position, cameraUp); 1074 | 1075 | if(referenceMode == ReferenceModes.Surface && vessel.srfSpeed > 4) 1076 | { 1077 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.srf_velocity.normalized); 1078 | } 1079 | else if(referenceMode == ReferenceModes.Orbit && vessel.obt_speed > 4) 1080 | { 1081 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.obt_velocity.normalized); 1082 | } 1083 | else 1084 | { 1085 | flightCamera.transform.position = vessel.transform.position + (distanceAhead * vessel.vesselTransform.up); 1086 | } 1087 | 1088 | if(flightCamera.mode == FlightCamera.Modes.FREE || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.FREE) 1089 | { 1090 | flightCamera.transform.position += (sideDistance * rightAxis) + (manualOffsetUp * cameraUp); 1091 | } 1092 | else if(flightCamera.mode == FlightCamera.Modes.ORBITAL || FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL) 1093 | { 1094 | flightCamera.transform.position += (sideDistance * FlightGlobals.getUpAxis()) + (manualOffsetUp * Vector3.up); 1095 | } 1096 | } 1097 | else if(setPresetOffset) 1098 | { 1099 | flightCamera.transform.position = presetOffset; 1100 | //setPresetOffset = false; 1101 | } 1102 | 1103 | initialVelocity = vessel.srf_velocity; 1104 | initialOrbit = new Orbit(); 1105 | initialOrbit.UpdateFromStateVectors(vessel.orbit.pos, vessel.orbit.vel, FlightGlobals.currentMainBody, Planetarium.GetUniversalTime()); 1106 | initialUT = Planetarium.GetUniversalTime(); 1107 | 1108 | cameraToolActive = true; 1109 | 1110 | SetDoppler(true); 1111 | AddAtmoAudioControllers(true); 1112 | } 1113 | else 1114 | { 1115 | Debug.Log ("CameraTools: Stationary Camera failed. Active Vessel is null."); 1116 | } 1117 | resetPositionFix = flightCamera.transform.position; 1118 | Debug.Log ("flightCamera position post init: "+flightCamera.transform.position); 1119 | } 1120 | 1121 | void RevertCamera() 1122 | { 1123 | posCounter = 0; 1124 | 1125 | if(cameraToolActive) 1126 | { 1127 | presetOffset = flightCamera.transform.position; 1128 | if(camTarget==null) 1129 | { 1130 | savedRotation = flightCamera.transform.rotation; 1131 | hasSavedRotation = true; 1132 | } 1133 | else 1134 | { 1135 | hasSavedRotation = false; 1136 | } 1137 | } 1138 | hasDied = false; 1139 | if (FlightGlobals.ActiveVessel != null && HighLogic.LoadedScene == GameScenes.FLIGHT) 1140 | { 1141 | flightCamera.SetTarget(FlightGlobals.ActiveVessel.transform, FlightCamera.TargetMode.Vessel); 1142 | } 1143 | flightCamera.transform.parent = origParent; 1144 | flightCamera.transform.position = origPosition; 1145 | flightCamera.transform.rotation = origRotation; 1146 | Camera.main.nearClipPlane = origNearClip; 1147 | 1148 | flightCamera.SetFoV(60); 1149 | flightCamera.ActivateUpdate(); 1150 | currentFOV = 60; 1151 | 1152 | cameraToolActive = false; 1153 | 1154 | ResetDoppler(); 1155 | if(OnResetCTools != null) 1156 | { 1157 | OnResetCTools(); 1158 | } 1159 | 1160 | StopPlayingPath(); 1161 | } 1162 | 1163 | void SaveOriginalCamera() 1164 | { 1165 | origPosition = flightCamera.transform.position; 1166 | origRotation = flightCamera.transform.localRotation; 1167 | origParent = flightCamera.transform.parent; 1168 | origNearClip = Camera.main.nearClipPlane; 1169 | } 1170 | 1171 | Part GetPartFromMouse() 1172 | { 1173 | Vector3 mouseAim = new Vector3(Input.mousePosition.x/Screen.width, Input.mousePosition.y/Screen.height, 0); 1174 | Ray ray = FlightCamera.fetch.mainCamera.ViewportPointToRay(mouseAim); 1175 | RaycastHit hit; 1176 | if(Physics.Raycast(ray, out hit, 10000, 1<<0)) 1177 | { 1178 | Part p = hit.transform.GetComponentInParent(); 1179 | return p; 1180 | } 1181 | else return null; 1182 | } 1183 | 1184 | Vector3 GetPosFromMouse() 1185 | { 1186 | Vector3 mouseAim = new Vector3(Input.mousePosition.x/Screen.width, Input.mousePosition.y/Screen.height, 0); 1187 | Ray ray = FlightCamera.fetch.mainCamera.ViewportPointToRay(mouseAim); 1188 | RaycastHit hit; 1189 | if(Physics.Raycast(ray, out hit, 15000, 557057)) 1190 | { 1191 | return hit.point - (10 * ray.direction); 1192 | } 1193 | else return Vector3.zero; 1194 | } 1195 | 1196 | void PostDeathRevert() 1197 | { 1198 | if(cameraToolActive) 1199 | { 1200 | RevertCamera(); 1201 | } 1202 | } 1203 | 1204 | void PostDeathRevert(GameScenes f) 1205 | { 1206 | if(cameraToolActive) 1207 | { 1208 | RevertCamera(); 1209 | } 1210 | } 1211 | 1212 | void PostDeathRevert(Vessel v) 1213 | { 1214 | if(cameraToolActive) 1215 | { 1216 | RevertCamera(); 1217 | } 1218 | } 1219 | 1220 | //GUI 1221 | void OnGUI() 1222 | { 1223 | if(guiEnabled && gameUIToggle) 1224 | { 1225 | windowRect = GUI.Window(320, windowRect, GuiWindow, ""); 1226 | 1227 | if(showKeyframeEditor) 1228 | { 1229 | KeyframeEditorWindow(); 1230 | } 1231 | if(showPathSelectorWindow) 1232 | { 1233 | PathSelectorWindow(); 1234 | } 1235 | } 1236 | } 1237 | 1238 | void GuiWindow(int windowID) 1239 | { 1240 | GUI.DragWindow(new Rect(0,0,windowWidth, draggableHeight)); 1241 | 1242 | GUIStyle centerLabel = new GUIStyle(); 1243 | centerLabel.alignment = TextAnchor.UpperCenter; 1244 | centerLabel.normal.textColor = Color.white; 1245 | 1246 | GUIStyle leftLabel = new GUIStyle(); 1247 | leftLabel.alignment = TextAnchor.UpperLeft; 1248 | leftLabel.normal.textColor = Color.white; 1249 | 1250 | GUIStyle leftLabelBold = new GUIStyle(leftLabel); 1251 | leftLabelBold.fontStyle = FontStyle.Bold; 1252 | 1253 | 1254 | 1255 | float line = 1; 1256 | float contentWidth = (windowWidth) - (2*leftIndent); 1257 | float contentTop = 20; 1258 | GUIStyle titleStyle = new GUIStyle(centerLabel); 1259 | titleStyle.fontSize = 24; 1260 | titleStyle.alignment = TextAnchor.MiddleCenter; 1261 | GUI.Label(new Rect(0, contentTop, windowWidth, 40), "Camera Tools", titleStyle); 1262 | line++; 1263 | float parseResult; 1264 | 1265 | //tool mode switcher 1266 | GUI.Label(new Rect(leftIndent, contentTop+(line*entryHeight), contentWidth, entryHeight), "Tool: "+toolMode.ToString(), leftLabelBold); 1267 | line++; 1268 | if(!cameraToolActive) 1269 | { 1270 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), 25, entryHeight - 2), "<")) 1271 | { 1272 | CycleToolMode(false); 1273 | } 1274 | if(GUI.Button(new Rect(leftIndent + 25 + 4, contentTop + (line * entryHeight), 25, entryHeight - 2), ">")) 1275 | { 1276 | CycleToolMode(true); 1277 | } 1278 | } 1279 | line++; 1280 | line++; 1281 | if(autoFOV) 1282 | { 1283 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Autozoom Margin: "); 1284 | line++; 1285 | autoZoomMargin = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + ((line) * entryHeight), contentWidth - 45, entryHeight), autoZoomMargin, 0, 50); 1286 | GUI.Label(new Rect(leftIndent + contentWidth - 40, contentTop + ((line - 0.15f) * entryHeight), 40, entryHeight), autoZoomMargin.ToString("0.0"), leftLabel); 1287 | } 1288 | else 1289 | { 1290 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Zoom:", leftLabel); 1291 | line++; 1292 | zoomExp = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + ((line) * entryHeight), contentWidth - 45, entryHeight), zoomExp, 1, 8); 1293 | GUI.Label(new Rect(leftIndent + contentWidth - 40, contentTop + ((line - 0.15f) * entryHeight), 40, entryHeight), zoomFactor.ToString("0.0") + "x", leftLabel); 1294 | } 1295 | line++; 1296 | 1297 | if(toolMode != ToolModes.Pathing) 1298 | { 1299 | autoFOV = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), autoFOV, "Auto Zoom");//, leftLabel); 1300 | line++; 1301 | } 1302 | line++; 1303 | useAudioEffects = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), useAudioEffects, "Use Audio Effects"); 1304 | line++; 1305 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Camera shake:"); 1306 | line++; 1307 | shakeMultiplier = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth - 45, entryHeight), shakeMultiplier, 0f, 10f); 1308 | GUI.Label(new Rect(leftIndent + contentWidth - 40, contentTop + ((line - 0.25f) * entryHeight), 40, entryHeight), shakeMultiplier.ToString("0.00") + "x"); 1309 | line++; 1310 | line++; 1311 | 1312 | //Stationary camera GUI 1313 | if(toolMode == ToolModes.StationaryCamera) 1314 | { 1315 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Frame of Reference: " + referenceMode.ToString(), leftLabel); 1316 | line++; 1317 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), 25, entryHeight - 2), "<")) 1318 | { 1319 | CycleReferenceMode(false); 1320 | } 1321 | if(GUI.Button(new Rect(leftIndent + 25 + 4, contentTop + (line * entryHeight), 25, entryHeight - 2), ">")) 1322 | { 1323 | CycleReferenceMode(true); 1324 | } 1325 | 1326 | line++; 1327 | 1328 | if(referenceMode == ReferenceModes.Surface || referenceMode == ReferenceModes.Orbit) 1329 | { 1330 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Max Rel. V: ", leftLabel); 1331 | maxRelV = float.Parse(GUI.TextField(new Rect(leftIndent + contentWidth / 2, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), maxRelV.ToString())); 1332 | } 1333 | else if(referenceMode == ReferenceModes.InitialVelocity) 1334 | { 1335 | useOrbital = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), useOrbital, " Orbital"); 1336 | } 1337 | line++; 1338 | 1339 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Camera Position:", leftLabel); 1340 | line++; 1341 | string posButtonText = "Set Position w/ Click"; 1342 | if(setPresetOffset) posButtonText = "Clear Position"; 1343 | if(waitingForPosition) posButtonText = "Waiting..."; 1344 | if(FlightGlobals.ActiveVessel != null && GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight - 2), posButtonText)) 1345 | { 1346 | if(setPresetOffset) 1347 | { 1348 | setPresetOffset = false; 1349 | } 1350 | else 1351 | { 1352 | waitingForPosition = true; 1353 | mouseUp = false; 1354 | } 1355 | } 1356 | line++; 1357 | 1358 | 1359 | autoFlybyPosition = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), autoFlybyPosition, "Auto Flyby Position"); 1360 | if(autoFlybyPosition) manualOffset = false; 1361 | line++; 1362 | 1363 | manualOffset = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), manualOffset, "Manual Flyby Position"); 1364 | line++; 1365 | 1366 | Color origGuiColor = GUI.color; 1367 | if(manualOffset) 1368 | { 1369 | autoFlybyPosition = false; 1370 | } 1371 | else 1372 | { 1373 | GUI.color = new Color(0.5f, 0.5f, 0.5f, origGuiColor.a); 1374 | } 1375 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), 60, entryHeight), "Fwd:", leftLabel); 1376 | float textFieldWidth = 42; 1377 | Rect fwdFieldRect = new Rect(leftIndent + contentWidth - textFieldWidth - (3 * incrButtonWidth), contentTop + (line * entryHeight), textFieldWidth, entryHeight); 1378 | guiOffsetForward = GUI.TextField(fwdFieldRect, guiOffsetForward.ToString()); 1379 | if(float.TryParse(guiOffsetForward, out parseResult)) 1380 | { 1381 | manualOffsetForward = parseResult; 1382 | } 1383 | DrawIncrementButtons(fwdFieldRect, ref manualOffsetForward); 1384 | guiOffsetForward = manualOffsetForward.ToString(); 1385 | 1386 | line++; 1387 | Rect rightFieldRect = new Rect(fwdFieldRect.x, contentTop + (line * entryHeight), textFieldWidth, entryHeight); 1388 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), 60, entryHeight), "Right:", leftLabel); 1389 | guiOffsetRight = GUI.TextField(rightFieldRect, guiOffsetRight); 1390 | if(float.TryParse(guiOffsetRight, out parseResult)) 1391 | { 1392 | manualOffsetRight = parseResult; 1393 | } 1394 | DrawIncrementButtons(rightFieldRect, ref manualOffsetRight); 1395 | guiOffsetRight = manualOffsetRight.ToString(); 1396 | line++; 1397 | 1398 | Rect upFieldRect = new Rect(fwdFieldRect.x, contentTop + (line * entryHeight), textFieldWidth, entryHeight); 1399 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), 60, entryHeight), "Up:", leftLabel); 1400 | guiOffsetUp = GUI.TextField(upFieldRect, guiOffsetUp); 1401 | if(float.TryParse(guiOffsetUp, out parseResult)) 1402 | { 1403 | manualOffsetUp = parseResult; 1404 | } 1405 | DrawIncrementButtons(upFieldRect, ref manualOffsetUp); 1406 | guiOffsetUp = manualOffsetUp.ToString(); 1407 | GUI.color = origGuiColor; 1408 | 1409 | line++; 1410 | line++; 1411 | 1412 | string targetText = "None"; 1413 | if(camTarget != null) targetText = camTarget.gameObject.name; 1414 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Camera Target: " + targetText, leftLabel); 1415 | line++; 1416 | string tgtButtonText = "Set Target w/ Click"; 1417 | if(waitingForTarget) tgtButtonText = "waiting..."; 1418 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight - 2), tgtButtonText)) 1419 | { 1420 | waitingForTarget = true; 1421 | mouseUp = false; 1422 | } 1423 | line++; 1424 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), (contentWidth / 2) - 2, entryHeight - 2), "Target Self")) 1425 | { 1426 | camTarget = FlightGlobals.ActiveVessel.GetReferenceTransformPart(); 1427 | hasTarget = true; 1428 | } 1429 | if(GUI.Button(new Rect(2 + leftIndent + contentWidth / 2, contentTop + (line * entryHeight), (contentWidth / 2) - 2, entryHeight - 2), "Clear Target")) 1430 | { 1431 | camTarget = null; 1432 | hasTarget = false; 1433 | } 1434 | line++; 1435 | 1436 | targetCoM = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight - 2), targetCoM, "Vessel Center of Mass"); 1437 | } 1438 | else if(toolMode == ToolModes.DogfightCamera) 1439 | { 1440 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Secondary target:"); 1441 | line++; 1442 | string tVesselLabel; 1443 | if(showingVesselList) 1444 | { 1445 | tVesselLabel = "Clear"; 1446 | } 1447 | else if(dogfightTarget) 1448 | { 1449 | tVesselLabel = dogfightTarget.vesselName; 1450 | } 1451 | else 1452 | { 1453 | tVesselLabel = "None"; 1454 | } 1455 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), tVesselLabel)) 1456 | { 1457 | if(showingVesselList) 1458 | { 1459 | showingVesselList = false; 1460 | dogfightTarget = null; 1461 | } 1462 | else 1463 | { 1464 | UpdateLoadedVessels(); 1465 | showingVesselList = true; 1466 | } 1467 | } 1468 | line++; 1469 | 1470 | if(showingVesselList) 1471 | { 1472 | foreach(var v in loadedVessels) 1473 | { 1474 | if(!v || !v.loaded) continue; 1475 | if(GUI.Button(new Rect(leftIndent + 10, contentTop + (line * entryHeight), contentWidth - 10, entryHeight), v.vesselName)) 1476 | { 1477 | dogfightTarget = v; 1478 | showingVesselList = false; 1479 | } 1480 | line++; 1481 | } 1482 | } 1483 | line++; 1484 | 1485 | if(hasBDAI) 1486 | { 1487 | useBDAutoTarget = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight - 2), useBDAutoTarget, "BDA AI Auto target"); 1488 | line++; 1489 | } 1490 | 1491 | line++; 1492 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Distance: " + dogfightDistance.ToString("0.0")); 1493 | line++; 1494 | dogfightDistance = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), dogfightDistance, 1, 100); 1495 | line += 1.5f; 1496 | 1497 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Offset:"); 1498 | line++; 1499 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), 15, entryHeight), "X: "); 1500 | dogfightOffsetX = GUI.HorizontalSlider(new Rect(leftIndent + 15, contentTop + (line * entryHeight) + 6, contentWidth - 45, entryHeight), dogfightOffsetX, -dogfightMaxOffset, dogfightMaxOffset); 1501 | GUI.Label(new Rect(leftIndent + contentWidth - 25, contentTop + (line * entryHeight), 25, entryHeight), dogfightOffsetX.ToString("0.0")); 1502 | line++; 1503 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), 15, entryHeight), "Y: "); 1504 | dogfightOffsetY = GUI.HorizontalSlider(new Rect(leftIndent + 15, contentTop + (line * entryHeight) + 6, contentWidth - 45, entryHeight), dogfightOffsetY, -dogfightMaxOffset, dogfightMaxOffset); 1505 | GUI.Label(new Rect(leftIndent + contentWidth - 25, contentTop + (line * entryHeight), 25, entryHeight), dogfightOffsetY.ToString("0.0")); 1506 | line += 1.5f; 1507 | } 1508 | else if(toolMode == ToolModes.Pathing) 1509 | { 1510 | if(selectedPathIndex >= 0) 1511 | { 1512 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Path:"); 1513 | currentPath.pathName = GUI.TextField(new Rect(leftIndent + 34, contentTop + (line * entryHeight), contentWidth-34, entryHeight), currentPath.pathName); 1514 | } 1515 | else 1516 | { 1517 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Path: None"); 1518 | } 1519 | line += 1.25f; 1520 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Open Path")) 1521 | { 1522 | TogglePathList(); 1523 | } 1524 | line++; 1525 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth/2, entryHeight), "New Path")) 1526 | { 1527 | CreateNewPath(); 1528 | } 1529 | if(GUI.Button(new Rect(leftIndent + (contentWidth/2), contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Delete Path")) 1530 | { 1531 | DeletePath(selectedPathIndex); 1532 | } 1533 | line ++; 1534 | if(selectedPathIndex >= 0) 1535 | { 1536 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Interpolation rate: " + currentPath.lerpRate.ToString("0.0")); 1537 | line++; 1538 | currentPath.lerpRate = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + (line * entryHeight) + 4, contentWidth - 50, entryHeight), currentPath.lerpRate, 1f, 15f); 1539 | currentPath.lerpRate = Mathf.Round(currentPath.lerpRate * 10) / 10; 1540 | line++; 1541 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Path timescale " + currentPath.timeScale.ToString("0.00")); 1542 | line++; 1543 | currentPath.timeScale = GUI.HorizontalSlider(new Rect(leftIndent, contentTop + (line * entryHeight) + 4, contentWidth - 50, entryHeight), currentPath.timeScale, 0.05f, 4f); 1544 | currentPath.timeScale = Mathf.Round(currentPath.timeScale * 20) / 20; 1545 | line++; 1546 | float viewHeight = Mathf.Max(6 * entryHeight, currentPath.keyframeCount * entryHeight); 1547 | Rect scrollRect = new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, 6 * entryHeight); 1548 | GUI.Box(scrollRect, string.Empty); 1549 | float viewContentWidth = contentWidth - (2 * leftIndent); 1550 | keysScrollPos = GUI.BeginScrollView(scrollRect, keysScrollPos, new Rect(0, 0, viewContentWidth, viewHeight)); 1551 | if(currentPath.keyframeCount > 0) 1552 | { 1553 | Color origGuiColor = GUI.color; 1554 | for(int i = 0; i < currentPath.keyframeCount; i++) 1555 | { 1556 | if(i == currentKeyframeIndex) 1557 | { 1558 | GUI.color = Color.green; 1559 | } 1560 | else 1561 | { 1562 | GUI.color = origGuiColor; 1563 | } 1564 | string kLabel = "#" + i.ToString() + ": " + currentPath.GetKeyframe(i).time.ToString("0.00") + "s"; 1565 | if(GUI.Button(new Rect(0, (i * entryHeight), 3 * viewContentWidth / 4, entryHeight), kLabel)) 1566 | { 1567 | SelectKeyframe(i); 1568 | } 1569 | if(GUI.Button(new Rect((3 * contentWidth / 4), (i * entryHeight), (viewContentWidth / 4) - 20, entryHeight), "X")) 1570 | { 1571 | DeleteKeyframe(i); 1572 | break; 1573 | } 1574 | //line++; 1575 | } 1576 | GUI.color = origGuiColor; 1577 | } 1578 | GUI.EndScrollView(); 1579 | line += 6; 1580 | line += 0.5f; 1581 | if(GUI.Button(new Rect(leftIndent, contentTop + (line * entryHeight), 3 * contentWidth / 4, entryHeight), "New Key")) 1582 | { 1583 | CreateNewKeyframe(); 1584 | } 1585 | } 1586 | } 1587 | 1588 | line += 1.25f; 1589 | 1590 | enableKeypad = GUI.Toggle(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), enableKeypad, "Keypad Control"); 1591 | if(enableKeypad) 1592 | { 1593 | line++; 1594 | 1595 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Move Speed:"); 1596 | guiFreeMoveSpeed = GUI.TextField(new Rect(leftIndent + contentWidth / 2, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), guiFreeMoveSpeed); 1597 | if(float.TryParse(guiFreeMoveSpeed, out parseResult)) 1598 | { 1599 | freeMoveSpeed = Mathf.Abs(parseResult); 1600 | guiFreeMoveSpeed = freeMoveSpeed.ToString(); 1601 | } 1602 | 1603 | line++; 1604 | 1605 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), "Zoom Speed:"); 1606 | guiKeyZoomSpeed = GUI.TextField(new Rect(leftIndent + contentWidth / 2, contentTop + (line * entryHeight), contentWidth / 2, entryHeight), guiKeyZoomSpeed); 1607 | if(float.TryParse(guiKeyZoomSpeed, out parseResult)) 1608 | { 1609 | keyZoomSpeed = Mathf.Abs(parseResult); 1610 | guiKeyZoomSpeed = keyZoomSpeed.ToString(); 1611 | } 1612 | } 1613 | else 1614 | { 1615 | line++; 1616 | line++; 1617 | } 1618 | 1619 | line++; 1620 | line++; 1621 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Keys:", centerLabel); 1622 | line++; 1623 | 1624 | //activate key binding 1625 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Activate: ", leftLabel); 1626 | GUI.Label(new Rect(leftIndent + 60, contentTop + (line * entryHeight), 60, entryHeight), cameraKey, leftLabel); 1627 | if(!isRecordingInput) 1628 | { 1629 | if(GUI.Button(new Rect(leftIndent + 125, contentTop + (line * entryHeight), 100, entryHeight), "Bind Key")) 1630 | { 1631 | mouseUp = false; 1632 | isRecordingInput = true; 1633 | isRecordingActivate = true; 1634 | } 1635 | } 1636 | else if(mouseUp && isRecordingActivate) 1637 | { 1638 | GUI.Label(new Rect(leftIndent + 125, contentTop + (line * entryHeight), 100, entryHeight), "Press a Key", leftLabel); 1639 | 1640 | string inputString = CCInputUtils.GetInputString(); 1641 | if(inputString.Length > 0) 1642 | { 1643 | cameraKey = inputString; 1644 | isRecordingInput = false; 1645 | isRecordingActivate = false; 1646 | } 1647 | } 1648 | 1649 | line++; 1650 | 1651 | //revert key binding 1652 | GUI.Label(new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth, entryHeight), "Revert: ", leftLabel); 1653 | GUI.Label(new Rect(leftIndent + 60, contentTop + (line * entryHeight), 60, entryHeight), revertKey); 1654 | if(!isRecordingInput) 1655 | { 1656 | if(GUI.Button(new Rect(leftIndent + 125, contentTop + (line * entryHeight), 100, entryHeight), "Bind Key")) 1657 | { 1658 | mouseUp = false; 1659 | isRecordingInput = true; 1660 | isRecordingRevert = true; 1661 | } 1662 | } 1663 | else if(mouseUp && isRecordingRevert) 1664 | { 1665 | GUI.Label(new Rect(leftIndent + 125, contentTop + (line * entryHeight), 100, entryHeight), "Press a Key", leftLabel); 1666 | string inputString = CCInputUtils.GetInputString(); 1667 | if(inputString.Length > 0) 1668 | { 1669 | revertKey = inputString; 1670 | isRecordingInput = false; 1671 | isRecordingRevert = false; 1672 | } 1673 | } 1674 | 1675 | line++; 1676 | line++; 1677 | Rect saveRect = new Rect(leftIndent, contentTop + (line * entryHeight), contentWidth / 2, entryHeight); 1678 | if(GUI.Button(saveRect, "Save")) 1679 | { 1680 | Save(); 1681 | } 1682 | 1683 | Rect loadRect = new Rect(saveRect); 1684 | loadRect.x += contentWidth / 2; 1685 | if(GUI.Button(loadRect, "Reload")) 1686 | { 1687 | Load(); 1688 | } 1689 | 1690 | //fix length 1691 | windowHeight = contentTop+(line*entryHeight)+entryHeight+entryHeight; 1692 | windowRect.height = windowHeight;// = new Rect(windowRect.x, windowRect.y, windowWidth, windowHeight); 1693 | } 1694 | 1695 | public static string pathSaveURL = "GameData/CameraTools/paths.cfg"; 1696 | void Save() 1697 | { 1698 | CTPersistantField.Save(); 1699 | 1700 | ConfigNode pathFileNode = ConfigNode.Load(pathSaveURL); 1701 | ConfigNode pathsNode = pathFileNode.GetNode("CAMERAPATHS"); 1702 | pathsNode.RemoveNodes("CAMERAPATH"); 1703 | 1704 | foreach(var path in availablePaths) 1705 | { 1706 | path.Save(pathsNode); 1707 | } 1708 | pathFileNode.Save(pathSaveURL); 1709 | } 1710 | 1711 | void Load() 1712 | { 1713 | CTPersistantField.Load(); 1714 | guiOffsetForward = manualOffsetForward.ToString(); 1715 | guiOffsetRight = manualOffsetRight.ToString(); 1716 | guiOffsetUp = manualOffsetUp.ToString(); 1717 | guiKeyZoomSpeed = keyZoomSpeed.ToString(); 1718 | guiFreeMoveSpeed = freeMoveSpeed.ToString(); 1719 | 1720 | DeselectKeyframe(); 1721 | selectedPathIndex = -1; 1722 | availablePaths = new List(); 1723 | ConfigNode pathFileNode = ConfigNode.Load(pathSaveURL); 1724 | foreach(var node in pathFileNode.GetNode("CAMERAPATHS").GetNodes("CAMERAPATH")) 1725 | { 1726 | availablePaths.Add(CameraPath.Load(node)); 1727 | } 1728 | } 1729 | 1730 | void KeyframeEditorWindow() 1731 | { 1732 | float width = 300; 1733 | float height = 130; 1734 | Rect kWindowRect = new Rect(windowRect.x - width, windowRect.y + 365, width, height); 1735 | GUI.Box(kWindowRect, string.Empty); 1736 | GUI.BeginGroup(kWindowRect); 1737 | GUI.Label(new Rect(5, 5, 100, 25), "Keyframe #"+currentKeyframeIndex); 1738 | if(GUI.Button(new Rect(105, 5, 180, 25), "Revert Pos")) 1739 | { 1740 | ViewKeyframe(currentKeyframeIndex); 1741 | } 1742 | GUI.Label(new Rect(5, 35, 80, 25), "Time: "); 1743 | currKeyTimeString = GUI.TextField(new Rect(100, 35, 195, 25), currKeyTimeString, 16); 1744 | float parsed; 1745 | if(float.TryParse(currKeyTimeString, out parsed)) 1746 | { 1747 | currentKeyframeTime = parsed; 1748 | } 1749 | bool applied = false; 1750 | if(GUI.Button(new Rect(100, 65, 195, 25), "Apply")) 1751 | { 1752 | Debug.Log("Applying keyframe at time: " + currentKeyframeTime); 1753 | currentPath.SetTransform(currentKeyframeIndex, flightCamera.transform, zoomExp, currentKeyframeTime); 1754 | applied = true; 1755 | } 1756 | if(GUI.Button(new Rect(100, 105, 195, 20), "Cancel")) 1757 | { 1758 | applied = true; 1759 | } 1760 | GUI.EndGroup(); 1761 | 1762 | if(applied) 1763 | { 1764 | DeselectKeyframe(); 1765 | } 1766 | } 1767 | 1768 | bool showPathSelectorWindow = false; 1769 | Vector2 pathSelectScrollPos; 1770 | void PathSelectorWindow() 1771 | { 1772 | float width = 300; 1773 | float height = 300; 1774 | float indent = 5; 1775 | float scrollRectSize = width - indent - indent; 1776 | Rect pSelectRect = new Rect(windowRect.x - width, windowRect.y + 290, width, height); 1777 | GUI.Box(pSelectRect, string.Empty); 1778 | GUI.BeginGroup(pSelectRect); 1779 | 1780 | Rect scrollRect = new Rect(indent, indent, scrollRectSize, scrollRectSize); 1781 | float scrollHeight = Mathf.Max(scrollRectSize, entryHeight * availablePaths.Count); 1782 | Rect scrollViewRect = new Rect(0, 0, scrollRectSize-20, scrollHeight); 1783 | pathSelectScrollPos = GUI.BeginScrollView(scrollRect, pathSelectScrollPos, scrollViewRect); 1784 | bool selected = false; 1785 | for(int i = 0; i < availablePaths.Count; i++) 1786 | { 1787 | if(GUI.Button(new Rect(0, i * entryHeight, scrollRectSize - 90, entryHeight), availablePaths[i].pathName)) 1788 | { 1789 | SelectPath(i); 1790 | selected = true; 1791 | } 1792 | if(GUI.Button(new Rect(scrollRectSize-80, i * entryHeight, 60, entryHeight), "Delete")) 1793 | { 1794 | DeletePath(i); 1795 | break; 1796 | } 1797 | } 1798 | 1799 | GUI.EndScrollView(); 1800 | 1801 | GUI.EndGroup(); 1802 | if(selected) 1803 | { 1804 | showPathSelectorWindow = false; 1805 | } 1806 | } 1807 | 1808 | void DrawIncrementButtons(Rect fieldRect, ref float val) 1809 | { 1810 | Rect incrButtonRect = new Rect(fieldRect.x-incrButtonWidth, fieldRect.y, incrButtonWidth, entryHeight); 1811 | if(GUI.Button(incrButtonRect, "-")) 1812 | { 1813 | val -= 5; 1814 | } 1815 | 1816 | incrButtonRect.x -= incrButtonWidth; 1817 | 1818 | if(GUI.Button(incrButtonRect, "--")) 1819 | { 1820 | val -= 50; 1821 | } 1822 | 1823 | incrButtonRect.x = fieldRect.x + fieldRect.width; 1824 | 1825 | if(GUI.Button(incrButtonRect, "+")) 1826 | { 1827 | val += 5; 1828 | } 1829 | 1830 | incrButtonRect.x += incrButtonWidth; 1831 | 1832 | if(GUI.Button(incrButtonRect, "++")) 1833 | { 1834 | val += 50; 1835 | } 1836 | } 1837 | 1838 | //AppLauncherSetup 1839 | void AddToolbarButton() 1840 | { 1841 | if(!hasAddedButton) 1842 | { 1843 | Texture buttonTexture = GameDatabase.Instance.GetTexture("CameraTools/Textures/icon", false); 1844 | ApplicationLauncher.Instance.AddModApplication(EnableGui, DisableGui, Dummy, Dummy, Dummy, Dummy, ApplicationLauncher.AppScenes.FLIGHT, buttonTexture); 1845 | CamTools.hasAddedButton = true; 1846 | } 1847 | 1848 | } 1849 | 1850 | void EnableGui() 1851 | { 1852 | guiEnabled = true; 1853 | Debug.Log ("Showing CamTools GUI"); 1854 | } 1855 | 1856 | void DisableGui() 1857 | { 1858 | guiEnabled = false; 1859 | Debug.Log ("Hiding CamTools GUI"); 1860 | } 1861 | 1862 | void Dummy() 1863 | {} 1864 | 1865 | void GameUIEnable() 1866 | { 1867 | gameUIToggle = true; 1868 | } 1869 | 1870 | void GameUIDisable() 1871 | { 1872 | gameUIToggle = false; 1873 | } 1874 | 1875 | void CycleReferenceMode(bool forward) 1876 | { 1877 | var length = System.Enum.GetValues(typeof(ReferenceModes)).Length; 1878 | if(forward) 1879 | { 1880 | referenceMode++; 1881 | if((int)referenceMode == length) referenceMode = 0; 1882 | } 1883 | else 1884 | { 1885 | referenceMode--; 1886 | if((int)referenceMode == -1) referenceMode = (ReferenceModes) length-1; 1887 | } 1888 | } 1889 | 1890 | void CycleToolMode(bool forward) 1891 | { 1892 | var length = System.Enum.GetValues(typeof(ToolModes)).Length; 1893 | if(forward) 1894 | { 1895 | toolMode++; 1896 | if((int)toolMode == length) toolMode = 0; 1897 | } 1898 | else 1899 | { 1900 | toolMode--; 1901 | if((int)toolMode == -1) toolMode = (ToolModes) length-1; 1902 | } 1903 | } 1904 | 1905 | void OnFloatingOriginShift(Vector3d offset, Vector3d data1) 1906 | { 1907 | /* 1908 | Debug.LogWarning ("======Floating origin shifted.======"); 1909 | Debug.LogWarning ("======Passed offset: "+offset+"======"); 1910 | Debug.LogWarning ("======FloatingOrigin offset: "+FloatingOrigin.fetch.offset+"======"); 1911 | Debug.LogWarning("========Floating Origin threshold: "+FloatingOrigin.fetch.threshold+"=========="); 1912 | */ 1913 | } 1914 | 1915 | void UpdateLoadedVessels() 1916 | { 1917 | if(loadedVessels == null) 1918 | { 1919 | loadedVessels = new List(); 1920 | } 1921 | else 1922 | { 1923 | loadedVessels.Clear(); 1924 | } 1925 | 1926 | foreach(var v in FlightGlobals.Vessels) 1927 | { 1928 | if(v.loaded && v.vesselType != VesselType.Debris && !v.isActiveVessel) 1929 | { 1930 | loadedVessels.Add(v); 1931 | } 1932 | } 1933 | } 1934 | 1935 | private void CheckForBDAI(Vessel v) 1936 | { 1937 | hasBDAI = false; 1938 | aiComponent = null; 1939 | if(v) 1940 | { 1941 | foreach(Part p in v.parts) 1942 | { 1943 | if(p.GetComponent("BDModulePilotAI")) 1944 | { 1945 | hasBDAI = true; 1946 | aiComponent = (object)p.GetComponent("BDModulePilotAI"); 1947 | return; 1948 | } 1949 | } 1950 | } 1951 | } 1952 | 1953 | private Vessel GetAITargetedVessel() 1954 | { 1955 | if(!hasBDAI || aiComponent==null || bdAiTargetField==null) 1956 | { 1957 | return null; 1958 | } 1959 | 1960 | return (Vessel) bdAiTargetField.GetValue(aiComponent); 1961 | } 1962 | 1963 | private Type AIModuleType() 1964 | { 1965 | //Debug.Log("loaded assy's: "); 1966 | foreach(var assy in AssemblyLoader.loadedAssemblies) 1967 | { 1968 | //Debug.Log("- "+assy.assembly.FullName); 1969 | if(assy.assembly.FullName.Contains("BDArmory")) 1970 | { 1971 | foreach(var t in assy.assembly.GetTypes()) 1972 | { 1973 | if(t.Name == "BDModulePilotAI") 1974 | { 1975 | return t; 1976 | } 1977 | } 1978 | } 1979 | } 1980 | 1981 | return null; 1982 | } 1983 | 1984 | private FieldInfo GetAITargetField() 1985 | { 1986 | Type aiModType = AIModuleType(); 1987 | if(aiModType == null) return null; 1988 | 1989 | FieldInfo[] fields = aiModType.GetFields(BindingFlags.NonPublic|BindingFlags.Instance); 1990 | //Debug.Log("bdai fields: "); 1991 | foreach(var f in fields) 1992 | { 1993 | //Debug.Log("- " + f.Name); 1994 | if(f.Name == "targetVessel") 1995 | { 1996 | return f; 1997 | } 1998 | } 1999 | 2000 | return null; 2001 | } 2002 | 2003 | 2004 | void SwitchToVessel(Vessel v) 2005 | { 2006 | vessel = v; 2007 | 2008 | CheckForBDAI(v); 2009 | 2010 | if(cameraToolActive) 2011 | { 2012 | if(toolMode == ToolModes.DogfightCamera) 2013 | { 2014 | StartCoroutine(ResetDogfightCamRoutine()); 2015 | } 2016 | } 2017 | } 2018 | 2019 | IEnumerator ResetDogfightCamRoutine() 2020 | { 2021 | yield return new WaitForEndOfFrame(); 2022 | RevertCamera(); 2023 | StartDogfightCamera(); 2024 | } 2025 | 2026 | void CreateNewPath() 2027 | { 2028 | showKeyframeEditor = false; 2029 | availablePaths.Add(new CameraPath()); 2030 | selectedPathIndex = availablePaths.Count - 1; 2031 | } 2032 | 2033 | void DeletePath(int index) 2034 | { 2035 | if(index < 0) return; 2036 | if(index >= availablePaths.Count) return; 2037 | availablePaths.RemoveAt(index); 2038 | selectedPathIndex = -1; 2039 | } 2040 | 2041 | void SelectPath(int index) 2042 | { 2043 | selectedPathIndex = index; 2044 | } 2045 | 2046 | void SelectKeyframe(int index) 2047 | { 2048 | if(isPlayingPath) 2049 | { 2050 | StopPlayingPath(); 2051 | } 2052 | currentKeyframeIndex = index; 2053 | UpdateCurrentValues(); 2054 | showKeyframeEditor = true; 2055 | ViewKeyframe(currentKeyframeIndex); 2056 | } 2057 | 2058 | void DeselectKeyframe() 2059 | { 2060 | currentKeyframeIndex = -1; 2061 | showKeyframeEditor = false; 2062 | } 2063 | 2064 | void DeleteKeyframe(int index) 2065 | { 2066 | currentPath.RemoveKeyframe(index); 2067 | if(index == currentKeyframeIndex) 2068 | { 2069 | DeselectKeyframe(); 2070 | } 2071 | if(currentPath.keyframeCount > 0 && currentKeyframeIndex >= 0) 2072 | { 2073 | SelectKeyframe(Mathf.Clamp(currentKeyframeIndex, 0, currentPath.keyframeCount - 1)); 2074 | } 2075 | } 2076 | 2077 | void UpdateCurrentValues() 2078 | { 2079 | if(currentPath == null) return; 2080 | if(currentKeyframeIndex < 0 || currentKeyframeIndex >= currentPath.keyframeCount) 2081 | { 2082 | return; 2083 | } 2084 | CameraKeyframe currentKey = currentPath.GetKeyframe(currentKeyframeIndex); 2085 | currentKeyframeTime = currentKey.time; 2086 | 2087 | currKeyTimeString = currentKeyframeTime.ToString(); 2088 | } 2089 | 2090 | void CreateNewKeyframe() 2091 | { 2092 | if(!cameraToolActive) 2093 | { 2094 | StartPathingCam(); 2095 | } 2096 | 2097 | showPathSelectorWindow = false; 2098 | 2099 | float time = currentPath.keyframeCount > 0 ? currentPath.GetKeyframe(currentPath.keyframeCount - 1).time + 1 : 0; 2100 | currentPath.AddTransform(flightCamera.transform, zoomExp, time); 2101 | SelectKeyframe(currentPath.keyframeCount - 1); 2102 | 2103 | if(currentPath.keyframeCount > 6) 2104 | { 2105 | keysScrollPos.y += entryHeight; 2106 | } 2107 | } 2108 | 2109 | void ViewKeyframe(int index) 2110 | { 2111 | if(!cameraToolActive) 2112 | { 2113 | StartPathingCam(); 2114 | } 2115 | CameraKeyframe currentKey = currentPath.GetKeyframe(index); 2116 | flightCamera.transform.localPosition = currentKey.position; 2117 | flightCamera.transform.localRotation = currentKey.rotation; 2118 | zoomExp = currentKey.zoom; 2119 | } 2120 | 2121 | void StartPathingCam() 2122 | { 2123 | vessel = FlightGlobals.ActiveVessel; 2124 | cameraUp = -FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D()).normalized; 2125 | if(FlightCamera.fetch.mode == FlightCamera.Modes.ORBITAL || (FlightCamera.fetch.mode == FlightCamera.Modes.AUTO && FlightCamera.GetAutoModeForVessel(vessel) == FlightCamera.Modes.ORBITAL)) 2126 | { 2127 | cameraUp = Vector3.up; 2128 | } 2129 | 2130 | cameraParent.transform.position = vessel.transform.position+vessel.rb_velocity*Time.fixedDeltaTime; 2131 | cameraParent.transform.rotation = vessel.transform.rotation; 2132 | flightCamera.SetTargetNone(); 2133 | flightCamera.transform.parent = cameraParent.transform; 2134 | flightCamera.DeactivateUpdate(); 2135 | 2136 | cameraToolActive = true; 2137 | } 2138 | 2139 | void PlayPathingCam() 2140 | { 2141 | if(selectedPathIndex < 0) 2142 | { 2143 | RevertCamera(); 2144 | return; 2145 | } 2146 | 2147 | if(currentPath.keyframeCount <= 0) 2148 | { 2149 | RevertCamera(); 2150 | return; 2151 | } 2152 | 2153 | DeselectKeyframe(); 2154 | 2155 | if(!cameraToolActive) 2156 | { 2157 | StartPathingCam(); 2158 | } 2159 | 2160 | CameraTransformation firstFrame = currentPath.Evaulate(0); 2161 | flightCamera.transform.localPosition = firstFrame.position; 2162 | flightCamera.transform.localRotation = firstFrame.rotation; 2163 | zoomExp = firstFrame.zoom; 2164 | 2165 | isPlayingPath = true; 2166 | pathStartTime = Time.time; 2167 | } 2168 | 2169 | void StopPlayingPath() 2170 | { 2171 | isPlayingPath = false; 2172 | } 2173 | 2174 | void TogglePathList() 2175 | { 2176 | showKeyframeEditor = false; 2177 | showPathSelectorWindow = !showPathSelectorWindow; 2178 | } 2179 | 2180 | void UpdatePathingCam() 2181 | { 2182 | cameraParent.transform.position = vessel.transform.position+vessel.rb_velocity*Time.fixedDeltaTime; 2183 | cameraParent.transform.rotation = vessel.transform.rotation; 2184 | 2185 | if(isPlayingPath) 2186 | { 2187 | CameraTransformation tf = currentPath.Evaulate(pathTime * currentPath.timeScale); 2188 | flightCamera.transform.localPosition = Vector3.Lerp(flightCamera.transform.localPosition, tf.position, currentPath.lerpRate*Time.fixedDeltaTime); 2189 | flightCamera.transform.localRotation = Quaternion.Slerp(flightCamera.transform.localRotation, tf.rotation, currentPath.lerpRate*Time.fixedDeltaTime); 2190 | zoomExp = Mathf.Lerp(zoomExp, tf.zoom, currentPath.lerpRate*Time.fixedDeltaTime); 2191 | } 2192 | else 2193 | { 2194 | //move 2195 | //mouse panning, moving 2196 | Vector3 forwardLevelAxis = flightCamera.transform.forward;//(Quaternion.AngleAxis(-90, cameraUp) * flightCamera.transform.right).normalized; 2197 | Vector3 rightAxis = flightCamera.transform.right;//(Quaternion.AngleAxis(90, forwardLevelAxis) * cameraUp).normalized; 2198 | if(enableKeypad) 2199 | { 2200 | if(Input.GetKey(fmUpKey)) 2201 | { 2202 | flightCamera.transform.position += cameraUp * freeMoveSpeed * Time.fixedDeltaTime; 2203 | } 2204 | else if(Input.GetKey(fmDownKey)) 2205 | { 2206 | flightCamera.transform.position -= cameraUp * freeMoveSpeed * Time.fixedDeltaTime; 2207 | } 2208 | if(Input.GetKey(fmForwardKey)) 2209 | { 2210 | flightCamera.transform.position += forwardLevelAxis * freeMoveSpeed * Time.fixedDeltaTime; 2211 | } 2212 | else if(Input.GetKey(fmBackKey)) 2213 | { 2214 | flightCamera.transform.position -= forwardLevelAxis * freeMoveSpeed * Time.fixedDeltaTime; 2215 | } 2216 | if(Input.GetKey(fmLeftKey)) 2217 | { 2218 | flightCamera.transform.position -= flightCamera.transform.right * freeMoveSpeed * Time.fixedDeltaTime; 2219 | } 2220 | else if(Input.GetKey(fmRightKey)) 2221 | { 2222 | flightCamera.transform.position += flightCamera.transform.right * freeMoveSpeed * Time.fixedDeltaTime; 2223 | } 2224 | 2225 | //keyZoom 2226 | if(!autoFOV) 2227 | { 2228 | if(Input.GetKey(fmZoomInKey)) 2229 | { 2230 | zoomExp = Mathf.Clamp(zoomExp + (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 2231 | } 2232 | else if(Input.GetKey(fmZoomOutKey)) 2233 | { 2234 | zoomExp = Mathf.Clamp(zoomExp - (keyZoomSpeed * Time.fixedDeltaTime), 1, 8); 2235 | } 2236 | } 2237 | else 2238 | { 2239 | if(Input.GetKey(fmZoomInKey)) 2240 | { 2241 | autoZoomMargin = Mathf.Clamp(autoZoomMargin + (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 2242 | } 2243 | else if(Input.GetKey(fmZoomOutKey)) 2244 | { 2245 | autoZoomMargin = Mathf.Clamp(autoZoomMargin - (keyZoomSpeed * 10 * Time.fixedDeltaTime), 0, 50); 2246 | } 2247 | } 2248 | } 2249 | 2250 | if(Input.GetKey(KeyCode.Mouse1) && Input.GetKey(KeyCode.Mouse2)) 2251 | { 2252 | flightCamera.transform.rotation = Quaternion.AngleAxis(Input.GetAxis("Mouse X") * -1.7f, flightCamera.transform.forward) * flightCamera.transform.rotation; 2253 | } 2254 | else 2255 | { 2256 | if(Input.GetKey(KeyCode.Mouse1)) 2257 | { 2258 | flightCamera.transform.rotation *= Quaternion.AngleAxis(Input.GetAxis("Mouse X") * 1.7f/(zoomExp*zoomExp), Vector3.up); //*(Mathf.Abs(Mouse.delta.x)/7) 2259 | flightCamera.transform.rotation *= Quaternion.AngleAxis(-Input.GetAxis("Mouse Y") * 1.7f/(zoomExp*zoomExp), Vector3.right); 2260 | flightCamera.transform.rotation = Quaternion.LookRotation(flightCamera.transform.forward, flightCamera.transform.up); 2261 | } 2262 | if(Input.GetKey(KeyCode.Mouse2)) 2263 | { 2264 | flightCamera.transform.position += flightCamera.transform.right * Input.GetAxis("Mouse X") * 2; 2265 | flightCamera.transform.position += forwardLevelAxis * Input.GetAxis("Mouse Y") * 2; 2266 | } 2267 | } 2268 | flightCamera.transform.position += flightCamera.transform.up * 10 * Input.GetAxis("Mouse ScrollWheel"); 2269 | 2270 | } 2271 | 2272 | //zoom 2273 | zoomFactor = Mathf.Exp(zoomExp) / Mathf.Exp(1); 2274 | manualFOV = 60 / zoomFactor; 2275 | updateFOV = (currentFOV != manualFOV); 2276 | if(updateFOV) 2277 | { 2278 | currentFOV = Mathf.Lerp(currentFOV, manualFOV, 0.1f); 2279 | flightCamera.SetFoV(currentFOV); 2280 | updateFOV = false; 2281 | } 2282 | } 2283 | 2284 | } 2285 | 2286 | 2287 | 2288 | 2289 | 2290 | public enum ReferenceModes {InitialVelocity, Surface, Orbit} 2291 | 2292 | public enum ToolModes {StationaryCamera, DogfightCamera, Pathing}; 2293 | } 2294 | 2295 | -------------------------------------------------------------------------------- /CameraTools/CameraKeyframe.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | namespace CameraTools 4 | { 5 | public struct CameraKeyframe 6 | { 7 | public Vector3 position; 8 | public Quaternion rotation; 9 | public float zoom; 10 | public float time; 11 | 12 | public CameraKeyframe(Vector3 pos, Quaternion rot, float z, float t) 13 | { 14 | position = pos; 15 | rotation = rot; 16 | zoom = z; 17 | time = t; 18 | } 19 | 20 | } 21 | 22 | public class CameraKeyframeComparer : IComparer 23 | { 24 | public int Compare(CameraKeyframe a, CameraKeyframe b) 25 | { 26 | return a.time.CompareTo(b.time); 27 | } 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /CameraTools/CameraPath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace CameraTools 6 | { 7 | public class CameraPath 8 | { 9 | public string pathName; 10 | int keyCount = 0; 11 | public int keyframeCount 12 | { 13 | get 14 | { 15 | return keyCount; 16 | } 17 | private set 18 | { 19 | keyCount = value; 20 | } 21 | } 22 | public List points; 23 | public List rotations; 24 | public List times; 25 | public List zooms; 26 | 27 | public float lerpRate = 15; 28 | public float timeScale = 1; 29 | 30 | Vector3Animation pointCurve; 31 | RotationAnimation rotationCurve; 32 | AnimationCurve zoomCurve; 33 | 34 | public CameraPath() 35 | { 36 | pathName = "New Path"; 37 | points = new List(); 38 | rotations = new List(); 39 | times = new List(); 40 | zooms = new List(); 41 | } 42 | 43 | public static CameraPath Load(ConfigNode node) 44 | { 45 | CameraPath newPath = new CameraPath(); 46 | 47 | newPath.pathName = node.GetValue("pathName"); 48 | newPath.points = ParseVectorList(node.GetValue("points")); 49 | newPath.rotations = ParseQuaternionList(node.GetValue("rotations")); 50 | newPath.times = ParseFloatList(node.GetValue("times")); 51 | newPath.zooms = ParseFloatList(node.GetValue("zooms")); 52 | newPath.lerpRate = float.Parse(node.GetValue("lerpRate")); 53 | newPath.timeScale = float.Parse(node.GetValue("timeScale")); 54 | newPath.Refresh(); 55 | 56 | return newPath; 57 | } 58 | 59 | public void Save(ConfigNode node) 60 | { 61 | Debug.Log("Saving path: " + pathName); 62 | ConfigNode pathNode = node.AddNode("CAMERAPATH"); 63 | pathNode.AddValue("pathName", pathName); 64 | pathNode.AddValue("points", WriteVectorList(points)); 65 | pathNode.AddValue("rotations", WriteQuaternionList(rotations)); 66 | pathNode.AddValue("times", WriteFloatList(times)); 67 | pathNode.AddValue("zooms", WriteFloatList(zooms)); 68 | pathNode.AddValue("lerpRate", lerpRate); 69 | pathNode.AddValue("timeScale", timeScale); 70 | } 71 | 72 | public static string WriteVectorList(List list) 73 | { 74 | string output = string.Empty; 75 | foreach(var val in list) 76 | { 77 | output += ConfigNode.WriteVector(val) + ";"; 78 | } 79 | return output; 80 | } 81 | 82 | public static string WriteQuaternionList(List list) 83 | { 84 | string output = string.Empty; 85 | foreach(var val in list) 86 | { 87 | output += ConfigNode.WriteQuaternion(val) + ";"; 88 | } 89 | return output; 90 | } 91 | 92 | public static string WriteFloatList(List list) 93 | { 94 | string output = string.Empty; 95 | foreach(var val in list) 96 | { 97 | output += val.ToString() + ";"; 98 | } 99 | return output; 100 | } 101 | 102 | public static List ParseVectorList(string arrayString) 103 | { 104 | string[] vectorStrings = arrayString.Split(new char[]{ ';' }, StringSplitOptions.RemoveEmptyEntries); 105 | List vList = new List(); 106 | for(int i = 0; i < vectorStrings.Length; i++) 107 | { 108 | Debug.Log("attempting to parse vector: --" + vectorStrings[i] + "--"); 109 | vList.Add(ConfigNode.ParseVector3(vectorStrings[i])); 110 | } 111 | 112 | return vList; 113 | } 114 | 115 | public static List ParseQuaternionList(string arrayString) 116 | { 117 | string[] qStrings = arrayString.Split(new char[]{ ';' }, StringSplitOptions.RemoveEmptyEntries); 118 | List qList = new List(); 119 | for(int i = 0; i < qStrings.Length; i++) 120 | { 121 | qList.Add(ConfigNode.ParseQuaternion(qStrings[i])); 122 | } 123 | 124 | return qList; 125 | } 126 | 127 | public static List ParseFloatList(string arrayString) 128 | { 129 | string[] fStrings = arrayString.Split(new char[]{ ';' }, StringSplitOptions.RemoveEmptyEntries); 130 | List fList = new List(); 131 | for(int i = 0; i < fStrings.Length; i++) 132 | { 133 | fList.Add(float.Parse(fStrings[i])); 134 | } 135 | 136 | return fList; 137 | } 138 | 139 | public void AddTransform(Transform cameraTransform, float zoom, float time) 140 | { 141 | points.Add(cameraTransform.localPosition); 142 | rotations.Add(cameraTransform.localRotation); 143 | zooms.Add(zoom); 144 | times.Add(time); 145 | keyframeCount = times.Count; 146 | Sort(); 147 | UpdateCurves(); 148 | } 149 | 150 | public void SetTransform(int index, Transform cameraTransform, float zoom, float time) 151 | { 152 | points[index] = cameraTransform.localPosition; 153 | rotations[index] = cameraTransform.localRotation; 154 | zooms[index] = zoom; 155 | times[index] = time; 156 | Sort(); 157 | UpdateCurves(); 158 | } 159 | 160 | public void Refresh() 161 | { 162 | keyframeCount = times.Count; 163 | Sort(); 164 | UpdateCurves(); 165 | } 166 | 167 | public void RemoveKeyframe(int index) 168 | { 169 | points.RemoveAt(index); 170 | rotations.RemoveAt(index); 171 | zooms.RemoveAt(index); 172 | times.RemoveAt(index); 173 | keyframeCount = times.Count; 174 | UpdateCurves(); 175 | } 176 | 177 | public void Sort() 178 | { 179 | List keyframes = new List(); 180 | for(int i = 0; i < points.Count; i++) 181 | { 182 | keyframes.Add(new CameraKeyframe(points[i], rotations[i], zooms[i], times[i])); 183 | } 184 | keyframes.Sort(new CameraKeyframeComparer()); 185 | 186 | for(int i = 0; i < keyframes.Count; i++) 187 | { 188 | points[i] = keyframes[i].position; 189 | rotations[i] = keyframes[i].rotation; 190 | zooms[i] = keyframes[i].zoom; 191 | times[i] = keyframes[i].time; 192 | } 193 | } 194 | 195 | public CameraKeyframe GetKeyframe(int index) 196 | { 197 | int i = index; 198 | return new CameraKeyframe(points[i], rotations[i], zooms[i], times[i]); 199 | } 200 | 201 | public void UpdateCurves() 202 | { 203 | pointCurve = new Vector3Animation(points.ToArray(), times.ToArray()); 204 | rotationCurve = new RotationAnimation(rotations.ToArray(), times.ToArray()); 205 | zoomCurve = new AnimationCurve(); 206 | for(int i = 0; i < zooms.Count; i++) 207 | { 208 | zoomCurve.AddKey(new Keyframe(times[i], zooms[i])); 209 | } 210 | } 211 | 212 | public CameraTransformation Evaulate(float time) 213 | { 214 | CameraTransformation tf = new CameraTransformation(); 215 | tf.position = pointCurve.Evaluate(time); 216 | tf.rotation = rotationCurve.Evaluate(time); 217 | tf.zoom = zoomCurve.Evaluate(time); 218 | 219 | return tf; 220 | } 221 | 222 | 223 | 224 | 225 | 226 | } 227 | } 228 | 229 | -------------------------------------------------------------------------------- /CameraTools/CameraTools.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 9.0.21022 7 | 2.0 8 | {446E2470-00DC-4835-B62D-9DB8A7D41F4A} 9 | Library 10 | CameraTools 11 | CameraTools 12 | v4.7.2 13 | 14 | 15 | 16 | 17 | 3.5 18 | 19 | 20 | 21 | 22 | True 23 | full 24 | False 25 | bin\Debug 26 | DEBUG; 27 | prompt 28 | 4 29 | x86 30 | False 31 | false 32 | 33 | 34 | none 35 | False 36 | bin\Release 37 | prompt 38 | 4 39 | x86 40 | False 41 | false 42 | 43 | 44 | true 45 | bin\Debug\ 46 | DEBUG; 47 | full 48 | AnyCPU 49 | prompt 50 | MinimumRecommendedRules.ruleset 51 | false 52 | 53 | 54 | bin\Release\ 55 | AnyCPU 56 | prompt 57 | MinimumRecommendedRules.ruleset 58 | true 59 | false 60 | portable 61 | true 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | False 81 | ..\..\_LocalDev\KSPRefs\Assembly-CSharp.dll 82 | 83 | 84 | False 85 | ..\..\_LocalDev\KSPRefs\KSPAssets.dll 86 | 87 | 88 | 89 | 90 | False 91 | ..\..\_LocalDev\KSPRefs\UnityEngine.dll 92 | 93 | 94 | ..\..\_LocalDev\KSPRefs\UnityEngine.AnimationModule.dll 95 | 96 | 97 | ..\..\_LocalDev\KSPRefs\UnityEngine.AssetBundleModule.dll 98 | 99 | 100 | ..\..\_LocalDev\KSPRefs\UnityEngine.AudioModule.dll 101 | 102 | 103 | ..\..\_LocalDev\KSPRefs\UnityEngine.CoreModule.dll 104 | 105 | 106 | ..\..\_LocalDev\KSPRefs\UnityEngine.ImageConversionModule.dll 107 | 108 | 109 | ..\..\_LocalDev\KSPRefs\UnityEngine.IMGUIModule.dll 110 | 111 | 112 | ..\..\_LocalDev\KSPRefs\UnityEngine.InputLegacyModule.dll 113 | 114 | 115 | ..\..\_LocalDev\KSPRefs\UnityEngine.InputModule.dll 116 | 117 | 118 | ..\..\_LocalDev\KSPRefs\UnityEngine.JSONSerializeModule.dll 119 | 120 | 121 | ..\..\_LocalDev\KSPRefs\UnityEngine.ParticleSystemModule.dll 122 | 123 | 124 | ..\..\_LocalDev\KSPRefs\UnityEngine.PhysicsModule.dll 125 | 126 | 127 | ..\..\_LocalDev\KSPRefs\UnityEngine.TextCoreModule.dll 128 | 129 | 130 | ..\..\_LocalDev\KSPRefs\UnityEngine.TextRenderingModule.dll 131 | 132 | 133 | False 134 | ..\..\_LocalDev\KSPRefs\UnityEngine.UI.dll 135 | 136 | 137 | ..\..\_LocalDev\KSPRefs\UnityEngine.UIElementsModule.dll 138 | 139 | 140 | ..\..\_LocalDev\KSPRefs\UnityEngine.UIModule.dll 141 | 142 | 143 | ..\..\_LocalDev\KSPRefs\UnityEngine.UnityWebRequestWWWModule.dll 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | @echo $(Targetname) 170 | @echo ... 171 | @echo set lpath vars from LocalDev storage... 172 | set /p KSP_DIR=<"$(ProjectDir)LocalDev\ksp_dir.txt" 173 | set /p PDB2MDB_EXE=<"$(ProjectDir)LocalDev\pdb2mdb_exe.txt" 174 | set /p ZA_DIR=<"$(ProjectDir)LocalDev\7za_dir.txt" 175 | set /p DIST_DIR=<"$(ProjectDir)LocalDev\dist_dir.txt" 176 | 177 | @echo distributing $(Targetname) files... 178 | copy /Y "$(TargetPath)" "$(ProjectDir)Distribution\GameData\CameraTools\Plugins\" 179 | 180 | if $(ConfigurationName) == Debug ( 181 | @echo building $(Targetname).dll.mdb file... 182 | cd "$(TargetDir)" 183 | copy /Y "$(TargetDir)$(Targetname).pdb" "%25KSP_DIR%25\GameData\CameraTools\Plugins\" 184 | ) 185 | 186 | @echo packaging files... 187 | if exist "%25DIST_DIR%25\CameraTools*.zip" del "%25DIST_DIR%25\CameraTools*.zip" 188 | call "%25ZA_DIR%25\7za.exe" a -tzip -r "%25DIST_DIR%25\CameraTools.@(VersionNumber)_%25DATE:~4,2%25%25DATE:~7,2%25%25DATE:~10,4%25.zip" "$(ProjectDir)Distribution\*.*" 189 | 190 | @echo Deploy $(Targetname) Distribution files to test env: %25KSP_DIR%25\GameData... 191 | @echo copying:"$(SolutionDir)\CameraTools\Distribution\GameData" to "%25KSP_DIR%25\GameData" 192 | xcopy /E /Y "$(SolutionDir)\CameraTools\Distribution\GameData" "%25KSP_DIR%25\GameData" 193 | 194 | if $(ConfigurationName) == Debug ( 195 | copy /Y "$(TargetDir)$(Targetname).pdb" "%25KSP_DIR%25\GameData\CameraTools\Plugins\" 196 | ) 197 | 198 | @echo Build/deploy complete! 199 | 200 | -------------------------------------------------------------------------------- /CameraTools/CameraTransformation.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | namespace CameraTools 3 | { 4 | public struct CameraTransformation 5 | { 6 | public Vector3 position; 7 | public Quaternion rotation; 8 | public float zoom; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /CameraTools/Curve3D.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace CameraTools 4 | { 5 | public class Curve3D 6 | { 7 | private Vector3[] points; 8 | private float[] times; 9 | private AnimationCurve[] curves; 10 | 11 | bool curveReady = false; 12 | 13 | // Use this for initialization 14 | public Curve3D() 15 | { 16 | curves = new AnimationCurve[]{new AnimationCurve(), new AnimationCurve(), new AnimationCurve()}; 17 | } 18 | 19 | public Curve3D(Vector3[] newPoints, float[] newTimes) 20 | { 21 | curves = new AnimationCurve[]{new AnimationCurve(), new AnimationCurve(), new AnimationCurve()}; 22 | SetPoints(newPoints, newTimes); 23 | } 24 | 25 | public void SetPoints(Vector3[] newPoints, float[] newTimes) 26 | { 27 | if(newPoints.Length != newTimes.Length) 28 | { 29 | Debug.LogError("Curve3D: points array must be same length as times array"); 30 | return; 31 | } 32 | points = new Vector3[newPoints.Length]; 33 | times = new float[newPoints.Length]; 34 | for(int i = 0; i < points.Length; i++) 35 | { 36 | points[i] = newPoints[i]; 37 | times[i] = newTimes[i]; 38 | } 39 | 40 | UpdateCurve(); 41 | } 42 | 43 | public void SetPoint(int index, Vector3 newPoint, float newTime) 44 | { 45 | if(index < points.Length) 46 | { 47 | SetAnimKey(index, newPoint, newTime); 48 | } 49 | else 50 | { 51 | Debug.LogError("Tried to set new point in a Curve3D beyond the existing array. Not yet implemented."); 52 | } 53 | } 54 | 55 | 56 | private void UpdateCurve() 57 | { 58 | curveReady = false; 59 | //clear existing keys 60 | for(int i = 0; i < 3; i++) 61 | { 62 | curves[i] = new AnimationCurve(); 63 | } 64 | 65 | if(points.Length == 0) return; 66 | 67 | for(int i = 0; i < points.Length; i++) 68 | { 69 | SetAnimKey(i, points[i], times[i]); 70 | } 71 | 72 | curveReady = true; 73 | } 74 | 75 | void SetAnimKey(int index, Vector3 point, float time) 76 | { 77 | if(index >= curves[0].keys.Length) 78 | { 79 | curves[0].AddKey(time, point.x); 80 | curves[1].AddKey(time, point.y); 81 | curves[2].AddKey(time, point.z); 82 | } 83 | else 84 | { 85 | curves[0].MoveKey(index, new Keyframe(time, point.x)); 86 | curves[1].MoveKey(index, new Keyframe(time, point.y)); 87 | curves[2].MoveKey(index, new Keyframe(time, point.z)); 88 | } 89 | } 90 | 91 | public Vector3 GetPoint(float time) 92 | { 93 | if(!curveReady) 94 | { 95 | Debug.LogWarning("Curve was accessed but it was not properly initialized."); 96 | return Vector3.zero; 97 | } 98 | 99 | float x = curves[0].Evaluate(time); 100 | float y = curves[1].Evaluate(time); 101 | float z = curves[2].Evaluate(time); 102 | return new Vector3(x,y,z); 103 | } 104 | 105 | public Vector3 GetTangent(float time) 106 | { 107 | if(!curveReady) 108 | { 109 | Debug.LogWarning("Curve was accessed but it was not properly initialized."); 110 | return Vector3.one; 111 | } 112 | 113 | if(time < 1) 114 | { 115 | return (GetPoint(Mathf.Min(time+0.01f, 1))-GetPoint(time)).normalized; 116 | } 117 | else 118 | { 119 | return (GetPoint(1)-GetPoint(0.99f)).normalized; 120 | } 121 | } 122 | 123 | 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/ATM_CameraTools.cfg: -------------------------------------------------------------------------------- 1 | ACTIVE_TEXTURE_MANAGER_CONFIG 2 | { 3 | folder = CameraTools 4 | enabled = true 5 | 6 | OVERRIDES 7 | { 8 | CameraTools/Textures/.* 9 | { 10 | compress = true 11 | mipmaps = false 12 | scale = 1 13 | max_size = 0 14 | make_not_readable = false 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/CameraTools.version: -------------------------------------------------------------------------------- 1 | { 2 | "NAME": "CameraTools", 3 | "URL": "https://raw.githubusercontent.com/jrodrigv/CameraTools/master/CameraTools/Distribution/GameData/CameraTools/CameraTools.version", 4 | "DOWNLOAD": "https://github.com/jrodrigv/CameraTools/releases/tag/v1.14.0", 5 | "CHANGE_LOG_URL": "https://github.com/jrodrigv/CameraTools/blob/master/CameraTools/Distribution/GameData/CameraTools/Changelog.txt", 6 | "VERSION": { 7 | "MAJOR": 1, 8 | "MINOR": 14, 9 | "PATCH": 0, 10 | "BUILD": 0 11 | }, 12 | "KSP_VERSION": { 13 | "MAJOR": 1, 14 | "MINOR": 9, 15 | "PATCH": 0 16 | }, 17 | "KSP_VERSION_MIN": { 18 | "MAJOR": 1, 19 | "MINOR": 9, 20 | "PATCH": 0 21 | }, 22 | "KSP_VERSION_MAX": { 23 | "MAJOR": 1, 24 | "MINOR": 9, 25 | "PATCH": 99 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Changelog.txt: -------------------------------------------------------------------------------- 1 | v1.14.0 2 | - Compatibility with KSP 1.9.x 3 | 4 | v1.13.0 5 | - Compatibility with KSP 1.8.x 6 | 7 | v1.12.0 8 | - Compatibility with KSP 1.7.x 9 | 10 | v1.11.0 11 | - Compatibility with KSP 1.5.x 12 | 13 | v1.10.0 14 | - Compatibility with KSP 1.4.x 15 | 16 | v1.9.0 17 | - Compatibility with KSP 1.3.1 18 | - Fixing Dogfighting camera for BDArmory 19 | 20 | v1.8.0 21 | - Compatibility with KSP 1.2.2 and KSP 1.2.9 BETA 22 | - Fixing isssue when reverting the camera 23 | 24 | 25 | v1.7.0 26 | - Compatibility with KSP 1.2.1 27 | 28 | v1.6.0 29 | - 1.1 compat and path tool 30 | - fix loading paths/deleting paths, fix deleting selected key 31 | - set spatial blend to 3d audio 32 | 33 | v1.5.1 34 | - Dogfight mode auto-resets when a new target is selected or active vessel is switched 35 | - Auto targeting option with BDArmory AI pilot target 36 | 37 | v1.5 38 | - Dogfight chase mode 39 | - Autozoom margin slider 40 | 41 | v1.4.2 42 | - Slight UI tweak 43 | - Incremental buttons for manual offset 44 | 45 | v1.4.1 46 | - Ability to save persistant settings 47 | - Fixed part audio too loud when stationary 48 | - Fixed inability to select auto position without unchecking manual position 49 | - Stopped sonic boom being played when vessel breaks sound barrier after wavefront already passed camera 50 | - Increased sonic boom volume 51 | - Temporary fix for silent atmospheric audio when >~600m/s 52 | 53 | v1.4 54 | - Atmospheric audio effects (toggleable) 55 | - Camera shake (adjustable) 56 | 57 | v1.3 58 | - 1.0+ Compatibility 59 | - Manual camera position now persists after resetting camera 60 | - Bind activate/reset key by recording instead of typing button name 61 | - Camera no longer resets when pausing 62 | 63 | 64 | v1.2 65 | - Added Orbit frame of reference 66 | - Fixed issues with setting camera offset to vertically launching vehicles 67 | 68 | v1.1 69 | - 0.25 update 70 | - Added ability to set location -before- activating camera 71 | - Fixed text fields in GUI (it won't fight you when entering negatives or decimals) 72 | - Fixed Toolbar Icon 73 | - Greatly reduced motion of stationary camera when vessel is accelerating/turning 74 | 75 | 76 | v1.0 77 | - Initial release -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/License.txt: -------------------------------------------------------------------------------- 1 | This plugin for Kerbal Space Program is licensed under GPLv3. 2 | For more information, please visit this site: 3 | http://www.gnu.org/copyleft/gpl.html -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Plugins/CameraTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Plugins/CameraTools.dll -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Sounds/sonicBoom.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Sounds/sonicBoom.wav -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Sounds/windhowl.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Sounds/windhowl.wav -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Sounds/windloop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Sounds/windloop.wav -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Sounds/windtear.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Sounds/windtear.wav -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/Textures/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/Distribution/GameData/CameraTools/Textures/icon.png -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/paths.cfg: -------------------------------------------------------------------------------- 1 | CAMERAPATHS 2 | { 3 | CAMERAPATH 4 | { 5 | pathName = New Path 6 | points = 13.40305,-16.60615,-4.274539;14.48815,-13.88801,-4.26651;14.48839,-13.88819,-4.267331;15.52922,-14.25925,-4.280066; 7 | rotations = 0.5759971,0.2491289,-0.2965982,-0.7198553;-0.6991884,0.09197949,-0.08556388,0.7038141;-0.6991884,0.09197949,-0.08556388,0.7038141;-0.6506922,0.2786613,-0.271617,0.6520521; 8 | times = 0;1;2;6; 9 | zooms = 1;2.035503;3.402367;3.402367; 10 | lerpRate = 3.1 11 | timeScale = 0.29 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CameraTools/Distribution/GameData/CameraTools/settings.cfg: -------------------------------------------------------------------------------- 1 | CToolsSettings 2 | { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /CameraTools/LocalDev/7za_dir.txt: -------------------------------------------------------------------------------- 1 | G:\7za\x64 -------------------------------------------------------------------------------- /CameraTools/LocalDev/dist_dir.txt: -------------------------------------------------------------------------------- 1 | D:\PROGRAMACION\KSP_Development -------------------------------------------------------------------------------- /CameraTools/LocalDev/ksp_dir.txt: -------------------------------------------------------------------------------- 1 | G:\GAMES\KERBAL\Kerbal Space Program_18_DEV -------------------------------------------------------------------------------- /CameraTools/LocalDev/ksp_dir2.txt: -------------------------------------------------------------------------------- 1 | G:\GAMES\KERBAL\Kerbal Space Program_DEV_161M 2 | -------------------------------------------------------------------------------- /CameraTools/LocalDev/mono_exe.txt: -------------------------------------------------------------------------------- 1 | G:\Unity\Editor\Data\MonoBleedingEdge\bin\mono.exe -------------------------------------------------------------------------------- /CameraTools/LocalDev/pdb2mdb_exe.txt: -------------------------------------------------------------------------------- 1 | G:\pdb2mdb\pdb2mdb.exe -------------------------------------------------------------------------------- /CameraTools/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle( "CameraTools" )] 8 | [assembly: AssemblyDescription( "" )] 9 | [assembly: AssemblyConfiguration( "" )] 10 | [assembly: AssemblyCompany( "" )] 11 | [assembly: AssemblyProduct( "CameraTools" )] 12 | [assembly: AssemblyCopyright( "Copyright © 2019" )] 13 | [assembly: AssemblyTrademark( "" )] 14 | [assembly: AssemblyCulture( "" )] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible( false )] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid( "d17db18a-01d0-4990-83f7-a17aa54ab16b" )] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | [assembly: AssemblyVersion( "1.14.0" )] 32 | [assembly: AssemblyFileVersion( "1.14.0.0" )] 33 | -------------------------------------------------------------------------------- /CameraTools/RotationAnimation.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | namespace CameraTools 3 | { 4 | public class RotationAnimation 5 | { 6 | Quaternion[] rotations; 7 | float[] times; 8 | 9 | public RotationAnimation (Quaternion[] rots, float[] times) 10 | { 11 | this.rotations = rots; 12 | this.times = times; 13 | } 14 | 15 | public Quaternion Evaluate(float t) 16 | { 17 | int startIndex = 0; 18 | for(int i = 0; i < times.Length; i++) 19 | { 20 | if(t >= times[i]) 21 | { 22 | startIndex = i; 23 | } 24 | else 25 | { 26 | break; 27 | } 28 | } 29 | 30 | int nextIndex = Mathf.RoundToInt(Mathf.Min(startIndex + 1, times.Length - 1)); 31 | 32 | float overTime = t - times[startIndex]; 33 | float intervalTime = times[nextIndex] - times[startIndex]; 34 | if(intervalTime <= 0) return rotations[nextIndex]; 35 | 36 | float normTime = overTime/intervalTime; 37 | return Quaternion.Lerp(rotations[startIndex], rotations[nextIndex], normTime); 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /CameraTools/Vector3Animation.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace CameraTools 4 | { 5 | public class Vector3Animation 6 | { 7 | Vector3[] positions; 8 | float[] times; 9 | 10 | public Vector3Animation(Vector3[] pos, float[] times) 11 | { 12 | this.positions = pos; 13 | this.times = times; 14 | } 15 | 16 | public Vector3 Evaluate(float t) 17 | { 18 | int startIndex = 0; 19 | for(int i = 0; i < times.Length; i++) 20 | { 21 | if(t >= times[i]) 22 | { 23 | startIndex = i; 24 | } 25 | else 26 | { 27 | break; 28 | } 29 | } 30 | 31 | int nextIndex = Mathf.RoundToInt(Mathf.Min(startIndex + 1, times.Length - 1)); 32 | 33 | float overTime = t - times[startIndex]; 34 | float intervalTime = times[nextIndex] - times[startIndex]; 35 | if(intervalTime <= 0) return positions[nextIndex]; 36 | 37 | float normTime = overTime/intervalTime; 38 | return Vector3.Lerp(positions[startIndex], positions[nextIndex], normTime); 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /CameraTools/bin/Release/CameraTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jrodrigv/CameraTools/c4e739d3b1142299d06cf46fb4df4c23a2b0690c/CameraTools/bin/Release/CameraTools.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Camera Tools (forked by westamastaflash) 2 | 3 | Custom Camera angles for Cinematics! 4 | 5 | KSP Forum Thread: 6 | http://forum.kerbalspaceprogram.com/index.php?/topic/84938-105-camera-tools-v151-dogfight-mode-autozoom-margin-slider-march-28/ 7 | 8 | 9 | --------------------------------------------------------------------------------