├── Cutscene Ed ├── Gizmos │ └── Cutscene.png ├── Effects │ ├── Filters │ │ ├── CutsceneInvertFilter.cs │ │ └── CutsceneBlurFilter.cs │ ├── CutsceneEffect.cs │ └── ImageEffects.cs ├── Editor │ ├── CutsceneEditorGUILayout.cs │ ├── ICutsceneGUI.cs │ ├── CutsceneOptions.cs │ ├── CutsceneSubtitleInspector.cs │ ├── CutsceneTools.cs │ ├── BugReporter.cs │ ├── CutsceneNavigation.cs │ ├── CutsceneTrackControls.cs │ ├── CutscenePreview.cs │ ├── CutsceneAddSubtitle.cs │ ├── CutscenePlaybackControls.cs │ ├── CutsceneAddAudio.cs │ ├── CutsceneAddActor.cs │ ├── CutsceneHotkeys.cs │ ├── CutsceneInspector.cs │ ├── CutsceneTrackInfo.cs │ ├── CutsceneEffectsWindow.cs │ ├── CutsceneTimeline.cs │ ├── CutsceneTimecodeBar.cs │ ├── CutsceneMediaWindow.cs │ ├── CutsceneTracksView.cs │ └── CutsceneEditor.cs └── Scripts │ ├── CutsceneShot.cs │ ├── CutsceneAudio.cs │ ├── CutsceneActor.cs │ ├── CutsceneTrigger.cs │ ├── CutsceneSubtitle.cs │ ├── CutsceneMedia.cs │ ├── EDebug.cs │ ├── CutsceneClip.cs │ ├── CutsceneTrack.cs │ └── Cutscene.cs ├── Editor Default Resources └── Cutscene Ed │ ├── gui_pane.png │ ├── icon_add.png │ ├── icon_eye.png │ ├── overlay.png │ ├── resize.png │ ├── clip_actor.png │ ├── clip_audio.png │ ├── clip_shot.png │ ├── icon_lock.png │ ├── media_shot.png │ ├── tool_move.png │ ├── tool_zoom.png │ ├── track_lock.png │ ├── clip_selected.png │ ├── clip_subtitle.png │ ├── gui_selection.png │ ├── icon_addtrack.png │ ├── icon_zoomout.png │ ├── media_actor.png │ ├── media_audio.png │ ├── playback_back.png │ ├── playback_in.png │ ├── playback_out.png │ ├── playback_play.png │ ├── tool_scissors.png │ ├── effects_filter.png │ ├── media_subtitle.png │ ├── playback_pause.png │ ├── effects_transition.png │ ├── gui_trackcontrols.png │ ├── inpoint_indicator.png │ ├── outpoint_indicator.png │ ├── playback_forward.png │ ├── position_indicator.png │ ├── icon_zoomtotimeline.png │ ├── cutscene_editor_style.guiskin │ └── Icons.txt └── README.md /Cutscene Ed/Gizmos/Cutscene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Cutscene Ed/Gizmos/Cutscene.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/gui_pane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/gui_pane.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_add.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_eye.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/overlay.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/resize.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/clip_actor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/clip_actor.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/clip_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/clip_audio.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/clip_shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/clip_shot.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_lock.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/media_shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/media_shot.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/tool_move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/tool_move.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/tool_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/tool_zoom.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/track_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/track_lock.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/clip_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/clip_selected.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/clip_subtitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/clip_subtitle.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/gui_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/gui_selection.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_addtrack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_addtrack.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_zoomout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_zoomout.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/media_actor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/media_actor.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/media_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/media_audio.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_back.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_in.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_out.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_play.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/tool_scissors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/tool_scissors.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/effects_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/effects_filter.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/media_subtitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/media_subtitle.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_pause.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/effects_transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/effects_transition.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/gui_trackcontrols.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/gui_trackcontrols.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/inpoint_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/inpoint_indicator.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/outpoint_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/outpoint_indicator.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/playback_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/playback_forward.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/position_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/position_indicator.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/icon_zoomtotimeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/icon_zoomtotimeline.png -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/cutscene_editor_style.guiskin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mminer/silverscreen/HEAD/Editor Default Resources/Cutscene Ed/cutscene_editor_style.guiskin -------------------------------------------------------------------------------- /Editor Default Resources/Cutscene Ed/Icons.txt: -------------------------------------------------------------------------------- 1 | Editor icons are courtesy of Fugue Icons, available online at http://www.pinvoke.com. They are licensed under the Creative Commons Attribution 3.0 license (http://creativecommons.org/licenses/by/3.0/). -------------------------------------------------------------------------------- /Cutscene Ed/Effects/Filters/CutsceneInvertFilter.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | // Based off of InvertCamera.js by Joachim Ante 4 | // Retrieved from the Unify Community wiki (http://www.unifycommunity.com/wiki/index.php?title=InvertCamera) 5 | 6 | public class CutsceneInvertFilter : CutsceneEffect { 7 | [HideInInspector] 8 | public static new string name = "Invert"; 9 | 10 | void OnPreCull () { 11 | camera.ResetWorldToCameraMatrix(); 12 | camera.ResetProjectionMatrix(); 13 | camera.projectionMatrix = camera.projectionMatrix * Matrix4x4.Scale(new Vector3(1, -1, 1)); 14 | } 15 | 16 | void OnPreRender () { 17 | GL.SetRevertBackfacing(true); 18 | } 19 | 20 | void OnPostRender () { 21 | GL.SetRevertBackfacing(false); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneEditorGUILayout.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | public delegate void GUIContents (); 5 | 6 | public static class CutsceneEditorGUILayout 7 | { 8 | public static Rect Horizontal (GUIContents contents, params GUILayoutOption[] options) 9 | { 10 | Rect rect = EditorGUILayout.BeginHorizontal(options); 11 | contents(); 12 | EditorGUILayout.EndHorizontal(); 13 | 14 | return rect; 15 | } 16 | 17 | public static Rect Horizontal (GUIContents contents, GUIStyle style, params GUILayoutOption[] options) 18 | { 19 | Rect rect = EditorGUILayout.BeginHorizontal(style, options); 20 | contents(); 21 | EditorGUILayout.EndHorizontal(); 22 | 23 | return rect; 24 | } 25 | } 26 | 27 | public static class CutsceneGUILayout 28 | { 29 | public static void Area (GUIContents contents, Rect screenRect) 30 | { 31 | GUILayout.BeginArea(screenRect); 32 | contents(); 33 | GUILayout.EndArea(); 34 | } 35 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneShot.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | [RequireComponent(typeof(Camera))] 26 | public class CutsceneShot : CutsceneMedia {} -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneAudio.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | [RequireComponent(typeof(AudioSource))] 26 | public class CutsceneAudio : CutsceneMedia {} -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneActor.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | public class CutsceneActor : CutsceneMedia 26 | { 27 | public AnimationClip anim; 28 | public GameObject go; 29 | } -------------------------------------------------------------------------------- /Cutscene Ed/Effects/CutsceneEffect.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | /// 26 | /// Base class for all cutscene effects. 27 | /// 28 | [ExecuteInEditMode] 29 | [RequireComponent(typeof(CutsceneShot))] 30 | public class CutsceneEffect : MonoBehaviour {} -------------------------------------------------------------------------------- /Cutscene Ed/Editor/ICutsceneGUI.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | interface ICutsceneGUI 26 | { 27 | /// 28 | /// Displays the GUI for this element. 29 | /// 30 | /// The bounding box this element is contained in. 31 | void OnGUI (Rect rect); 32 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneTrigger.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using System.Collections; 25 | 26 | public class CutsceneTrigger : MonoBehaviour 27 | { 28 | public Cutscene scene; 29 | 30 | void Update () 31 | { 32 | //TEMP 33 | if (Input.GetKey("p")) { 34 | scene.PlayCutscene(); 35 | } 36 | } 37 | 38 | void OnTriggerEnter (Collider collider) 39 | { 40 | scene.PlayCutscene(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneSubtitle.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | public class CutsceneSubtitle : CutsceneMedia 26 | { 27 | public string dialog; 28 | 29 | public new string name { 30 | get { 31 | int maxTitleLength = 25; 32 | string _name = dialog; 33 | if (_name.Length > maxTitleLength) { 34 | _name = _name.Substring(0, maxTitleLength) + " ..."; 35 | } 36 | return _name; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Silver Screen 2 | ============= 3 | 4 | Editor tools for creating cinematics using the Unity game engine. 5 | 6 | I haven't updated this in ages. If you're looking for a cutscene editor, there 7 | are numerous good options on the Asset Store that are more likely to work well 8 | with the latest version of Unity. 9 | 10 | 11 | Release History 12 | --------------- 13 | 14 | - 0.1 15 | - Initial release 16 | - Compatible with Unity 2.6 17 | 18 | 19 | License 20 | ------- 21 | 22 | All code is released under the MIT license. 23 | 24 | > Copyright (c) 2010 Matthew Miner 25 | > 26 | > Permission is hereby granted, free of charge, to any person obtaining a copy 27 | > of this software and associated documentation files (the "Software"), to deal 28 | > in the Software without restriction, including without limitation the rights 29 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 30 | > copies of the Software, and to permit persons to whom the Software is 31 | > furnished to do so, subject to the following conditions: 32 | > 33 | > The above copyright notice and this permission notice shall be included in 34 | > all copies or substantial portions of the Software. 35 | > 36 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 39 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 40 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 41 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 42 | > THE SOFTWARE. 43 | -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneMedia.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | public abstract class CutsceneMedia : MonoBehaviour 26 | { 27 | public Cutscene.MediaType type { 28 | get { 29 | if (this.GetType() == typeof(CutsceneShot)) { 30 | return Cutscene.MediaType.Shots; 31 | } else if (this.GetType() == typeof(CutsceneActor)) { 32 | return Cutscene.MediaType.Actors; 33 | } else if (this.GetType() == typeof(CutsceneAudio)) { 34 | return Cutscene.MediaType.Audio; 35 | } else { // obj.GetType() == typeof(CutsceneSubtitle) 36 | return Cutscene.MediaType.Subtitles; 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneOptions.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | class CutsceneOptions : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | public CutsceneOptions (CutsceneEditor ed) 31 | { 32 | this.ed = ed; 33 | } 34 | 35 | /// 36 | /// Displays the options window. 37 | /// 38 | /// The options window's Rect. 39 | public void OnGUI (Rect rect) 40 | { 41 | GUILayout.BeginArea(rect); 42 | 43 | ed.scene.inPoint = GUILayout.HorizontalSlider(ed.scene.inPoint, 0, 100); 44 | 45 | GUILayout.EndArea(); 46 | } 47 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneSubtitleInspector.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | /// 27 | /// A custom inspector for a subtitle. 28 | /// 29 | [CustomEditor (typeof(CutsceneSubtitle))] 30 | public class CutsceneSubtitleInspector : Editor 31 | { 32 | CutsceneSubtitle subtitle { 33 | get { return target as CutsceneSubtitle; } 34 | } 35 | 36 | public override void OnInspectorGUI () 37 | { 38 | EditorGUILayout.BeginHorizontal(); 39 | 40 | EditorGUILayout.PrefixLabel("Dialog"); 41 | subtitle.dialog = EditorGUILayout.TextArea(subtitle.dialog); 42 | 43 | EditorGUILayout.EndHorizontal(); 44 | 45 | if (GUI.changed) { 46 | EditorUtility.SetDirty(subtitle); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneTools.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | public enum Tool { 27 | MoveResize, 28 | Scissors, 29 | Zoom 30 | } 31 | 32 | class CutsceneTools : ICutsceneGUI 33 | { 34 | readonly CutsceneEditor ed; 35 | 36 | readonly GUIContent[] tools = { 37 | new GUIContent(EditorGUIUtility.LoadRequired("Cutscene Ed/tool_move.png") as Texture, "Move/Resize"), 38 | new GUIContent(EditorGUIUtility.LoadRequired("Cutscene Ed/tool_scissors.png") as Texture, "Scissors"), 39 | new GUIContent(EditorGUIUtility.LoadRequired("Cutscene Ed/tool_zoom.png") as Texture, "Zoom") 40 | }; 41 | 42 | public CutsceneTools (CutsceneEditor ed) 43 | { 44 | this.ed = ed; 45 | } 46 | 47 | public void OnGUI (Rect rect) 48 | { 49 | CutsceneGUILayout.Area(delegate { 50 | CutsceneEditorGUILayout.Horizontal(delegate { 51 | 52 | GUILayout.FlexibleSpace(); 53 | ed.currentTool = (Tool)GUILayout.Toolbar((int)ed.currentTool, tools); 54 | 55 | }, ed.style.GetStyle("Tools Bar"), GUILayout.Width(rect.width)); 56 | }, rect); 57 | } 58 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/EDebug.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | 25 | /// 26 | /// A simple class for toggle-able debug messages. Debug messages for editor tools are useful when developing the tool itself, but annoying for end users. 27 | /// 28 | public class EDebug 29 | { 30 | static bool debug = false; 31 | 32 | public static void Break () 33 | { 34 | if (debug) Debug.Break(); 35 | } 36 | 37 | public static void Log (object message) 38 | { 39 | if (debug) Debug.Log(message); 40 | } 41 | 42 | public static void Log (object message, Object context) 43 | { 44 | if (debug) Debug.Log(message, context); 45 | } 46 | 47 | public static void LogError (object message) 48 | { 49 | if (debug) Debug.LogError(message); 50 | } 51 | 52 | public static void LogError (object message, Object context) 53 | { 54 | if (debug) Debug.LogError(message, context); 55 | } 56 | 57 | public static void LogWarning (object message) 58 | { 59 | if (debug) Debug.LogWarning(message); 60 | } 61 | 62 | public static void LogWarning (object message, Object context) 63 | { 64 | if (debug) Debug.LogWarning(message, context); 65 | } 66 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/BugReporter.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | public class BugReporter : EditorWindow 27 | { 28 | string email = ""; 29 | string details = ""; 30 | 31 | readonly GUIContent emailLabel = new GUIContent("Your Email", "If we require additional information, we'll contact you at the supplied address (optional)."); 32 | readonly GUIContent submitLabel = new GUIContent("Submit", "Send this bug report."); 33 | 34 | /// 35 | /// Adds "Bug Reporter" to the Window menu. 36 | /// 37 | [MenuItem("Window/Bug Reporter")] 38 | public static void OpenEditor () 39 | { 40 | // Get existing open window or if none, make a new one 41 | GetWindow(true, "Bug Reporter").Show(); 42 | } 43 | 44 | void OnGUI () 45 | { 46 | GUILayout.Label("Please take a minute to tell us what happened in as much detail as possible. This makes it possible for us to fix the problem."); 47 | 48 | EditorGUILayout.Separator(); 49 | 50 | email = EditorGUILayout.TextField(emailLabel, email); 51 | 52 | EditorGUILayout.Separator(); 53 | 54 | GUILayout.Label("Problem Details:"); 55 | details = EditorGUILayout.TextArea(details); 56 | 57 | EditorGUILayout.BeginHorizontal(); 58 | 59 | GUILayout.FlexibleSpace(); 60 | 61 | if (GUILayout.Button(submitLabel, GUILayout.ExpandWidth(false))) { 62 | // TODO Send bug report 63 | Debug.Log("Bug report sent."); 64 | } 65 | EditorGUILayout.EndHorizontal(); 66 | } 67 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneNavigation.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | class CutsceneNavigation : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | readonly ICutsceneGUI playbackControls; 31 | readonly ICutsceneGUI timecodeBar; 32 | 33 | readonly GUIContent zoomButton = new GUIContent("", "Zoom timeline to entire scene."); 34 | 35 | public CutsceneNavigation (CutsceneEditor ed) 36 | { 37 | this.ed = ed; 38 | playbackControls = new CutscenePlaybackControls(ed); 39 | timecodeBar = new CutsceneTimecodeBar(ed); 40 | } 41 | 42 | public void OnGUI (Rect rect) 43 | { 44 | GUI.BeginGroup(rect); 45 | 46 | float zoomButtonWidth = GUI.skin.verticalScrollbar.fixedWidth; 47 | float timecodeBarWidth = ed.position.width - CutsceneTimeline.trackInfoWidth - zoomButtonWidth; 48 | 49 | // Playback controls 50 | Rect playbackControlsRect = new Rect(0, 0, CutsceneTimeline.trackInfoWidth, rect.height); 51 | playbackControls.OnGUI(playbackControlsRect); 52 | 53 | // Timecode bar 54 | Rect timecodeBarRect = new Rect(playbackControlsRect.xMax, 0, timecodeBarWidth, rect.height); 55 | timecodeBar.OnGUI(timecodeBarRect); 56 | 57 | // Zoom to view entire project 58 | Rect zoomButtonRect = new Rect(timecodeBarRect.xMax, 0, zoomButtonWidth, rect.height); 59 | if (GUI.Button(zoomButtonRect, zoomButton, EditorStyles.toolbarButton)) { 60 | ed.timelineZoom = ed.timelineMin; 61 | EDebug.Log("Cutscene Editor: zoomed timeline to entire scene"); 62 | } 63 | 64 | GUI.EndGroup(); 65 | } 66 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneTrackControls.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | class CutsceneTrackControls : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | readonly GUIContent newTrackLabel = new GUIContent( 31 | EditorGUIUtility.LoadRequired("Cutscene Ed/icon_addtrack.png") as Texture, 32 | "Add a new track." 33 | ); 34 | 35 | public CutsceneTrackControls (CutsceneEditor ed) 36 | { 37 | this.ed = ed; 38 | } 39 | 40 | public void OnGUI (Rect rect) 41 | { 42 | // TODO Make this a style in the cutscene editor's GUISkin 43 | GUIStyle popupStyle = "MiniToolbarButton"; 44 | popupStyle.padding = new RectOffset(0, 0, 2, 1); // Left, right, top, bottom 45 | 46 | GUI.BeginGroup(rect, GUI.skin.GetStyle("MiniToolbarButtonLeft")); 47 | 48 | // New track popdown 49 | Rect newTrackRect = new Rect(0, 0, 33, rect.height); 50 | GUI.Label(newTrackRect, newTrackLabel, popupStyle); 51 | 52 | if (Event.current.type == EventType.MouseDown && newTrackRect.Contains(Event.current.mousePosition)) { 53 | GUIUtility.hotControl = 0; 54 | EditorUtility.DisplayPopupMenu(newTrackRect, "Component/Cutscene/Track", null); 55 | Event.current.Use(); 56 | } 57 | 58 | // Timeline zoom slider 59 | Rect timelineZoomRect = new Rect(newTrackRect.xMax + GUI.skin.horizontalSlider.margin.left, -1, rect.width - newTrackRect.xMax - GUI.skin.horizontalSlider.margin.horizontal, rect.height); 60 | ed.timelineZoom = GUI.HorizontalSlider(timelineZoomRect, ed.timelineZoom, ed.timelineMin, CutsceneTimeline.timelineZoomMax); 61 | 62 | GUI.EndGroup(); 63 | } 64 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutscenePreview.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | class CutscenePreview : ICutsceneGUI 27 | { 28 | //readonly CutsceneEditor ed; 29 | 30 | public CutscenePreview (CutsceneEditor ed) 31 | { 32 | //this.ed = ed; 33 | } 34 | 35 | public void OnGUI (Rect rect) 36 | { 37 | //GUI.DrawTexture(rect, ); 38 | Camera cam = GameObject.Find("Some Cam").GetComponent(); 39 | EDebug.Log(cam.name); 40 | 41 | cam.targetTexture = new RenderTexture(128, 128, 32); 42 | cam.targetTexture.isPowerOfTwo = true; 43 | cam.targetTexture.Create(); 44 | 45 | 46 | 47 | GUI.DrawTexture(rect, cam.targetTexture); 48 | 49 | cam.targetTexture.Release(); 50 | cam.targetTexture = null; 51 | 52 | /*if (Event.current.type == EventType.repaint) { 53 | MovieTexture target = base.target as MovieTexture; 54 | float num = Mathf.Min(Mathf.Min((float)(r.width / ((float)target.width)), (float)(r.height / ((float)target.height))), 1f); 55 | Rect viewRect = new Rect(r.x, r.y, target.width * num, target.height * num); 56 | PreviewGUI.BeginScrollView(r, this.m_Pos, viewRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); 57 | GUI.DrawTexture(viewRect, target, ScaleMode.StretchToFill, false); 58 | this.m_Pos = PreviewGUI.EndScrollView(); 59 | if (target.isPlaying) { 60 | GUIView.current.Repaint(); 61 | } 62 | if (Application.isPlaying) { 63 | if (target.isPlaying) { 64 | Rect position = new Rect(r.x, r.y + 10f, r.width, 20f); 65 | EditorGUI.DropShadowLabel(position, "Can't pause preview when in play mode"); 66 | } else { 67 | Rect rect3 = new Rect(r.x, r.y + 10f, r.width, 20f); 68 | EditorGUI.DropShadowLabel(rect3, "Can't start preview when in play mode"); 69 | } 70 | } 71 | }*/ 72 | } 73 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneAddSubtitle.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | public class CutsceneAddSubtitle : ScriptableWizard { 27 | string dialog = ""; 28 | 29 | /// 30 | /// Creates a wizard for adding a new subtitle. 31 | /// 32 | [MenuItem("Component/Cutscene/Add Media/Subtitle")] 33 | public static void CreateWizard () 34 | { 35 | DisplayWizard("Add Subtitle", "Add"); 36 | } 37 | 38 | /// 39 | /// Validates the menu item. 40 | /// 41 | /// The item will be disabled if no cutscene is selected. 42 | [MenuItem("Component/Cutscene/Add Media/Subtitle", true)] 43 | static bool ValidateCreateWizard () 44 | { 45 | return CutsceneEditor.CutsceneSelected; 46 | } 47 | 48 | void OnGUI () 49 | { 50 | OnWizardUpdate(); 51 | 52 | EditorGUILayout.BeginHorizontal(); 53 | 54 | GUIContent itemLabel = new GUIContent("Dialog", EditorGUIUtility.ObjectContent(null, typeof(TextAsset)).image); 55 | GUILayout.Label(itemLabel, GUILayout.ExpandWidth(false)); 56 | dialog = EditorGUILayout.TextArea(dialog); 57 | 58 | EditorGUILayout.EndHorizontal(); 59 | 60 | GUI.enabled = isValid; 61 | EditorGUILayout.BeginHorizontal(); 62 | 63 | GUILayout.FlexibleSpace(); 64 | 65 | if (GUILayout.Button("Add", GUILayout.ExpandWidth(false))) { 66 | OnWizardCreate(); 67 | Close(); 68 | } 69 | 70 | EditorGUILayout.EndHorizontal(); 71 | GUI.enabled = true; 72 | } 73 | 74 | void OnWizardUpdate () 75 | { 76 | helpString = "Type in some dialog to add."; 77 | // Only valid if some text has been entered in the text field 78 | isValid = dialog != ""; 79 | } 80 | 81 | /// 82 | /// Adds the new subtitle to the cutscene. 83 | /// 84 | void OnWizardCreate () 85 | { 86 | Selection.activeGameObject.GetComponent().NewSubtitle(dialog); 87 | } 88 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutscenePlaybackControls.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | class CutscenePlaybackControls : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | const int buttonWidth = 18; 31 | 32 | readonly GUIContent inPointLabel = new GUIContent( 33 | EditorGUIUtility.LoadRequired("Cutscene Ed/playback_in.png") as Texture, 34 | "Go to in point." 35 | ); 36 | readonly GUIContent backLabel = new GUIContent( 37 | EditorGUIUtility.LoadRequired("Cutscene Ed/playback_back.png") as Texture, 38 | "Go back a second." 39 | ); 40 | /* 41 | readonly GUIContent playLabel = new GUIContent( 42 | EditorGUIUtility.LoadRequired("Cutscene Ed/playback_play.png") as Texture, 43 | "Play." 44 | ); 45 | */ 46 | readonly GUIContent forwardLabel = new GUIContent( 47 | EditorGUIUtility.LoadRequired("Cutscene Ed/playback_forward.png") as Texture, 48 | "Go forward a second." 49 | ); 50 | readonly GUIContent outPointLabel = new GUIContent( 51 | EditorGUIUtility.LoadRequired("Cutscene Ed/playback_out.png") as Texture, 52 | "Go to out point." 53 | ); 54 | 55 | public CutscenePlaybackControls (CutsceneEditor ed) 56 | { 57 | this.ed = ed; 58 | } 59 | 60 | /// 61 | /// Displays playback controls. 62 | /// 63 | /// The playback controls' Rect. 64 | public void OnGUI (Rect rect) 65 | { 66 | GUI.BeginGroup(rect, EditorStyles.toolbar); 67 | 68 | // In point 69 | Rect inPointRect = new Rect(6, 0, buttonWidth, rect.height); 70 | if (GUI.Button(inPointRect, inPointLabel, EditorStyles.toolbarButton)) { 71 | ed.scene.playhead = ed.scene.inPoint; 72 | } 73 | // Back 74 | Rect backRect = new Rect(inPointRect.xMax, 0, buttonWidth, rect.height); 75 | if (GUI.Button(backRect, backLabel, EditorStyles.toolbarButton)) { 76 | ed.scene.playhead -= CutsceneTimeline.scrubSmallJump; 77 | } 78 | /* Feature not implemented yet: 79 | // Play 80 | Rect playRect = new Rect(backRect.xMax, 0, buttonWidth, rect.height); 81 | if (GUI.Button(playRect, playLabel, EditorStyles.toolbarButton)) { 82 | EDebug.Log("Cutscene Editor: previewing scene (feature not implemented)"); 83 | };*/ 84 | // Forward 85 | Rect forwardRect = new Rect(backRect.xMax, 0, buttonWidth, rect.height); 86 | if (GUI.Button(forwardRect, forwardLabel, EditorStyles.toolbarButton)) { 87 | ed.scene.playhead += CutsceneTimeline.scrubSmallJump; 88 | } 89 | // Out point 90 | Rect outPointRect = new Rect(forwardRect.xMax, 0, buttonWidth, rect.height); 91 | if (GUI.Button(outPointRect, outPointLabel, EditorStyles.toolbarButton)) { 92 | ed.scene.playhead = ed.scene.outPoint; 93 | } 94 | 95 | Rect floatRect = new Rect(outPointRect.xMax + 4, 2, 50, rect.height); 96 | ed.scene.playhead = EditorGUI.FloatField(floatRect, ed.scene.playhead, EditorStyles.toolbarTextField); 97 | 98 | GUI.EndGroup(); 99 | } 100 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneAddAudio.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | class CutsceneAddAudio : ScriptableWizard 27 | { 28 | //GUISkin style = EditorGUIUtility.LoadRequired("Cutscene Ed/cutscene_editor_style.guiskin") as GUISkin; 29 | 30 | AudioClip[] audioClips; 31 | AudioClip selected; 32 | 33 | /// 34 | /// Creates a wizard for adding a new audio clip. 35 | /// 36 | [MenuItem("Component/Cutscene/Add Media/Audio")] 37 | public static void CreateWizard () 38 | { 39 | DisplayWizard("Add Audio", "Add"); 40 | } 41 | 42 | /// 43 | /// Validates the menu item. 44 | /// 45 | /// The item will be disabled if no cutscene is selected. 46 | [MenuItem("Component/Cutscene/Add Media/Audio", true)] 47 | static bool ValidateCreateWizard () 48 | { 49 | return CutsceneEditor.CutsceneSelected; 50 | } 51 | 52 | void OnGUI () 53 | { 54 | OnWizardUpdate(); 55 | 56 | // Display temporary workaround info 57 | GUILayout.Label("To add an audio clip from the Project view, drag and drop it to the audio pane. This is a temporary workaround and will hopefully be fixed soon."); 58 | 59 | // TODO Make LoadAllAssetsAtPath work 60 | /* 61 | audioClips = (AudioClip[])AssetDatabase.LoadAllAssetsAtPath("Assets"); 62 | 63 | Debug.Log("Objects length: " + audioClips.Length); 64 | 65 | EditorGUILayout.BeginVertical(style.GetStyle("List Container")); 66 | 67 | foreach (AudioClip aud in audioClips) { 68 | GUIStyle itemStyle = aud == selected ? style.GetStyle("Selected List Item") : GUIStyle.none; 69 | 70 | Rect rect = EditorGUILayout.BeginHorizontal(itemStyle); 71 | 72 | GUIContent itemLabel = new GUIContent(aud.name, EditorGUIUtility.ObjectContent(null, typeof(AudioClip)).image); 73 | GUILayout.Label(itemLabel); 74 | 75 | EditorGUILayout.EndHorizontal(); 76 | 77 | // Select when clicked 78 | if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { 79 | selected = aud; 80 | EditorGUIUtility.PingObject(aud); 81 | Event.current.Use(); 82 | } 83 | } 84 | 85 | EditorGUILayout.EndVertical(); 86 | 87 | GUI.enabled = isValid; 88 | EditorGUILayout.BeginHorizontal(); 89 | 90 | GUILayout.FlexibleSpace(); 91 | 92 | if (GUILayout.Button("Add", GUILayout.ExpandWidth(false))) { 93 | OnWizardCreate(); 94 | Close(); 95 | } 96 | 97 | EditorGUILayout.EndHorizontal(); 98 | GUI.enabled = true;*/ 99 | } 100 | 101 | void OnWizardUpdate () 102 | { 103 | helpString = "Choose an audio clip to add."; 104 | // Only valid if an audio clip has been selected 105 | isValid = selected != null; 106 | } 107 | 108 | /// 109 | /// Adds a new audio clip to the cutscene. 110 | /// 111 | void OnWizardCreate () 112 | { 113 | Selection.activeGameObject.GetComponent().NewAudio(selected); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneAddActor.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | 28 | class CutsceneAddActor : ScriptableWizard 29 | { 30 | GUISkin style = EditorGUIUtility.LoadRequired("Cutscene Ed/cutscene_editor_style.guiskin") as GUISkin; 31 | AnimationClip selected; 32 | GameObject selectedGO; 33 | 34 | /// 35 | /// Creates a wizard for adding a new actor. 36 | /// 37 | [MenuItem("Component/Cutscene/Add Media/Actor")] 38 | public static void CreateWizard () { 39 | DisplayWizard("Add Actor", "Add"); 40 | } 41 | 42 | /// 43 | /// Validates the menu item. 44 | /// 45 | /// The item will be disabled if no cutscene is selected. 46 | [MenuItem("Component/Cutscene/Add Media/Actor", true)] 47 | static bool ValidateCreateWizard () { 48 | return CutsceneEditor.CutsceneSelected; 49 | } 50 | 51 | void OnGUI () 52 | { 53 | OnWizardUpdate(); 54 | 55 | Object[] animations = FindObjectsOfType(typeof(Animation)); 56 | 57 | EditorGUILayout.BeginVertical(style.GetStyle("List Container")); 58 | 59 | foreach (Animation anim in animations) { 60 | GUILayout.Label(anim.gameObject.name, EditorStyles.largeLabel); 61 | 62 | foreach (AnimationClip clip in AnimationUtility.GetAnimationClips(anim)) { 63 | GUIStyle itemStyle = GUIStyle.none; 64 | if (clip == selected) { 65 | itemStyle = style.GetStyle("Selected List Item"); 66 | } 67 | 68 | Rect rect = EditorGUILayout.BeginHorizontal(itemStyle); 69 | 70 | GUIContent itemLabel = new GUIContent(clip.name, EditorGUIUtility.ObjectContent(null, typeof(Animation)).image); 71 | GUILayout.Label(itemLabel); 72 | 73 | EditorGUILayout.EndHorizontal(); 74 | 75 | // Select when clicked 76 | if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { 77 | selected = clip; 78 | selectedGO = anim.gameObject; 79 | EditorGUIUtility.PingObject(anim); 80 | Event.current.Use(); 81 | Repaint(); 82 | } 83 | } 84 | } 85 | 86 | EditorGUILayout.EndVertical(); 87 | 88 | GUI.enabled = isValid; 89 | EditorGUILayout.BeginHorizontal(); 90 | 91 | GUILayout.FlexibleSpace(); 92 | 93 | if (GUILayout.Button("Add", GUILayout.ExpandWidth(false))) { 94 | OnWizardCreate(); 95 | Close(); 96 | } 97 | 98 | EditorGUILayout.EndHorizontal(); 99 | GUI.enabled = true; 100 | } 101 | 102 | void OnWizardUpdate () 103 | { 104 | helpString = "Choose an animation to add."; 105 | // Only valid if an animation has been selected 106 | isValid = selected != null; 107 | } 108 | 109 | /// 110 | /// Adds the new actor to the cutscene. 111 | /// 112 | void OnWizardCreate () 113 | { 114 | Selection.activeGameObject.GetComponent().NewActor(selected, selectedGO); 115 | } 116 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneHotkeys.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | struct Hotkey 27 | { 28 | const string prefPrefix = "Cutscene Editor Hotkey "; 29 | 30 | string id; 31 | KeyCode defaultKey; 32 | bool assignable; 33 | 34 | public KeyCode key { 35 | get { 36 | if (assignable && EditorPrefs.HasKey(prefPrefix + id)) { 37 | return (KeyCode)EditorPrefs.GetInt(prefPrefix + id, (int)defaultKey); 38 | } else { 39 | return defaultKey; 40 | } 41 | } 42 | set { 43 | if (assignable) { 44 | EditorPrefs.SetInt(prefPrefix + id, (int)value); 45 | } else { 46 | EDebug.LogWarning("Cutscene Editor: Hotkey " + id + " cannot be reassigned"); 47 | } 48 | } 49 | } 50 | 51 | public Hotkey (string id, KeyCode defaultKey, bool assignable) 52 | { 53 | this.id = id; 54 | this.defaultKey = defaultKey; 55 | this.assignable = assignable; 56 | } 57 | 58 | /// 59 | /// Resets the key to its default value. 60 | /// 61 | public void Reset () 62 | { 63 | if (assignable) { 64 | key = defaultKey; 65 | } 66 | EDebug.Log("Cutscene Editor: Hotkey " + id + " reset to its default " + defaultKey); 67 | } 68 | } 69 | 70 | static class CutsceneHotkeys 71 | { 72 | // Assignable: 73 | public static Hotkey MoveResizeTool = new Hotkey("moveResizeTool", KeyCode.M, true); 74 | public static Hotkey ScissorsTool = new Hotkey("scissorsTool", KeyCode.S, true); 75 | public static Hotkey ZoomTool = new Hotkey("zoomTool", KeyCode.Z, true); 76 | public static Hotkey SetInPont = new Hotkey("setInPoint", KeyCode.I, true); 77 | public static Hotkey SetOutPoint = new Hotkey("setOutPoint", KeyCode.O, true); 78 | 79 | // Unassignable: 80 | public static readonly Hotkey SelectTrack1 = new Hotkey("selectTrack1", KeyCode.Alpha1, true); 81 | public static readonly Hotkey SelectTrack2 = new Hotkey("selectTrack2", KeyCode.Alpha2, true); 82 | public static readonly Hotkey SelectTrack3 = new Hotkey("selectTrack3", KeyCode.Alpha3, true); 83 | public static readonly Hotkey SelectTrack4 = new Hotkey("selectTrack4", KeyCode.Alpha4, true); 84 | public static readonly Hotkey SelectTrack5 = new Hotkey("selectTrack5", KeyCode.Alpha5, true); 85 | public static readonly Hotkey SelectTrack6 = new Hotkey("selectTrack6", KeyCode.Alpha6, true); 86 | public static readonly Hotkey SelectTrack7 = new Hotkey("selectTrack7", KeyCode.Alpha7, true); 87 | public static readonly Hotkey SelectTrack8 = new Hotkey("selectTrack8", KeyCode.Alpha8, true); 88 | public static readonly Hotkey SelectTrack9 = new Hotkey("selectTrack9", KeyCode.Alpha9, true); 89 | 90 | public static Hotkey[] assignable = new Hotkey[] { 91 | MoveResizeTool, 92 | ScissorsTool, 93 | ZoomTool, 94 | SetInPont, 95 | SetOutPoint 96 | }; 97 | 98 | /// 99 | /// Resets all the assignable hotkeys to their default values. 100 | /// 101 | public static void ResetAll () 102 | { 103 | foreach (Hotkey key in assignable) { 104 | key.Reset(); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneInspector.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | /// 27 | /// A custom inspector for a cutscene. 28 | /// 29 | [CustomEditor(typeof(Cutscene))] 30 | public class CutsceneInspector : Editor 31 | { 32 | Cutscene scene { 33 | get { return target as Cutscene; } 34 | } 35 | 36 | public override void OnInspectorGUI () 37 | { 38 | /* 39 | GUILayout.Label("Timing", EditorStyles.boldLabel); 40 | 41 | GUIContent durationLabel = new GUIContent("Duration", "The entire length of the cutscene."); 42 | scene.duration = EditorGUILayout.FloatField(durationLabel, scene.duration); 43 | 44 | // Instead of trying to clamp the values of the in and out points by slider leftValue and rightValue of the slider, we leave it to the Cutscene class 45 | GUIContent inPointLabel = new GUIContent("In", "The point at which the cutscene starts."); 46 | scene.inPoint = EditorGUILayout.Slider(inPointLabel, scene.inPoint, 0f, scene.duration); 47 | 48 | GUIContent outPointLabel = new GUIContent("Out", "The point at which the cutscene ends."); 49 | scene.outPoint = EditorGUILayout.Slider(outPointLabel, scene.outPoint, 0f, scene.duration); 50 | 51 | GUILayout.Label("Options", EditorStyles.boldLabel); 52 | 53 | GUIContent stopPlayerLabel = new GUIContent("Stop Player", "Deactivate the player when the scene starts."); 54 | scene.stopPlayer = EditorGUILayout.Toggle(stopPlayerLabel, scene.stopPlayer); 55 | 56 | // Disable the player reference box if the stop player toggle in unchecked 57 | GUI.enabled = scene.stopPlayer ? true : false; 58 | 59 | GUIContent playerLabel = new GUIContent("Player", "The player to deactivate."); 60 | scene.player = EditorGUILayout.ObjectField(playerLabel, scene.player, typeof(GameObject)) as GameObject; 61 | 62 | GUI.enabled = true; 63 | 64 | EditorGUILayout.Separator();*/ 65 | 66 | DrawDefaultInspector(); 67 | 68 | if (GUILayout.Button("Edit")) { 69 | CutsceneEditor.OpenEditor(); 70 | } 71 | 72 | if (GUI.changed) { 73 | EditorUtility.SetDirty(target); 74 | } 75 | } 76 | 77 | public void OnSceneGUI () 78 | { 79 | Handles.BeginGUI(); 80 | 81 | GUI.Box(new Rect(0, Screen.height - 300, 200, 30), "Cutscene Preview"); 82 | 83 | //Rect camRect = GUILayoutUtility.GetRect(100, 100); 84 | if (scene != null) { 85 | 86 | Camera cam = null; 87 | 88 | foreach (CutsceneTrack track in scene.tracks) { 89 | if (track.type == Cutscene.MediaType.Shots) { 90 | CutsceneClip clip = track.ContainsClipAtTime(scene.playhead); 91 | if (clip != null) { 92 | cam = ((CutsceneShot)clip.master).camera; 93 | break; 94 | } 95 | } 96 | } 97 | 98 | if (cam != null) { 99 | DrawCamera(new Rect(0, 0, 200, 200), cam); 100 | } 101 | } 102 | 103 | Handles.EndGUI(); 104 | } 105 | 106 | void DrawCamera (Rect previewRect, Camera camera) 107 | { 108 | if (Event.current.type == EventType.Repaint) { 109 | Rect cameraOriginalRect = camera.pixelRect; 110 | camera.pixelRect = previewRect; 111 | camera.Render(); 112 | camera.pixelRect = cameraOriginalRect; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneTrackInfo.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | class CutsceneTrackInfo : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | readonly GUIContent visibilityIcon = new GUIContent("", 31 | EditorGUIUtility.LoadRequired("Cutscene Ed/icon_eye.png") as Texture, 32 | "Toggle visibility." 33 | ); 34 | 35 | readonly GUIContent lockIcon = new GUIContent("", 36 | EditorGUIUtility.LoadRequired("Cutscene Ed/icon_lock.png") as Texture, 37 | "Toggle track lock." 38 | ); 39 | 40 | public CutsceneTrackInfo (CutsceneEditor ed) { 41 | this.ed = ed; 42 | } 43 | 44 | /// 45 | /// Displays the track info GUI. 46 | /// 47 | /// The track info's Rect. 48 | public void OnGUI (Rect rect) 49 | { 50 | ed.timelineScrollPos.y = EditorGUILayout.BeginScrollView( 51 | new Vector2(0, ed.timelineScrollPos.y), 52 | false, false, 53 | ed.style.horizontalScrollbar, 54 | ed.style.verticalScrollbar, 55 | GUIStyle.none, 56 | GUILayout.Width(CutsceneTimeline.trackInfoWidth), GUILayout.ExpandHeight(true)).y; 57 | 58 | foreach (CutsceneTrack track in ed.scene.tracks) { 59 | if (track == ed.selectedTrack) { 60 | GUI.SetNextControlName("track"); 61 | } 62 | 63 | Rect infoRect = EditorGUILayout.BeginHorizontal(ed.style.GetStyle("Track Info")); 64 | track.enabled = GUILayout.Toggle(track.enabled, visibilityIcon, EditorStyles.miniButtonLeft, GUILayout.ExpandWidth(false)); 65 | track.locked = GUILayout.Toggle(track.locked, lockIcon, EditorStyles.miniButtonRight, GUILayout.ExpandWidth(false)); 66 | 67 | GUILayout.Space(10); 68 | 69 | GUI.enabled = track.enabled; 70 | 71 | // Track name and icon 72 | GUIContent trackIcon = new GUIContent(ed.mediaIcons[(int)track.type]); 73 | GUILayout.Label(trackIcon, GUILayout.ExpandWidth(false)); 74 | // Set a minimum width to keep the label from becoming uneditable 75 | Rect trackNameRect = GUILayoutUtility.GetRect(new GUIContent(track.name), EditorStyles.miniLabel, GUILayout.ExpandWidth(false), GUILayout.MinWidth(20)); 76 | track.name = EditorGUI.TextField(trackNameRect, track.name, EditorStyles.miniLabel); 77 | 78 | GUI.enabled = true; 79 | EditorGUILayout.EndHorizontal(); 80 | 81 | if (track == ed.selectedTrack) { 82 | GUI.FocusControl("track"); 83 | } 84 | 85 | // Handle clicks 86 | Vector2 mousePos = Event.current.mousePosition; 87 | if (Event.current.type == EventType.MouseDown && infoRect.Contains(mousePos)) { 88 | switch (Event.current.button) { 89 | case 0: // Left mouse button 90 | ed.selectedTrack = track; 91 | break; 92 | 93 | case 1: // Right mouse button 94 | EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/CutsceneTrack/", new MenuCommand(track)); 95 | break; 96 | 97 | default: 98 | break; 99 | } 100 | 101 | Event.current.Use(); 102 | } 103 | } 104 | 105 | // Divider line 106 | Handles.color = Color.grey; 107 | Handles.DrawLine(new Vector3(67, 0), new Vector3(67, rect.yMax)); 108 | 109 | EditorGUILayout.EndScrollView(); 110 | } 111 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneClip.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using System; 25 | 26 | public class CutsceneClip : ScriptableObject 27 | { 28 | public CutsceneMedia master; 29 | 30 | public float timelineStart = 0f; 31 | public float inPoint = 0f; 32 | public float outPoint = 5f; // Default 5 seconds 33 | 34 | public float timelineEnd { 35 | get { return timelineStart + duration; } 36 | } 37 | 38 | float maxOutPoint { 39 | get { 40 | float max = Mathf.Infinity; 41 | 42 | if (master is CutsceneActor) { 43 | max = ((CutsceneActor)master).anim.length; 44 | } else if (master is CutsceneAudio) { 45 | max = ((CutsceneAudio)master).gameObject.audio.clip.length; 46 | } 47 | 48 | return max; 49 | } 50 | } 51 | 52 | public void SetTimelineStart (float value) 53 | { 54 | timelineStart = Mathf.Clamp(value, 0f, Mathf.Infinity); 55 | } 56 | 57 | public void SetInPoint (float value) 58 | { 59 | inPoint = Mathf.Clamp(value, 0f, outPoint); 60 | } 61 | 62 | public void SetOutPoint (float value) 63 | { 64 | outPoint = Mathf.Clamp(value, inPoint, maxOutPoint); 65 | } 66 | 67 | [HideInInspector] 68 | public bool setToDelete = false; // An ugly workaround used for deleting clips 69 | 70 | // Read only 71 | public float duration { 72 | get { return outPoint - inPoint; } 73 | } 74 | public string startFunction { 75 | get { 76 | // Determine which function to call based on the master object type 77 | if (master is CutsceneShot) { 78 | return "PlayShot"; 79 | } else if (master is CutsceneActor) { 80 | return "PlayActor"; 81 | } else if (master is CutsceneAudio) { 82 | return "PlayAudio"; 83 | } else if (master is CutsceneSubtitle) { 84 | return "PlaySubtitle"; 85 | } else { 86 | return "UnknownFunction"; 87 | } 88 | } 89 | } 90 | public Cutscene.MediaType type { 91 | get { 92 | if (master is CutsceneShot) { 93 | return Cutscene.MediaType.Shots; 94 | } else if (master is CutsceneActor) { 95 | return Cutscene.MediaType.Actors; 96 | } else if (master is CutsceneAudio) { 97 | return Cutscene.MediaType.Audio; 98 | } else { // master is CutsceneSubtitles 99 | return Cutscene.MediaType.Subtitles; 100 | } 101 | } 102 | } 103 | 104 | public CutsceneClip (CutsceneMedia master) 105 | { 106 | this.master = master; 107 | if (master is CutsceneSubtitle) { 108 | name = ((CutsceneSubtitle)master).dialog; 109 | } else { 110 | name = master.name; 111 | } 112 | 113 | if (maxOutPoint != Mathf.Infinity) { 114 | outPoint = maxOutPoint; 115 | } 116 | } 117 | 118 | /// 119 | /// Gets a clone of the current clip. 120 | /// 121 | /// The clip copy. 122 | public CutsceneClip GetCopy () 123 | { 124 | CutsceneClip copy = new CutsceneClip(master); 125 | copy.timelineStart = timelineStart; 126 | copy.SetInPoint(inPoint); 127 | copy.outPoint = outPoint; 128 | 129 | return copy; 130 | } 131 | 132 | /// 133 | /// Adds an effect to the clip. 134 | /// 135 | /// The transitions or filter. 136 | public void ApplyEffect (Type effect) 137 | { 138 | // Only add the effect if the master object is a camera shot 139 | if (master is CutsceneShot) { 140 | master.gameObject.AddComponent(effect); 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/CutsceneTrack.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using System.Collections.Generic; 25 | using System; 26 | 27 | public class CutsceneTrack : MonoBehaviour 28 | { 29 | public bool locked; 30 | [HideInInspector] 31 | public Cutscene.MediaType type = Cutscene.MediaType.Shots; 32 | public new string name = DefaultName(Cutscene.MediaType.Shots); 33 | public List clips = new List(); 34 | [HideInInspector] 35 | public int id = 0; 36 | 37 | public AnimationClip track { 38 | get { 39 | AnimationClip _track = new AnimationClip(); 40 | 41 | foreach (CutsceneClip clip in clips) { 42 | AnimationEvent start = new AnimationEvent(); 43 | start.time = clip.timelineStart; 44 | start.functionName = clip.startFunction; 45 | start.objectReferenceParameter = clip; 46 | _track.AddEvent(start); 47 | } 48 | 49 | return _track; 50 | } 51 | } 52 | 53 | public static string DefaultName (Cutscene.MediaType type) 54 | { 55 | switch (type) { 56 | case Cutscene.MediaType.Shots: 57 | return "Shots"; 58 | case Cutscene.MediaType.Actors: 59 | return "Actors"; 60 | case Cutscene.MediaType.Audio: 61 | return "Audio"; 62 | default: // Cutscene.MediaType.Subtitles 63 | return "Subtitles"; 64 | } 65 | } 66 | 67 | /// 68 | /// Checks to see if there's a clip at the given time, ignoring the given clip. 69 | /// 70 | /// The time to check for. 71 | /// The CutsceneClip that is at the given time. 72 | public CutsceneClip ContainsClipAtTime (float time, CutsceneClip ignoreClip) 73 | { 74 | CutsceneClip contains = ContainsClipAtTime(time); 75 | 76 | if (contains != null && contains != ignoreClip) { 77 | return contains; 78 | } else { 79 | return null; 80 | } 81 | } 82 | 83 | /// 84 | /// Checks to see if there's a clip at the given time. 85 | /// 86 | /// The time to check for. 87 | /// The CutsceneClip that is at the given time. 88 | public CutsceneClip ContainsClipAtTime (float time) 89 | { 90 | foreach (CutsceneClip clip in clips) { 91 | if (time >= clip.timelineStart && time <= clip.timelineStart + clip.duration) { 92 | return clip; 93 | } 94 | } 95 | 96 | // The timeline doesn't contain a clip at the specified time 97 | return null; 98 | } 99 | 100 | public float GetTimeOfPreviousSplit (float time) 101 | { 102 | float splitTime = -1f; 103 | 104 | foreach (CutsceneClip clip in clips) { 105 | if (clip.timelineEnd < time && clip.timelineEnd > splitTime) { 106 | splitTime = clip.timelineEnd; 107 | } else if (clip.timelineStart < time && clip.timelineStart > splitTime) { 108 | splitTime = clip.timelineStart; 109 | } 110 | } 111 | 112 | // If splitTime is still -1, just return the original time 113 | return splitTime == -1f ? time : splitTime; 114 | } 115 | 116 | public float GetTimeOfNextSplit (float time) 117 | { 118 | float splitTime = Mathf.Infinity; 119 | 120 | foreach (CutsceneClip clip in clips) { 121 | if (clip.timelineStart > time && clip.timelineStart < splitTime) { 122 | splitTime = clip.timelineStart; 123 | } else if (clip.timelineEnd > time && clip.timelineEnd < splitTime) { 124 | splitTime = clip.timelineEnd; 125 | } 126 | } 127 | 128 | // If splitTime is still infinity, just return the original time 129 | return splitTime == Mathf.Infinity ? time : splitTime; 130 | } 131 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneEffectsWindow.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | using System; 26 | using System.Collections.Generic; 27 | 28 | class CutsceneEffectsWindow : ICutsceneGUI 29 | { 30 | readonly CutsceneEditor ed; 31 | 32 | static Dictionary filters = new Dictionary 33 | { 34 | { CutsceneBlurFilter.name, typeof(CutsceneBlurFilter) }, 35 | { CutsceneInvertFilter.name, typeof(CutsceneInvertFilter) } 36 | }; 37 | 38 | static Dictionary transitions = new Dictionary {}; 39 | 40 | static readonly GUIContent filtersLabel = new GUIContent("Filters", "Full screen filters."); 41 | static readonly GUIContent transitionsLabel = new GUIContent("Transitions", "Camera transitions."); 42 | 43 | readonly GUIContent[] effectsTabs = CutsceneEditor.HasPro ? new GUIContent[] { filtersLabel, transitionsLabel } : new GUIContent[] { transitionsLabel }; 44 | Cutscene.EffectType currentEffectsTab = Cutscene.EffectType.Filters; 45 | 46 | Type selectedEffect; 47 | 48 | readonly Texture[] effectsIcons = { 49 | EditorGUIUtility.LoadRequired("Cutscene Ed/effects_filter.png") as Texture, 50 | EditorGUIUtility.LoadRequired("Cutscene Ed/effects_transition.png") as Texture 51 | }; 52 | 53 | public CutsceneEffectsWindow (CutsceneEditor ed) 54 | { 55 | this.ed = ed; 56 | } 57 | 58 | /// 59 | /// Displays the effects pane's GUI. 60 | /// 61 | /// The effects pane's Rect. 62 | public void OnGUI (Rect rect) 63 | { 64 | GUILayout.BeginArea(rect, ed.style.GetStyle("Pane")); 65 | 66 | EditorGUILayout.BeginHorizontal(); 67 | 68 | GUILayout.FlexibleSpace(); 69 | currentEffectsTab = (Cutscene.EffectType)GUILayout.Toolbar((int)currentEffectsTab, effectsTabs, GUILayout.Width(CutsceneEditor.PaneTabsWidth(effectsTabs.Length))); 70 | GUILayout.FlexibleSpace(); 71 | 72 | EditorGUILayout.EndHorizontal(); 73 | 74 | EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.ExpandWidth(true)); 75 | 76 | GUI.enabled = ed.selectedClip != null && ed.selectedClip.type == Cutscene.MediaType.Shots && selectedEffect != null; 77 | 78 | GUIContent applyLabel = new GUIContent("Apply", "Apply the selected effect to the selected clip."); 79 | if (GUILayout.Button(applyLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 80 | if (ed.selectedClip != null) { 81 | ed.selectedClip.ApplyEffect(selectedEffect); 82 | } 83 | } 84 | 85 | GUI.enabled = true; 86 | 87 | EditorGUILayout.EndHorizontal(); 88 | 89 | switch (currentEffectsTab) { 90 | case Cutscene.EffectType.Filters: 91 | foreach (KeyValuePair item in filters) { 92 | 93 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedEffect == item.Value ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 94 | 95 | GUIContent filterLabel = new GUIContent(item.Key, effectsIcons[(int)Cutscene.EffectType.Filters]); 96 | GUILayout.Label(filterLabel); 97 | 98 | EditorGUILayout.EndHorizontal(); 99 | 100 | // Handle clicks 101 | if (Event.current.type == EventType.MouseDown && itemRect.Contains(Event.current.mousePosition)) { 102 | selectedEffect = item.Value; 103 | Event.current.Use(); 104 | } 105 | } 106 | break; 107 | 108 | case Cutscene.EffectType.Transitions: 109 | foreach (KeyValuePair item in transitions) { 110 | 111 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedEffect == item.Value ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 112 | GUIContent transitionLabel = new GUIContent(item.Key, effectsIcons[(int)Cutscene.EffectType.Transitions]); 113 | GUILayout.Label(transitionLabel); 114 | 115 | EditorGUILayout.EndHorizontal(); 116 | 117 | // Handle clicks 118 | if (Event.current.type == EventType.MouseDown && itemRect.Contains(Event.current.mousePosition)) { 119 | selectedEffect = item.Value; 120 | Event.current.Use(); 121 | } 122 | } 123 | break; 124 | 125 | default: 126 | break; 127 | } 128 | 129 | GUILayout.EndArea(); 130 | } 131 | } -------------------------------------------------------------------------------- /Cutscene Ed/Effects/Filters/CutsceneBlurFilter.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | // Based off of BlurEffect.cs from the Pro Standard Assets 5 | 6 | public class CutsceneBlurFilter : CutsceneEffect { 7 | [HideInInspector] 8 | public static new string name = "Blur"; 9 | 10 | /// Blur iterations - larger number means more blur. 11 | public int iterations = 3; 12 | 13 | /// Blur spread for each iteration. Lower values 14 | /// give better looking blur, but require more iterations to 15 | /// get large blurs. Value is usually between 0.5 and 1.0. 16 | public float blurSpread = 0.6f; 17 | 18 | 19 | // -------------------------------------------------------- 20 | // The blur iteration shader. 21 | // Basically it just takes 4 texture samples and averages them. 22 | // By applying it repeatedly and spreading out sample locations 23 | // we get a Gaussian blur approximation. 24 | 25 | static string blurMatString = 26 | @"Shader ""BlurConeTap"" { 27 | SubShader { 28 | Pass { 29 | ZTest Always Cull Off ZWrite Off Fog { Mode Off } 30 | SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant alpha} 31 | SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} 32 | SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} 33 | SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} 34 | } 35 | } 36 | Fallback off 37 | }"; 38 | 39 | static Material m_Material = null; 40 | protected static Material material { 41 | get { 42 | if (m_Material == null) { 43 | m_Material = new Material( blurMatString ); 44 | m_Material.hideFlags = HideFlags.HideAndDontSave; 45 | m_Material.shader.hideFlags = HideFlags.HideAndDontSave; 46 | } 47 | return m_Material; 48 | } 49 | } 50 | 51 | protected void OnDisable() { 52 | if( m_Material ) { 53 | DestroyImmediate( m_Material.shader ); 54 | DestroyImmediate( m_Material ); 55 | } 56 | } 57 | 58 | // -------------------------------------------------------- 59 | 60 | protected void Start() { 61 | // Disable if we don't support image effects 62 | if (!SystemInfo.supportsImageEffects) { 63 | enabled = false; 64 | return; 65 | } 66 | // Disable if the shader can't run on the users graphics card 67 | if (!material.shader.isSupported) { 68 | enabled = false; 69 | return; 70 | } 71 | } 72 | 73 | // Performs one blur iteration. 74 | public void FourTapCone (RenderTexture source, RenderTexture dest, int iteration) { 75 | RenderTexture.active = dest; 76 | source.SetGlobalShaderProperty ("__RenderTex"); 77 | 78 | float offsetX = (.5F+iteration*blurSpread) / (float)source.width; 79 | float offsetY = (.5F+iteration*blurSpread) / (float)source.height; 80 | GL.PushMatrix (); 81 | GL.LoadOrtho (); 82 | 83 | for (int i = 0; i < material.passCount; i++) { 84 | material.SetPass (i); 85 | Render4TapQuad( dest, offsetX, offsetY ); 86 | } 87 | GL.PopMatrix (); 88 | } 89 | 90 | // Downsamples the texture to a quarter resolution. 91 | void DownSample4x (RenderTexture source, RenderTexture dest) { 92 | RenderTexture.active = dest; 93 | source.SetGlobalShaderProperty ("__RenderTex"); 94 | 95 | float offsetX = 1.0f / (float)source.width; 96 | float offsetY = 1.0f / (float)source.height; 97 | 98 | GL.PushMatrix (); 99 | GL.LoadOrtho (); 100 | for (int i = 0; i < material.passCount; i++) 101 | { 102 | material.SetPass (i); 103 | Render4TapQuad( dest, offsetX, offsetY ); 104 | } 105 | GL.PopMatrix (); 106 | } 107 | 108 | // Called by the camera to apply the image effect 109 | void OnRenderImage (RenderTexture source, RenderTexture destination) { 110 | RenderTexture buffer = RenderTexture.GetTemporary(source.width/4, source.height/4, 0); 111 | RenderTexture buffer2 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0); 112 | 113 | // Copy source to the 4x4 smaller texture. 114 | DownSample4x (source, buffer); 115 | 116 | // Blur the small texture 117 | bool oddEven = true; 118 | for(int i = 0; i < iterations; i++) 119 | { 120 | if( oddEven ) 121 | FourTapCone (buffer, buffer2, i); 122 | else 123 | FourTapCone (buffer2, buffer, i); 124 | oddEven = !oddEven; 125 | } 126 | if( oddEven ) 127 | ImageEffects.Blit(buffer, destination); 128 | else 129 | ImageEffects.Blit(buffer2, destination); 130 | 131 | RenderTexture.ReleaseTemporary(buffer); 132 | RenderTexture.ReleaseTemporary(buffer2); 133 | } 134 | 135 | static void Render4TapQuad( RenderTexture dest, float offsetX, float offsetY ) { 136 | GL.Begin( GL.QUADS ); 137 | 138 | // Direct3D needs interesting texel offsets! 139 | Vector2 off = Vector2.zero; 140 | if( dest != null ) 141 | off = dest.GetTexelOffset() * 0.75f; 142 | 143 | Set4TexCoords( off.x, off.y, offsetX, offsetY ); 144 | GL.Vertex3( 0,0, .1f ); 145 | 146 | Set4TexCoords( 1.0f + off.x, off.y, offsetX, offsetY ); 147 | GL.Vertex3( 1,0, .1f ); 148 | 149 | Set4TexCoords( 1.0f + off.x, 1.0f + off.y, offsetX, offsetY ); 150 | GL.Vertex3( 1,1,.1f ); 151 | 152 | Set4TexCoords( off.x, 1.0f + off.y, offsetX, offsetY ); 153 | GL.Vertex3( 0,1,.1f ); 154 | 155 | GL.End(); 156 | } 157 | 158 | static void Set4TexCoords( float x, float y, float offsetX, float offsetY ) { 159 | GL.MultiTexCoord2( 0, x - offsetX, y - offsetY ); 160 | GL.MultiTexCoord2( 1, x + offsetX, y - offsetY ); 161 | GL.MultiTexCoord2( 2, x + offsetX, y + offsetY ); 162 | GL.MultiTexCoord2( 3, x - offsetX, y + offsetY ); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneTimeline.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | public enum DragEvent { 27 | Move, 28 | ResizeLeft, 29 | ResizeRight 30 | } 31 | 32 | class CutsceneTimeline : ICutsceneGUI 33 | { 34 | readonly CutsceneEditor ed; 35 | 36 | public const int scrubLargeJump = 10; 37 | public const int scrubSmallJump = 1; 38 | 39 | readonly ICutsceneGUI navigation; 40 | readonly ICutsceneGUI tracksView; 41 | readonly ICutsceneGUI trackControls; 42 | readonly ICutsceneGUI trackInfo; 43 | 44 | public const float timelineZoomMin = 1f; 45 | public const float timelineZoomMax = 100f; 46 | public const float trackInfoWidth = 160f; 47 | 48 | public CutsceneTimeline (CutsceneEditor ed) 49 | { 50 | this.ed = ed; 51 | 52 | navigation = new CutsceneNavigation(ed); 53 | tracksView = new CutsceneTracksView(ed); 54 | trackControls = new CutsceneTrackControls(ed); 55 | trackInfo = new CutsceneTrackInfo(ed); 56 | } 57 | 58 | /// 59 | /// Displays the timeline's GUI. 60 | /// 61 | /// The timeline's Rect. 62 | public void OnGUI (Rect rect) 63 | { 64 | CutsceneGUILayout.Area(delegate { 65 | 66 | float rightColWidth = GUI.skin.verticalScrollbar.fixedWidth; 67 | float middleColWidth = rect.width - CutsceneTimeline.trackInfoWidth - rightColWidth; 68 | 69 | ed.timelineMin = CutsceneTimeline.timelineZoomMin * (middleColWidth / ed.scene.duration); 70 | ed.timelineZoom = Mathf.Clamp(ed.timelineZoom, ed.timelineMin, CutsceneTimeline.timelineZoomMax); 71 | 72 | // Navigation bar 73 | Rect navigationRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.toolbar, GUILayout.Width(rect.width)); 74 | navigation.OnGUI(navigationRect); 75 | 76 | // Begin Tracks 77 | CutsceneEditorGUILayout.Horizontal(delegate { 78 | 79 | // Track info 80 | //Rect trackInfoRect = GUILayoutUtility.GetRect(trackInfoWidth, rect.height - navigationRect.yMax - GUI.skin.horizontalScrollbar.fixedHeight); 81 | Rect trackInfoRect = new Rect(0, 0, CutsceneTimeline.trackInfoWidth, 9999); 82 | trackInfo.OnGUI(trackInfoRect); 83 | 84 | // Track controls 85 | float trackControlsHeight = GUI.skin.horizontalScrollbar.fixedHeight; 86 | Rect trackControlsRect = new Rect(0, rect.height - trackControlsHeight, CutsceneTimeline.trackInfoWidth, trackControlsHeight); 87 | trackControls.OnGUI(trackControlsRect); 88 | 89 | // Tracks 90 | Rect tracksRect = new Rect(trackInfoRect.xMax, navigationRect.yMax, middleColWidth + rightColWidth, rect.height - navigationRect.yMax); 91 | tracksView.OnGUI(tracksRect); 92 | 93 | }, GUILayout.Width(rect.width), GUILayout.ExpandHeight(true)); 94 | 95 | if (Event.current.type == EventType.KeyDown) { // Key presses 96 | ed.HandleKeyboardShortcuts(Event.current); 97 | } 98 | 99 | }, rect); 100 | } 101 | 102 | /// 103 | /// Moves the playhead. 104 | /// 105 | /// The position to move the playhead to. 106 | void MovePlayheadToPosition (float playheadPos) 107 | { 108 | ed.scene.playhead = playheadPos / ed.timelineZoom; 109 | } 110 | 111 | /// 112 | /// Splits a clip into two separate ones at the specified time. 113 | /// 114 | /// The time at which to split the clip. 115 | /// The track the clip is sitting on. 116 | /// The clip to split. 117 | /// The new clip. 118 | public static CutsceneClip SplitClipAtTime (float splitPoint, CutsceneTrack track, CutsceneClip clip) 119 | { 120 | CutsceneClip newClip = clip.GetCopy(); 121 | 122 | // Make sure the clip actually spans over the split point 123 | if (splitPoint < clip.timelineStart || splitPoint > clip.timelineStart + clip.duration) { 124 | EDebug.Log("Cutscene Editor: cannot split clip; clip does not contain the split point"); 125 | return null; 126 | } 127 | 128 | clip.SetOutPoint(clip.inPoint + (splitPoint - clip.timelineStart)); 129 | newClip.SetInPoint(clip.outPoint); 130 | newClip.SetTimelineStart(splitPoint); 131 | 132 | track.clips.Add(newClip); 133 | 134 | Event.current.Use(); 135 | EDebug.Log("Cutscene Editor: splitting clip at time " + splitPoint); 136 | 137 | return newClip; 138 | } 139 | } -------------------------------------------------------------------------------- /Cutscene Ed/Effects/ImageEffects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | /// Blending modes use by the ImageEffects.Blit functions. 4 | public enum BlendMode { 5 | Copy, 6 | Multiply, 7 | MultiplyDouble, 8 | Add, 9 | AddSmoooth, 10 | Blend 11 | } 12 | 13 | /// A Utility class for performing various image based rendering tasks. 14 | [AddComponentMenu("")] 15 | public class ImageEffects { 16 | static Material[] m_BlitMaterials = new Material[6]; 17 | 18 | static public Material GetBlitMaterial (BlendMode mode) { 19 | int index = (int)mode; 20 | 21 | if (m_BlitMaterials[index] != null) 22 | return m_BlitMaterials[index]; 23 | 24 | // Blit Copy Material 25 | m_BlitMaterials[0] = new Material ( 26 | "Shader \"BlitCopy\" {\n" + 27 | " SubShader { Pass {\n" + 28 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 29 | " SetTexture [__RenderTex] { combine texture}" + 30 | " }}\n" + 31 | "Fallback Off }" 32 | ); 33 | // Blit Multiply 34 | m_BlitMaterials[1] = new Material ( 35 | "Shader \"BlitMultiply\" {\n" + 36 | " SubShader { Pass {\n" + 37 | " Blend DstColor Zero\n" + 38 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 39 | " SetTexture [__RenderTex] { combine texture }" + 40 | " }}\n" + 41 | "Fallback Off }" 42 | ); 43 | // Blit Multiply 2X 44 | m_BlitMaterials[2] = new Material ( 45 | "Shader \"BlitMultiplyDouble\" {\n" + 46 | " SubShader { Pass {\n" + 47 | " Blend DstColor SrcColor\n" + 48 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 49 | " SetTexture [__RenderTex] { combine texture }" + 50 | " }}\n" + 51 | "Fallback Off }" 52 | ); 53 | // Blit Add 54 | m_BlitMaterials[3] = new Material ( 55 | "Shader \"BlitAdd\" {\n" + 56 | " SubShader { Pass {\n" + 57 | " Blend One One\n" + 58 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 59 | " SetTexture [__RenderTex] { combine texture }" + 60 | " }}\n" + 61 | "Fallback Off }" 62 | ); 63 | // Blit AddSmooth 64 | m_BlitMaterials[4] = new Material ( 65 | "Shader \"BlitAddSmooth\" {\n" + 66 | " SubShader { Pass {\n" + 67 | " Blend OneMinusDstColor One\n" + 68 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 69 | " SetTexture [__RenderTex] { combine texture }" + 70 | " }}\n" + 71 | "Fallback Off }" 72 | ); 73 | // Blit Blend 74 | m_BlitMaterials[5] = new Material ( 75 | "Shader \"BlitBlend\" {\n" + 76 | " SubShader { Pass {\n" + 77 | " Blend SrcAlpha OneMinusSrcAlpha\n" + 78 | " ZTest Always Cull Off ZWrite Off Fog { Mode Off }\n" + 79 | " SetTexture [__RenderTex] { combine texture }" + 80 | " }}\n" + 81 | "Fallback Off }" 82 | ); 83 | for( int i = 0; i < m_BlitMaterials.Length; ++i ) { 84 | m_BlitMaterials[i].hideFlags = HideFlags.HideAndDontSave; 85 | m_BlitMaterials[i].shader.hideFlags = HideFlags.HideAndDontSave; 86 | } 87 | return m_BlitMaterials[index]; 88 | } 89 | 90 | 91 | /// Copies one render texture onto another. 92 | /// This function copies /source/ onto /dest/, optionally using a custom blend mode. 93 | /// If /blendMode/ is left out, the default operation is simply to copy one texture on to another. 94 | /// This function will copy the whole source texture on to the whole destination texture. If the sizes differ, 95 | /// the image in the source texture will get stretched to fit. 96 | /// The source and destination textures cannot be the same. 97 | public static void Blit (RenderTexture source, RenderTexture dest, BlendMode blendMode) { 98 | Blit (source, new Rect (0,0,1,1), dest, new Rect (0,0,1,1), blendMode); 99 | } 100 | public static void Blit (RenderTexture source, RenderTexture dest) { 101 | Blit (source, dest, BlendMode.Copy); 102 | } 103 | 104 | /// Copies one render texture onto another. 105 | public static void Blit (RenderTexture source, Rect sourceRect, RenderTexture dest, Rect destRect, BlendMode blendMode) { 106 | // Make the destination texture the target for all rendering 107 | RenderTexture.active = dest; 108 | // Assign the source texture to a property from a shader 109 | source.SetGlobalShaderProperty ("__RenderTex"); 110 | // Set up the simple Matrix 111 | GL.PushMatrix (); 112 | GL.LoadOrtho (); 113 | Material blitMaterial = GetBlitMaterial(blendMode); 114 | for (int i = 0; i < blitMaterial.passCount; i++) { 115 | blitMaterial.SetPass (i); 116 | DrawQuad(); 117 | } 118 | GL.PopMatrix (); 119 | } 120 | 121 | 122 | public static void BlitWithMaterial (Material material, RenderTexture source, RenderTexture destination) { 123 | RenderTexture.active = destination; 124 | material.SetTexture("_MainTex", source); 125 | 126 | GL.PushMatrix (); 127 | GL.LoadOrtho (); 128 | 129 | for (int i = 0; i < material.passCount; i++) { 130 | material.SetPass (i); 131 | ImageEffects.DrawQuad(); 132 | } 133 | GL.PopMatrix (); 134 | } 135 | 136 | 137 | public static void RenderDistortion (Material material, RenderTexture source, RenderTexture destination, float angle, Vector2 center, Vector2 radius) { 138 | Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, angle), Vector3.one); 139 | 140 | material.SetMatrix("_RotationMatrix", rotationMatrix); 141 | material.SetVector("_CenterRadius", new Vector4(center.x,center.y,radius.x,radius.y) ); 142 | material.SetFloat("_Angle", angle * Mathf.Deg2Rad); 143 | 144 | ImageEffects.BlitWithMaterial( material, source, destination ); 145 | } 146 | 147 | 148 | public static void DrawQuad() { 149 | GL.Begin (GL.QUADS); 150 | GL.TexCoord2( 0.0f, 0.0f ); GL.Vertex3( 0.0f, 0.0f, 0.1f ); 151 | GL.TexCoord2( 1.0f, 0.0f ); GL.Vertex3( 1.0f, 0.0f, 0.1f ); 152 | GL.TexCoord2( 1.0f, 1.0f ); GL.Vertex3( 1.0f, 1.0f, 0.1f ); 153 | GL.TexCoord2( 0.0f, 1.0f ); GL.Vertex3( 0.0f, 1.0f, 0.1f ); 154 | GL.End(); 155 | } 156 | 157 | public static void DrawGrid (int xSize, int ySize) { 158 | GL.Begin (GL.QUADS); 159 | 160 | float xDelta = 1.0F / xSize; 161 | float yDelta = 1.0F / ySize; 162 | 163 | for (int y=0;y 50 | /// Displays the timecode bar with vertical lines indicating the time and the playhead. 51 | /// 52 | /// The timecode bar's Rect. 53 | public void OnGUI (Rect rect) 54 | { 55 | GUI.BeginGroup(rect); 56 | 57 | // Create a button that looks like a toolbar 58 | if (GUI.RepeatButton(new Rect(0, 0, rect.width, rect.height), GUIContent.none, EditorStyles.toolbar)) { 59 | float position = Event.current.mousePosition.x + ed.timelineScrollPos.x; 60 | ed.scene.playhead = position / ed.timelineZoom; 61 | 62 | // Show a visual notification of the position 63 | GUIContent notification = new GUIContent("Playhead " + ed.scene.playhead.ToString("N2")); 64 | ed.ShowNotification(notification); 65 | 66 | ed.Repaint(); 67 | //SceneView.RepaintAll(); 68 | } else { 69 | // TODO Investigate if attempting to remove the notification every frame like this is wasteful 70 | ed.RemoveNotification(); 71 | } 72 | 73 | DrawTicks(); 74 | DrawLabels(); 75 | DrawPlayhead(); 76 | DrawInOutPoints(); 77 | 78 | GUI.EndGroup(); 79 | } 80 | 81 | /// 82 | /// Draws vertical lines representing time increments. 83 | /// 84 | void DrawTicks () 85 | { 86 | Handles.color = tickColor; 87 | 88 | // Draw short ticks every second 89 | for (float i = 0; i < ed.scene.duration * ed.timelineZoom; i += ed.timelineZoom) { 90 | float xPos = i - ed.timelineScrollPos.x; 91 | Handles.DrawLine(new Vector3(xPos, 0, 0), new Vector3(xPos, shortTickHeight)); 92 | } 93 | 94 | // Draw tall ticks every ten seconds 95 | for (float i = 0; i < ed.scene.duration * ed.timelineZoom; i += ed.timelineZoom * 10) { 96 | float xPos = i - ed.timelineScrollPos.x; 97 | Handles.DrawLine(new Vector3(xPos, 0, 0), new Vector3(xPos, tallTickHeight)); 98 | } 99 | } 100 | 101 | /// 102 | /// Draws labels indicating the time. 103 | /// 104 | void DrawLabels () 105 | { 106 | for (float i = 0; i < 1000; i += 10) { 107 | float xPos = (i * ed.timelineZoom) - ed.timelineScrollPos.x; 108 | GUIContent label = new GUIContent(i + ""); 109 | Vector2 dimensions = EditorStyles.miniLabel.CalcSize(label); 110 | Rect labelRect = new Rect(xPos - (dimensions.x / 2), 2, dimensions.x, dimensions.y); 111 | GUI.Label(labelRect, label, EditorStyles.miniLabel); 112 | } 113 | } 114 | 115 | /// 116 | /// Draws the playhead. 117 | /// 118 | void DrawPlayhead () 119 | { 120 | // Draw position indicator 121 | float pos = (ed.scene.playhead * ed.timelineZoom) - ed.timelineScrollPos.x; 122 | GUI.DrawTexture(new Rect(pos - 4, 0, 8, 8), positionIndicatorIcon); 123 | 124 | Handles.color = Color.black; 125 | 126 | // Vertical line 127 | Vector3 top = new Vector3(pos, 0); 128 | Vector3 bottom = new Vector3(pos, EditorStyles.toolbar.fixedHeight); 129 | Handles.DrawLine(top, bottom); 130 | 131 | // Zoom indicator block 132 | Handles.color = playheadBlockColor; 133 | 134 | for (int i = 1; i <= ed.timelineZoom; i++) { 135 | float xPos = pos + i; 136 | top = new Vector3(xPos, 4); 137 | bottom = new Vector3(xPos, EditorStyles.toolbar.fixedHeight - 1); 138 | Handles.DrawLine(top, bottom); 139 | } 140 | } 141 | 142 | /// 143 | /// Draws the in and out points. 144 | /// 145 | void DrawInOutPoints () 146 | { 147 | Handles.color = inOutPointColour; 148 | 149 | DrawInPoint(); 150 | DrawOutPoint(); 151 | } 152 | 153 | /// 154 | /// Draws the in point. 155 | /// 156 | void DrawInPoint () 157 | { 158 | float pos = (ed.scene.inPoint * ed.timelineZoom) - ed.timelineScrollPos.x; 159 | 160 | // Icon 161 | Rect indicatorRect = new Rect(pos, 0, 4, 8); 162 | GUI.DrawTexture(indicatorRect, inPointIndicatorIcon); 163 | 164 | // Tooltip 165 | GUI.Label(indicatorRect, inTooltip); 166 | 167 | // Vertical line 168 | Vector3 top = new Vector3(pos, 0); 169 | Vector3 bottom = new Vector3(pos, EditorStyles.toolbar.fixedHeight); 170 | Handles.DrawLine(top, bottom); 171 | } 172 | 173 | /// 174 | /// Draws the out point. 175 | /// 176 | void DrawOutPoint () 177 | { 178 | float pos = (ed.scene.outPoint * ed.timelineZoom) - ed.timelineScrollPos.x; 179 | 180 | // Icon 181 | Rect indicatorRect = new Rect(pos - 4, 0, 4, 8); 182 | GUI.DrawTexture(indicatorRect, outPointIndicatorIcon); 183 | 184 | // Tooltip 185 | GUI.Label(indicatorRect, outTooltip); 186 | 187 | // Vertical line 188 | Vector3 top = new Vector3(pos, 0); 189 | Vector3 bottom = new Vector3(pos, EditorStyles.toolbar.fixedHeight); 190 | Handles.DrawLine(top, bottom); 191 | } 192 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneMediaWindow.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | 26 | class CutsceneMediaWindow : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | readonly GUIContent[] mediaTabs = { 31 | new GUIContent("Shots", "Camera views."), 32 | new GUIContent("Actors", "Animated game objects."), 33 | new GUIContent("Audio", "Dialog, background music and sound effects."), 34 | new GUIContent("Subtitles", "Textual versions of dialog.") 35 | }; 36 | 37 | Cutscene.MediaType currentMediaTab = Cutscene.MediaType.Shots; 38 | Vector2[] mediaScrollPos = new Vector2[4]; 39 | CutsceneMedia selectedMediaItem; 40 | 41 | readonly GUIContent newMediaLabel = new GUIContent(EditorGUIUtility.LoadRequired("Cutscene Ed/icon_add.png") as Texture, "Add new media."); 42 | readonly GUIContent insertMediaLabel = new GUIContent("Insert", "Insert the selected shot onto the timeline."); 43 | 44 | public CutsceneMediaWindow (CutsceneEditor ed) 45 | { 46 | this.ed = ed; 47 | } 48 | 49 | /// 50 | /// Displays the media pane's GUI. 51 | /// 52 | /// The media pane's Rect. 53 | public void OnGUI (Rect rect) 54 | { 55 | GUILayout.BeginArea(rect, ed.style.GetStyle("Pane")); 56 | 57 | EditorGUILayout.BeginHorizontal(); 58 | 59 | GUILayout.FlexibleSpace(); 60 | currentMediaTab = (Cutscene.MediaType)GUILayout.Toolbar((int)currentMediaTab, mediaTabs, GUILayout.Width(CutsceneEditor.PaneTabsWidth(mediaTabs.Length))); 61 | GUILayout.FlexibleSpace(); 62 | 63 | EditorGUILayout.EndHorizontal(); 64 | 65 | switch (currentMediaTab) { 66 | case Cutscene.MediaType.Shots: 67 | // If the selected item is in a different tab, set it to null 68 | if (selectedMediaItem != null && selectedMediaItem.type != currentMediaTab) { 69 | selectedMediaItem = null; 70 | } 71 | 72 | EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 73 | 74 | if (GUILayout.Button(newMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 75 | ed.scene.NewShot(); 76 | } 77 | 78 | GUI.enabled = IsMediaInsertable(); 79 | if (GUILayout.Button(insertMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 80 | Insert(selectedMediaItem); 81 | } 82 | GUI.enabled = true; 83 | 84 | GUILayout.FlexibleSpace(); 85 | 86 | EditorGUILayout.EndHorizontal(); 87 | 88 | mediaScrollPos[(int)currentMediaTab] = EditorGUILayout.BeginScrollView(mediaScrollPos[(int)currentMediaTab], GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 89 | foreach (CutsceneShot shot in ed.scene.shots) { 90 | 91 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedMediaItem == shot ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 92 | 93 | GUIContent itemLabel = new GUIContent(shot.name, ed.mediaIcons[(int)Cutscene.MediaType.Shots]); 94 | GUILayout.Label(itemLabel); 95 | 96 | EditorGUILayout.EndHorizontal(); 97 | 98 | HandleMediaItemClicks(shot, itemRect); 99 | } 100 | EditorGUILayout.EndScrollView(); 101 | 102 | break; 103 | 104 | case Cutscene.MediaType.Actors: 105 | // If the selected item is in a different tab, set it to null 106 | if (selectedMediaItem != null && selectedMediaItem.type != currentMediaTab) { 107 | selectedMediaItem = null; 108 | } 109 | 110 | EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 111 | 112 | if (GUILayout.Button(newMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 113 | CutsceneAddActor.CreateWizard(); 114 | } 115 | 116 | GUI.enabled = IsMediaInsertable(); 117 | if (GUILayout.Button(insertMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 118 | Insert(selectedMediaItem); 119 | } 120 | GUI.enabled = true; 121 | 122 | GUILayout.FlexibleSpace(); 123 | 124 | EditorGUILayout.EndHorizontal(); 125 | 126 | mediaScrollPos[(int)currentMediaTab] = EditorGUILayout.BeginScrollView(mediaScrollPos[(int)currentMediaTab], GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 127 | foreach (CutsceneActor actor in ed.scene.actors) { 128 | 129 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedMediaItem == actor ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 130 | 131 | GUIContent itemLabel = new GUIContent(actor.anim.name, ed.mediaIcons[(int)Cutscene.MediaType.Actors]); 132 | GUILayout.Label(itemLabel); 133 | 134 | EditorGUILayout.EndHorizontal(); 135 | 136 | HandleMediaItemClicks(actor, itemRect); 137 | } 138 | EditorGUILayout.EndScrollView(); 139 | 140 | break; 141 | 142 | case Cutscene.MediaType.Audio: 143 | // If the selected item is in a different tab, set it to null 144 | if (selectedMediaItem != null && selectedMediaItem.type != currentMediaTab) { 145 | selectedMediaItem = null; 146 | } 147 | 148 | EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 149 | 150 | if (GUILayout.Button(newMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 151 | // Show a wizard that will take care of adding audio 152 | CutsceneAddAudio.CreateWizard(); 153 | } 154 | 155 | GUI.enabled = IsMediaInsertable(); 156 | if (GUILayout.Button(insertMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 157 | Insert(selectedMediaItem); 158 | } 159 | GUI.enabled = true; 160 | 161 | GUILayout.FlexibleSpace(); 162 | 163 | EditorGUILayout.EndHorizontal(); 164 | 165 | mediaScrollPos[(int)currentMediaTab] = EditorGUILayout.BeginScrollView(mediaScrollPos[(int)currentMediaTab], GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 166 | foreach (CutsceneAudio aud in ed.scene.audioSources) { 167 | 168 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedMediaItem == aud ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 169 | 170 | GUIContent itemLabel = new GUIContent(aud.name, ed.mediaIcons[(int)Cutscene.MediaType.Audio]); 171 | GUILayout.Label(itemLabel); 172 | 173 | EditorGUILayout.EndHorizontal(); 174 | 175 | HandleMediaItemClicks(aud, itemRect); 176 | } 177 | EditorGUILayout.EndScrollView(); 178 | 179 | break; 180 | 181 | case Cutscene.MediaType.Subtitles: 182 | // If the selected item is in a different tab, set it to null 183 | if (selectedMediaItem != null && selectedMediaItem.type != currentMediaTab) { 184 | selectedMediaItem = null; 185 | } 186 | 187 | EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); 188 | 189 | if (GUILayout.Button(newMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 190 | // Show a wizard that will take care of adding audio 191 | CutsceneAddSubtitle.CreateWizard(); 192 | } 193 | 194 | GUI.enabled = IsMediaInsertable(); 195 | if (GUILayout.Button(insertMediaLabel, EditorStyles.toolbarButton, GUILayout.ExpandWidth(false))) { 196 | Insert(selectedMediaItem); 197 | } 198 | GUI.enabled = true; 199 | 200 | GUILayout.FlexibleSpace(); 201 | 202 | EditorGUILayout.EndHorizontal(); 203 | 204 | mediaScrollPos[(int)currentMediaTab] = EditorGUILayout.BeginScrollView(mediaScrollPos[(int)currentMediaTab], GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 205 | foreach (CutsceneSubtitle subtitle in ed.scene.subtitles) { 206 | 207 | Rect itemRect = EditorGUILayout.BeginHorizontal(selectedMediaItem == subtitle ? ed.style.GetStyle("Selected List Item") : GUIStyle.none); 208 | 209 | GUIContent itemLabel = new GUIContent(ed.mediaIcons[(int)Cutscene.MediaType.Subtitles]); 210 | GUILayout.Label(itemLabel, GUILayout.ExpandWidth(false)); 211 | subtitle.dialog = EditorGUILayout.TextField(subtitle.dialog); 212 | 213 | EditorGUILayout.EndHorizontal(); 214 | 215 | HandleMediaItemClicks(subtitle, itemRect); 216 | } 217 | EditorGUILayout.EndScrollView(); 218 | 219 | break; 220 | 221 | default: 222 | break; 223 | } 224 | GUILayout.EndArea(); 225 | 226 | // Handle drag and drop events 227 | if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) { 228 | // Show a copy icon on the drag 229 | DragAndDrop.visualMode = DragAndDropVisualMode.Copy; 230 | 231 | if (Event.current.type == EventType.DragPerform && rect.Contains(Event.current.mousePosition)) { 232 | DragAndDrop.AcceptDrag(); 233 | Object[] draggedObjects = DragAndDrop.objectReferences; 234 | 235 | // Create the appropriate cutscene objects for each dragged object 236 | foreach (Object obj in draggedObjects) { 237 | if (obj is AudioClip) { 238 | ed.scene.NewAudio((AudioClip)obj); 239 | } else if (obj is GameObject && ((GameObject)obj).animation != null) { 240 | GameObject go = obj as GameObject; 241 | foreach (AnimationClip anim in AnimationUtility.GetAnimationClips(go.animation)) { 242 | ed.scene.NewActor(anim, go); 243 | } 244 | 245 | } 246 | EDebug.Log("Cutscene Editor: dropping " + obj.GetType()); 247 | } 248 | } 249 | Event.current.Use(); 250 | } 251 | } 252 | 253 | /// 254 | /// Handles left and right mouse clicks of media items. 255 | /// 256 | /// The item clicked on. 257 | /// The item's Rect. 258 | void HandleMediaItemClicks (CutsceneMedia item, Rect rect) 259 | { 260 | Vector2 mousePos = Event.current.mousePosition; 261 | if (Event.current.type == EventType.MouseDown && rect.Contains(mousePos)) { 262 | switch (Event.current.button) { 263 | case 0: // Left click 264 | selectedMediaItem = item; 265 | EditorGUIUtility.PingObject(item); 266 | break; 267 | 268 | case 1: // Right click 269 | EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/CutsceneObject/", new MenuCommand(item)); 270 | break; 271 | 272 | default: 273 | break; 274 | } 275 | Event.current.Use(); 276 | } 277 | } 278 | 279 | /// 280 | /// Determines whether or not the currently selected cutscene object can be inserted into the selected timeline. 281 | /// 282 | /// True if the selected clip and the selected track are the same, false otherwise. 283 | bool IsMediaInsertable () 284 | { 285 | return selectedMediaItem != null && selectedMediaItem.type == ed.selectedTrack.type; 286 | } 287 | 288 | /// 289 | /// Inserts the given cutscene object into the timeline. 290 | /// 291 | /// The cutscene object to insert. 292 | void Insert (CutsceneMedia obj) 293 | { 294 | CutsceneClip newClip = new CutsceneClip(obj); 295 | newClip.timelineStart = ed.scene.playhead; 296 | 297 | // If there are no existing tracks, add a new one 298 | if (ed.scene.tracks.Length == 0) { 299 | ed.scene.AddTrack(newClip.type); 300 | } 301 | 302 | // Manage overlap with other clips 303 | CutsceneClip existingClip = ed.selectedTrack.ContainsClipAtTime(ed.scene.playhead); 304 | if (existingClip != null) { 305 | CutsceneClip middleOfSplit = CutsceneTimeline.SplitClipAtTime(ed.scene.playhead, ed.selectedTrack, existingClip); 306 | CutsceneTimeline.SplitClipAtTime(ed.scene.playhead + newClip.duration, ed.selectedTrack, middleOfSplit); 307 | ed.selectedTrack.clips.Remove(middleOfSplit); 308 | } 309 | 310 | ed.selectedTrack.clips.Add(newClip); 311 | 312 | EDebug.Log("Cutscene Editor: inserting " + newClip.name + " into timeline " + ed.selectedTrack + " at " + ed.scene.playhead); 313 | } 314 | } -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneTracksView.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using UnityEditor; 25 | 26 | class CutsceneTracksView : ICutsceneGUI 27 | { 28 | readonly CutsceneEditor ed; 29 | 30 | readonly Texture overlay = EditorGUIUtility.LoadRequired("Cutscene Ed/overlay.png") as Texture; 31 | readonly Color inOutPointColour = Color.cyan; 32 | 33 | public CutsceneTracksView (CutsceneEditor ed) 34 | { 35 | this.ed = ed; 36 | } 37 | 38 | /// 39 | /// Displays the tracks GUI. 40 | /// 41 | /// The tracks' Rect. 42 | public void OnGUI (Rect rect) 43 | { 44 | // Display background 45 | Rect background = new Rect(rect.x, rect.y, 46 | rect.width - GUI.skin.verticalScrollbar.fixedWidth, 47 | rect.height - GUI.skin.horizontalScrollbar.fixedHeight); 48 | GUI.BeginGroup(background, GUI.skin.GetStyle("AnimationCurveEditorBackground")); 49 | GUI.EndGroup(); 50 | 51 | float trackHeight = ed.style.GetStyle("Track").fixedHeight + ed.style.GetStyle("Track").margin.vertical; 52 | // TODO Make the track width take into account clips that are beyond the out point 53 | float tracksWidth = (ed.scene.outPoint + 10) * ed.timelineZoom; 54 | float tracksHeight = trackHeight * ed.scene.tracks.Length; 55 | 56 | Rect view = new Rect(0, 0, 57 | Mathf.Max(background.width + 1, tracksWidth), 58 | Mathf.Max(background.height + 1, tracksHeight)); 59 | 60 | ed.timelineScrollPos = GUI.BeginScrollView(rect, ed.timelineScrollPos, view, true, true); 61 | 62 | // Zoom clicks 63 | if (ed.currentTool == Tool.Zoom && Event.current.type == EventType.MouseDown) { 64 | if (Event.current.alt && Event.current.shift) { // Zoom out all the way 65 | ed.timelineZoom = CutsceneTimeline.timelineZoomMin; 66 | } else if (Event.current.shift) { // Zoom in all the way 67 | ed.timelineZoom = CutsceneTimeline.timelineZoomMax; 68 | } else if (Event.current.alt) { // Zoom out 69 | ed.timelineZoom -= 10; 70 | } else { // Zoom in 71 | ed.timelineZoom += 10; 72 | } 73 | 74 | Event.current.Use(); 75 | } 76 | 77 | // Draw track divider lines 78 | Handles.color = Color.grey; 79 | for (int i = 0; i < ed.scene.tracks.Length; i++) { 80 | Rect trackRect = new Rect(0, trackHeight * i, view.width, trackHeight); 81 | 82 | DisplayTrack(trackRect, ed.scene.tracks[i]); 83 | float yPos = (i + 1) * trackHeight - 1; 84 | Handles.DrawLine(new Vector3(0, yPos), new Vector3(view.width, yPos)); 85 | } 86 | 87 | // Draw overlay over in area 88 | Rect inOverlay = new Rect(0, 0, ed.scene.inPoint * ed.timelineZoom, view.height); 89 | GUI.DrawTexture(inOverlay, overlay); 90 | 91 | // Draw overlay over out area 92 | Rect outOverlay = new Rect(ed.scene.outPoint * ed.timelineZoom, 0, 0, view.height); 93 | outOverlay.width = view.width - outOverlay.x; 94 | GUI.DrawTexture(outOverlay, overlay); 95 | 96 | DrawLines(view); 97 | 98 | GUI.EndScrollView(); 99 | } 100 | 101 | /// 102 | /// Displays visual tracks upon which clips sit. 103 | /// 104 | void DisplayTrack (Rect rect, CutsceneTrack track) 105 | { 106 | GUI.enabled = track.enabled; 107 | 108 | for (int i = track.clips.Count - 1; i >= 0; i--) { 109 | DisplayClip(rect, track, track.clips[i]); 110 | } 111 | 112 | GUI.enabled = true; 113 | 114 | // Handle clicks 115 | Vector2 mousePos = Event.current.mousePosition; 116 | if (Event.current.type == EventType.MouseDown && rect.Contains(mousePos)) { 117 | switch (Event.current.button) { 118 | case 0: // Left mouse button 119 | ed.selectedTrack = track; 120 | ed.selectedClip = null; 121 | break; 122 | case 1: // Right mouse button 123 | EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/CutsceneTrack/", new MenuCommand(track)); 124 | Event.current.Use(); 125 | break; 126 | default: 127 | break; 128 | } 129 | 130 | Event.current.Use(); 131 | } 132 | } 133 | 134 | /// 135 | /// Displays a clip. 136 | /// 137 | /// The Rect of the track the clip sits on. 138 | /// The track the clip sits on. 139 | /// The clip to display. 140 | void DisplayClip (Rect trackRect, CutsceneTrack track, CutsceneClip clip) 141 | { 142 | const float trimWidth = 5f; 143 | 144 | GUIStyle clipStyle = ed.style.GetStyle("Selected Clip"); 145 | // Set the clip style if this isn't the selected clip (selected clips all share the same style) 146 | if (clip != ed.selectedClip) { 147 | switch (clip.type) { 148 | case Cutscene.MediaType.Shots: 149 | clipStyle = ed.style.GetStyle("Shot Clip"); 150 | break; 151 | case Cutscene.MediaType.Actors: 152 | clipStyle = ed.style.GetStyle("Actor Clip"); 153 | break; 154 | case Cutscene.MediaType.Audio: 155 | clipStyle = ed.style.GetStyle("Audio Clip"); 156 | break; 157 | default: // Cutscene.MediaType.Subtitles 158 | clipStyle = ed.style.GetStyle("Subtitle Clip"); 159 | break; 160 | } 161 | } 162 | 163 | Rect rect = new Rect((trackRect.x + clip.timelineStart) * ed.timelineZoom, trackRect.y + 1, clip.duration * ed.timelineZoom, clipStyle.fixedHeight); 164 | 165 | GUI.BeginGroup(rect, clipStyle); 166 | 167 | GUIContent clipLabel = new GUIContent(clip.name, "Clip: " + clip.name + "\nDuration: " + clip.duration + "\nTimeline start: " + clip.timelineStart + "\nTimeline end: " + (clip.timelineStart + clip.duration)); 168 | Rect clipLabelRect = new Rect(clipStyle.contentOffset.x, 0, rect.width - clipStyle.contentOffset.x, rect.height); 169 | GUI.Label(clipLabelRect, clipLabel); 170 | 171 | GUI.EndGroup(); 172 | 173 | // Handle mouse clicks 174 | Vector2 mousePos = Event.current.mousePosition; 175 | if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { 176 | switch (Event.current.button) { 177 | case 0: // Left mouse button 178 | ed.selectedClip = clip; 179 | ed.selectedTrack = track; 180 | break; 181 | case 1: // Right mouse button 182 | EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "CONTEXT/CutsceneClip/", new MenuCommand(clip)); 183 | Event.current.Use(); 184 | break; 185 | default: 186 | break; 187 | } 188 | } 189 | 190 | if (clip.setToDelete) { 191 | ed.selectedTrack.clips.Remove(clip); 192 | return; 193 | } 194 | 195 | // Don't allow actions to be performed on the clip if the track is disabled or locked 196 | if (!track.enabled || track.locked) { 197 | return; 198 | } 199 | 200 | switch (ed.currentTool) { 201 | case Tool.MoveResize: 202 | // Define edit areas, adding custom cursors when hovered over 203 | 204 | // Move 205 | Rect move = new Rect(rect.x + trimWidth, rect.y, rect.width - (2 * trimWidth), rect.height); 206 | EditorGUIUtility.AddCursorRect(move, MouseCursor.SlideArrow); 207 | 208 | // Resize left 209 | Rect resizeLeft = new Rect(rect.x, rect.y, trimWidth, rect.height); 210 | EditorGUIUtility.AddCursorRect(resizeLeft, MouseCursor.ResizeHorizontal); 211 | 212 | // Resize right 213 | Rect resizeRight = new Rect(rect.xMax - trimWidth, rect.y, trimWidth, rect.height); 214 | EditorGUIUtility.AddCursorRect(resizeRight, MouseCursor.ResizeHorizontal); 215 | 216 | if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { 217 | ed.dragClip = clip; 218 | 219 | // Move 220 | if (move.Contains(Event.current.mousePosition)) { 221 | ed.dragEvent = DragEvent.Move; 222 | EDebug.Log("Cutscene Editor: starting clip move"); 223 | // Resize left 224 | } else if (resizeLeft.Contains(Event.current.mousePosition)) { 225 | ed.dragEvent = DragEvent.ResizeLeft; 226 | EDebug.Log("Cutscene Editor: starting clip resize left"); 227 | // Resize right 228 | } else if (resizeRight.Contains(Event.current.mousePosition)) { 229 | ed.dragEvent = DragEvent.ResizeRight; 230 | EDebug.Log("Cutscene Editor: starting clip resize right"); 231 | } 232 | 233 | Event.current.Use(); 234 | } else if (Event.current.type == EventType.MouseDrag && ed.dragClip == clip) { 235 | float shift = Event.current.delta.x / ed.timelineZoom; 236 | 237 | switch (ed.dragEvent) { 238 | case DragEvent.Move: 239 | float newPos = clip.timelineStart + shift; 240 | 241 | // Left collisions 242 | CutsceneClip leftCollision = track.ContainsClipAtTime(newPos, clip); 243 | if (leftCollision != null) { 244 | newPos = leftCollision.timelineStart + leftCollision.duration; 245 | } 246 | 247 | // Right collisions 248 | CutsceneClip rightCollision = track.ContainsClipAtTime(newPos + clip.duration, clip); 249 | if (rightCollision != null) { 250 | newPos = rightCollision.timelineStart - clip.duration; 251 | } 252 | 253 | if (newPos + clip.duration > ed.scene.duration) { 254 | newPos = ed.scene.duration - clip.duration; 255 | } 256 | 257 | clip.SetTimelineStart(newPos); 258 | break; 259 | case DragEvent.ResizeLeft: 260 | clip.SetTimelineStart(clip.timelineStart + shift); 261 | clip.SetInPoint(clip.inPoint + shift); 262 | 263 | // TODO Improve collision behaviour 264 | CutsceneClip leftResizeCollision = track.ContainsClipAtTime(clip.timelineStart, clip); 265 | if (leftResizeCollision != null) { 266 | 267 | 268 | clip.SetTimelineStart(leftResizeCollision.timelineStart + leftResizeCollision.duration); 269 | } 270 | 271 | break; 272 | case DragEvent.ResizeRight: 273 | float newOut = clip.outPoint + shift; 274 | 275 | // Right collisions 276 | CutsceneClip rightResizeCollision = track.ContainsClipAtTime(clip.timelineStart + clip.duration + shift, clip); 277 | if (rightResizeCollision != null) { 278 | newOut = rightResizeCollision.timelineStart - clip.timelineStart + clip.inPoint; 279 | } 280 | 281 | clip.SetOutPoint(newOut); 282 | break; 283 | default: 284 | break; 285 | } 286 | 287 | Event.current.Use(); 288 | } else if (Event.current.type == EventType.MouseUp) { 289 | ed.dragClip = null; 290 | Event.current.Use(); 291 | } 292 | 293 | break; 294 | case Tool.Scissors: 295 | // TODO Switch to something better than the text cursor, if possible 296 | EditorGUIUtility.AddCursorRect(rect, MouseCursor.Text); 297 | 298 | if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { 299 | SplitClip(track, clip, Event.current.mousePosition); 300 | Event.current.Use(); 301 | } 302 | 303 | break; 304 | default: 305 | break; 306 | } 307 | } 308 | 309 | /// 310 | /// Splits a clip into two separate ones. 311 | /// 312 | /// The track the clip is sitting on. 313 | /// The clip to split. 314 | /// The position of the mouse when the split operation occurred. 315 | /// The new clip. 316 | CutsceneClip SplitClip (CutsceneTrack track, CutsceneClip clip, Vector2 mousePosition) 317 | { 318 | float splitPoint = mousePosition.x / ed.timelineZoom; 319 | return CutsceneTimeline.SplitClipAtTime(splitPoint, track, clip); 320 | } 321 | 322 | /// 323 | /// Draws the in, out, and playhead lines. 324 | /// 325 | /// The timeline's Rect. 326 | void DrawLines (Rect rect) 327 | { 328 | DrawPlayhead(rect); 329 | 330 | Handles.color = inOutPointColour; 331 | DrawInLine(rect); 332 | DrawOutLine(rect); 333 | } 334 | 335 | /// 336 | /// Draws the playhead over the timeline. 337 | /// 338 | /// The timeline's Rect. 339 | void DrawPlayhead (Rect rect) 340 | { 341 | Handles.color = Color.black; 342 | float pos = ed.scene.playhead * ed.timelineZoom; 343 | 344 | Vector3 timelineTop = new Vector3(pos, 0); 345 | Vector3 timelineBottom = new Vector3(pos, rect.yMax); 346 | Handles.DrawLine(timelineTop, timelineBottom); 347 | } 348 | 349 | /// 350 | /// Draws the in point line over the timeline. 351 | /// 352 | /// The timeline's Rect. 353 | void DrawInLine (Rect rect) 354 | { 355 | float pos = ed.scene.inPoint * ed.timelineZoom; 356 | 357 | Vector3 top = new Vector3(pos, 0); 358 | Vector3 bottom = new Vector3(pos, rect.yMax); 359 | Handles.DrawLine(top, bottom); 360 | } 361 | 362 | /// 363 | /// Draws the out point line over the timeline. 364 | /// 365 | /// The timeline's Rect. 366 | void DrawOutLine (Rect rect) 367 | { 368 | float pos = ed.scene.outPoint * ed.timelineZoom; 369 | 370 | Vector3 top = new Vector3(pos, 0); 371 | Vector3 bottom = new Vector3(pos, rect.yMax); 372 | Handles.DrawLine(top, bottom); 373 | } 374 | } -------------------------------------------------------------------------------- /Cutscene Ed/Scripts/Cutscene.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEngine; 24 | using System.Collections; 25 | using System.Collections.Generic; 26 | 27 | // Functions to be run when the cutscene starts and finishes 28 | public delegate void CutsceneStart(); 29 | public delegate void CutscenePause(); 30 | public delegate void CutsceneEnd(); 31 | 32 | [RequireComponent(typeof(Animation))] 33 | public class Cutscene : MonoBehaviour 34 | { 35 | public float duration = 30f; 36 | public float inPoint = 0f; 37 | public float outPoint = 30f; 38 | public bool stopPlayer = true; 39 | public GameObject player; 40 | 41 | public GUIStyle subtitleStyle; 42 | public Rect subtitlePosition = new Rect(0, 0, 400, 200); 43 | 44 | public CutsceneStart startFunction { get; set; } 45 | public CutscenePause pauseFunction { get; set; } 46 | public CutsceneEnd endFunction { get; set; } 47 | 48 | public enum MediaType { 49 | Shots, 50 | Actors, 51 | Audio, 52 | Subtitles 53 | } 54 | public enum EffectType { 55 | Filters, 56 | Transitions 57 | } 58 | public CutsceneTrack[] tracks { 59 | get { return GetComponentsInChildren(); } 60 | } 61 | public CutsceneShot[] shots { 62 | get { return GetComponentsInChildren(); } 63 | } 64 | public CutsceneActor[] actors { 65 | get { return GetComponentsInChildren(); } 66 | } 67 | public CutsceneAudio[] audioSources { 68 | get { return GetComponentsInChildren(); } 69 | } 70 | public CutsceneSubtitle[] subtitles { 71 | get { return GetComponentsInChildren(); } 72 | } 73 | 74 | CutsceneSubtitle currentSubtitle; 75 | 76 | public float playhead { 77 | get { return animation["master"].time; } 78 | set { animation["master"].time = Mathf.Clamp(value, 0f, duration); } 79 | } 80 | 81 | [HideInInspector] 82 | public AnimationClip masterClip; 83 | 84 | void Start () 85 | { 86 | SetupMasterAnimationClip(); 87 | SetupTrackAnimationClips(); 88 | 89 | DisableCameras(); 90 | DisableAudio(); 91 | } 92 | 93 | void OnGUI () 94 | { 95 | /// Displays the current subtitle if there is one 96 | if (currentSubtitle == null) { 97 | return; 98 | } 99 | 100 | GUI.BeginGroup(subtitlePosition, subtitleStyle); 101 | 102 | GUILayout.Label(currentSubtitle.dialog, subtitleStyle); 103 | 104 | GUI.EndGroup(); 105 | } 106 | 107 | /// 108 | /// Visually shows the cutscene in the scene view. 109 | /// 110 | void OnDrawGizmos () 111 | { 112 | Gizmos.DrawIcon(transform.position, "Cutscene.png"); 113 | } 114 | 115 | /// 116 | /// Sets the in and out points of the master animation clip. 117 | /// 118 | void SetupMasterAnimationClip () 119 | { 120 | animation.RemoveClip("master"); 121 | 122 | // Create a new event for when the scene starts 123 | AnimationEvent start = new AnimationEvent(); 124 | start.time = inPoint; 125 | start.functionName = "SceneStart"; 126 | masterClip.AddEvent(start); 127 | 128 | // Create a new event for when the scene finishes 129 | AnimationEvent finish = new AnimationEvent(); 130 | finish.time = outPoint; 131 | finish.functionName = "SceneFinish"; 132 | masterClip.AddEvent(finish); 133 | 134 | animation.AddClip(masterClip, "master"); 135 | animation["master"].time = inPoint; 136 | } 137 | 138 | /// 139 | /// Adds each track's animation clip to the main animation. 140 | /// 141 | void SetupTrackAnimationClips () 142 | { 143 | foreach (CutsceneTrack t in tracks) { 144 | if (t.enabled) { 145 | AnimationClip trackAnimationClip = t.track; 146 | string clipName = "track" + t.id; 147 | animation.AddClip(trackAnimationClip, clipName); 148 | animation[clipName].time = inPoint; 149 | } 150 | } 151 | } 152 | 153 | /// 154 | /// Turns off all child cameras so that they don't display before the cutscene starts. 155 | /// 156 | void DisableCameras () 157 | { 158 | Camera[] childCams = GetComponentsInChildren(); 159 | foreach (Camera cam in childCams) { 160 | cam.enabled = false; 161 | } 162 | } 163 | 164 | /// 165 | /// Turns off all child cameras except for the one specified. 166 | /// 167 | /// The camera to stay enabled. 168 | void DisableOtherCameras (Camera exemptCam) 169 | { 170 | Camera[] childCams = GetComponentsInChildren(); 171 | foreach (Camera cam in childCams) { 172 | if (cam != exemptCam) { 173 | cam.enabled = false; 174 | } 175 | } 176 | } 177 | 178 | /// 179 | /// Keeps all child audio sources from playing once the game starts. 180 | /// 181 | void DisableAudio () 182 | { 183 | AudioSource[] childAudio = GetComponentsInChildren(); 184 | foreach (AudioSource audio in childAudio) { 185 | audio.playOnAwake = false; 186 | } 187 | } 188 | 189 | /// 190 | /// Starts playing the cutscene. 191 | /// 192 | public void PlayCutscene () 193 | { 194 | // Set up and play the master animation 195 | animation["master"].layer = 0; 196 | animation.Play("master"); 197 | 198 | // Set up and play each individual track 199 | for (int i = 0; i < tracks.Length; i++) { 200 | if (tracks[i].enabled) { 201 | animation["track" + tracks[i].id].layer = i + 1; 202 | animation.Play("track" + tracks[i].id); 203 | } 204 | } 205 | } 206 | 207 | /// 208 | /// Pauses the cutscene. 209 | /// 210 | public void PauseCutscene () 211 | { 212 | pauseFunction(); 213 | // TODO actually pause the cutscene 214 | } 215 | 216 | /// 217 | /// Called when the scene starts. 218 | /// 219 | void SceneStart () 220 | { 221 | if (startFunction != null) { 222 | startFunction(); 223 | } 224 | 225 | // Stop the player from being able to move 226 | if (player != null && stopPlayer) { 227 | EDebug.Log("Cutscene: deactivating player"); 228 | player.SetActive(false); 229 | } 230 | 231 | DisableCameras(); 232 | currentSubtitle = null; 233 | 234 | EDebug.Log("Cutscene: scene started at " + animation["master"].time); 235 | } 236 | 237 | /// 238 | /// Called when the scene ends. 239 | /// 240 | void SceneFinish () 241 | { 242 | if (endFunction != null) { 243 | endFunction(); 244 | } 245 | 246 | // Allow the player to move again 247 | if (player != null) { 248 | EDebug.Log("Cutscene: activating player"); 249 | player.SetActive(true); 250 | } 251 | 252 | EDebug.Log("Cutscene: scene finished at " + animation["master"].time); 253 | } 254 | 255 | /// 256 | /// Shows the specified shot. 257 | /// 258 | /// The shot to show. 259 | void PlayShot (CutsceneClip clip) 260 | { 261 | Camera cam = ((CutsceneShot)clip.master).camera; 262 | cam.enabled = true; 263 | 264 | StartCoroutine(StopShot(cam, clip.duration)); 265 | 266 | EDebug.Log("Cutscene: showing camera " + clip.name + " at " + animation["master"].time); 267 | } 268 | 269 | /// 270 | /// Stops the shot from playing at its out point. 271 | /// 272 | /// The shot to stop. 273 | /// The time at which to stop the shot. 274 | IEnumerator StopShot (Camera cam, float duration) 275 | { 276 | yield return new WaitForSeconds(duration); 277 | cam.enabled = false; 278 | EDebug.Log("Cutscene: stopping shot at " + animation["master"].time); 279 | } 280 | 281 | /// 282 | /// Plays the specified actor. 283 | /// 284 | /// The actor to play. 285 | void PlayActor (CutsceneClip clip) 286 | { 287 | CutsceneActor actor = ((CutsceneActor)clip.master); 288 | AnimationClip anim = actor.anim; 289 | GameObject go = ((CutsceneActor)clip.master).go; 290 | 291 | go.animation[anim.name].time = clip.inPoint; 292 | 293 | go.animation.Play(anim.name); 294 | StartCoroutine(StopActor(actor, clip.duration)); 295 | 296 | EDebug.Log("Cutscene: showing actor " + clip.name + " at " + animation["master"].time); 297 | } 298 | 299 | /// 300 | /// Stops the actor from playing at its out point. 301 | /// 302 | /// The actor to stop. 303 | /// The time at which to stop the actor. 304 | IEnumerator StopActor (CutsceneActor actor, float duration) 305 | { 306 | yield return new WaitForSeconds(duration); 307 | actor.go.animation.Stop(actor.anim.name); 308 | EDebug.Log("Cutscene: stopping actor at " + animation["master"].time); 309 | } 310 | 311 | /// 312 | /// Plays the specified audio. 313 | /// 314 | /// The audio to play. 315 | void PlayAudio (CutsceneClip clip) 316 | { 317 | AudioSource aud = ((CutsceneAudio)clip.master).audio; 318 | aud.Play(); 319 | aud.time = clip.inPoint; // Set the point at which the clip plays 320 | StartCoroutine(StopAudio(aud, clip.duration)); // Set the point at which the clip stops 321 | 322 | EDebug.Log("Playing audio " + clip.name + " at " + animation["master"].time); 323 | } 324 | 325 | /// 326 | /// Stops the audio from playing at its out point. 327 | /// 328 | /// The audio source to stop. 329 | /// The time at which to stop the audio. 330 | IEnumerator StopAudio (AudioSource aud, float duration) 331 | { 332 | yield return new WaitForSeconds(duration); 333 | aud.Stop(); 334 | } 335 | 336 | /// 337 | /// Displays the specified subtitle. 338 | /// 339 | /// The subtitle to display. 340 | void PlaySubtitle (CutsceneClip clip) 341 | { 342 | currentSubtitle = (CutsceneSubtitle)clip.master; 343 | EDebug.Log("Displaying subtitle " + clip.name + " at " + animation["master"].time); 344 | 345 | StartCoroutine(StopSubtitle(clip.duration)); 346 | } 347 | 348 | /// 349 | /// Stops the subtitle from displaying at its out point. 350 | /// 351 | /// The time at which to stop the audio. 352 | IEnumerator StopSubtitle (float duration) 353 | { 354 | yield return new WaitForSeconds(duration); 355 | currentSubtitle = null; 356 | } 357 | 358 | /// 359 | /// Stops all subtitles from displaying by setting the current subtitle to null. 360 | /// 361 | void StopSubtitle () 362 | { 363 | currentSubtitle = null; 364 | } 365 | 366 | /// 367 | /// Called when the clip type is unknown. 368 | /// 369 | /// For debugging only; ideally this will never be called. 370 | void UnknownFunction (CutsceneClip clip) 371 | { 372 | EDebug.Log("Cutscene: unknown function call from clip " + clip.name); 373 | } 374 | 375 | /// 376 | /// Creates a new CutsceneShot object and attaches it to a new game object as a child of the Shots game object. 377 | /// 378 | /// The new CutsceneShot object. 379 | public CutsceneShot NewShot () 380 | { 381 | GameObject shot = new GameObject("Camera", typeof(Camera), typeof(CutsceneShot)); 382 | // Keep the camera from displaying before it's placed on the timeline 383 | shot.camera.enabled = false; 384 | // Set the parent of the new shot to the Shots object 385 | shot.transform.parent = transform.Find("Shots"); 386 | 387 | EDebug.Log("Cutscene Editor: added new shot"); 388 | return shot.GetComponent(); 389 | } 390 | 391 | /// 392 | /// Creates a new CutsceneActor object and attaches it to a new game object as a child of the Shots game object. 393 | /// 394 | /// The new CutsceneActor object. 395 | public CutsceneActor NewActor (AnimationClip anim, GameObject go) 396 | { 397 | CutsceneActor actor = GameObject.Find("Actors").AddComponent(); 398 | actor.name = anim.name; 399 | actor.anim = anim; 400 | actor.go = go; 401 | 402 | EDebug.Log("Cutscene Editor: adding new actor"); 403 | return actor; 404 | } 405 | 406 | /// 407 | /// Creates a new CutsceneAudio object and attaches it to a new game object as a child of the Audio game object. 408 | /// 409 | /// The audio clip to be attached the CutsceneAudio object. 410 | /// The new CutsceneAudio object. 411 | public CutsceneAudio NewAudio (AudioClip clip) 412 | { 413 | GameObject aud = new GameObject(clip.name, typeof(AudioSource), typeof(CutsceneAudio)); 414 | aud.audio.clip = clip; 415 | // Keep the audio from playing when the game starts 416 | aud.audio.playOnAwake = false; 417 | // Set the parent of the new audio to the "Audio" object 418 | aud.transform.parent = transform.Find("Audio"); 419 | 420 | EDebug.Log("Cutscene Editor: added new audio"); 421 | return aud.GetComponent(); 422 | } 423 | 424 | /// 425 | /// Creates a new CutsceneSubtitle object and attaches it to the Subtitles game object. 426 | /// 427 | /// The dialog to be displayed. 428 | /// The new CutsceneSubtitle object. 429 | public CutsceneSubtitle NewSubtitle (string dialog) 430 | { 431 | CutsceneSubtitle subtitle = GameObject.Find("Subtitles").AddComponent(); 432 | subtitle.dialog = dialog; 433 | 434 | EDebug.Log("Cutscene Editor: added new subtitle"); 435 | return subtitle; 436 | } 437 | 438 | /// 439 | /// Attaches a new track component to the cutscene. 440 | /// 441 | /// The new cutscene track. 442 | public CutsceneTrack AddTrack (Cutscene.MediaType type) 443 | { 444 | int id = 0; 445 | // Ensure the new track has a unique ID 446 | foreach (CutsceneTrack t in tracks) { 447 | if (id == t.id) { 448 | id++; 449 | } else { 450 | break; 451 | } 452 | } 453 | 454 | CutsceneTrack track = gameObject.AddComponent(); 455 | track.id = id; 456 | track.type = type; 457 | track.name = CutsceneTrack.DefaultName(type); 458 | 459 | EDebug.Log("Cutscene Editor: added new track of type " + type); 460 | return track; 461 | } 462 | } 463 | -------------------------------------------------------------------------------- /Cutscene Ed/Editor/CutsceneEditor.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2010 Matthew Miner 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | using UnityEditor; 24 | using UnityEngine; 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | 28 | /// 29 | /// The Cutscene Editor, where tracks and clips can be managed in a fashion similar to non-linear video editors. 30 | /// 31 | public class CutsceneEditor : EditorWindow 32 | { 33 | public static readonly System.Version version = new System.Version(0, 2); 34 | 35 | public Cutscene scene { 36 | get { 37 | Object[] scenes = Selection.GetFiltered(typeof(Cutscene), SelectionMode.TopLevel); 38 | 39 | if (scenes.Length == 0) { 40 | return null; 41 | } 42 | 43 | return scenes[0] as Cutscene; 44 | } 45 | } 46 | 47 | public GUISkin style { get; private set; } 48 | 49 | //ICutsceneGUI options; 50 | ICutsceneGUI media; 51 | ICutsceneGUI effects; 52 | ICutsceneGUI tools; 53 | ICutsceneGUI timeline; 54 | 55 | public static bool CutsceneSelected { 56 | get { return Selection.GetFiltered(typeof(Cutscene), SelectionMode.TopLevel).Length > 0; } 57 | } 58 | 59 | public static bool HasPro = SystemInfo.supportsImageEffects; 60 | 61 | // Icons: 62 | 63 | public readonly Texture[] mediaIcons = { 64 | EditorGUIUtility.LoadRequired("Cutscene Ed/media_shot.png") as Texture, 65 | EditorGUIUtility.LoadRequired("Cutscene Ed/media_actor.png") as Texture, 66 | EditorGUIUtility.LoadRequired("Cutscene Ed/media_audio.png") as Texture, 67 | EditorGUIUtility.LoadRequired("Cutscene Ed/media_subtitle.png") as Texture 68 | }; 69 | 70 | // Timeline: 71 | 72 | public Tool currentTool = Tool.MoveResize; 73 | 74 | public Vector2 timelineScrollPos; 75 | 76 | public float timelineMin { get; set; } 77 | 78 | float _timelineZoom = CutsceneTimeline.timelineZoomMin; 79 | public float timelineZoom { 80 | get { return _timelineZoom; } 81 | set { _timelineZoom = Mathf.Clamp(value, CutsceneTimeline.timelineZoomMin, CutsceneTimeline.timelineZoomMax); } 82 | } 83 | 84 | CutsceneTrack _selectedTrack; 85 | public CutsceneTrack selectedTrack { 86 | get { 87 | if (_selectedTrack == null) { 88 | 89 | // If there are no tracks, add a new one 90 | if (scene.tracks.Length == 0) { 91 | scene.AddTrack(Cutscene.MediaType.Shots); 92 | } 93 | 94 | _selectedTrack = scene.tracks[0]; 95 | } 96 | 97 | return _selectedTrack; 98 | } 99 | set { _selectedTrack = value; } 100 | } 101 | 102 | public CutsceneClip selectedClip; 103 | public DragEvent dragEvent = DragEvent.Move; 104 | public CutsceneClip dragClip; 105 | 106 | // Menu items: 107 | 108 | /// 109 | /// Adds "Cutscene Editor" to the Window menu. 110 | /// 111 | [MenuItem("Window/Cutscene Editor")] 112 | public static void OpenEditor () 113 | { 114 | // Get existing open window or if none, make a new one 115 | GetWindow(false, "Cutscene Editor").Show(); 116 | } 117 | 118 | /// 119 | /// Validates the Cutscene Editor menu item. 120 | /// 121 | /// The item will be disabled if no cutscene is selected. 122 | [MenuItem("Window/Cutscene Editor", true)] 123 | static bool ValidateOpenEditor () 124 | { 125 | return CutsceneSelected; 126 | } 127 | 128 | /// 129 | /// Adds the option to create a cutscene from the GameObject > Create Other menu. 130 | /// 131 | /// The new cutscene. 132 | [MenuItem("GameObject/Create Other/Cutscene")] 133 | static void CreateCutscene () 134 | { 135 | // Create the new cutscene game object 136 | GameObject newSceneGO = new GameObject("Cutscene", typeof(Cutscene)); 137 | Cutscene newScene = newSceneGO.GetComponent(); 138 | 139 | // Add some tracks to get the user started 140 | newScene.AddTrack(Cutscene.MediaType.Shots); 141 | newScene.AddTrack(Cutscene.MediaType.Actors); 142 | newScene.AddTrack(Cutscene.MediaType.Audio); 143 | newScene.AddTrack(Cutscene.MediaType.Subtitles); 144 | 145 | // Create the cutscene's media game objects 146 | GameObject shots = new GameObject("Shots"); 147 | GameObject actors = new GameObject("Actors"); 148 | GameObject audio = new GameObject("Audio"); 149 | GameObject subtitles = new GameObject("Subtitles"); 150 | 151 | // Make the media game objects a child of the cutscene 152 | shots.transform.parent = newScene.transform; 153 | actors.transform.parent = newScene.transform; 154 | audio.transform.parent = newScene.transform; 155 | subtitles.transform.parent = newScene.transform; 156 | 157 | // Create the master animation clip 158 | AnimationClip masterClip = new AnimationClip(); 159 | newScene.masterClip = masterClip; 160 | newScene.animation.AddClip(masterClip, "master"); 161 | 162 | newScene.animation.playAutomatically = false; 163 | newScene.animation.wrapMode = WrapMode.Once; 164 | 165 | EDebug.Log("Cutscene Editor: created a new cutscene"); 166 | } 167 | 168 | /// 169 | /// Adds the option to create a cutscene trigger to the GameObject > Create Other menu. 170 | /// 171 | /// The trigger's collider. 172 | [MenuItem("GameObject/Create Other/Cutscene Trigger")] 173 | static Collider CreateCutsceneTrigger () 174 | { 175 | // Create the new cutscene trigger game object 176 | GameObject triggerGO = new GameObject("Cutscene Trigger", typeof(BoxCollider), typeof(CutsceneTrigger)); 177 | triggerGO.collider.isTrigger = true; 178 | return triggerGO.collider; 179 | } 180 | 181 | /// 182 | /// Adds the option to create a new shot track in the Component > Cutscene > Track menu. 183 | /// 184 | [MenuItem("Component/Cutscene/Track/Shot")] 185 | static void CreateShotTrack () 186 | { 187 | Selection.activeGameObject.GetComponent().AddTrack(Cutscene.MediaType.Shots); 188 | } 189 | 190 | /// 191 | /// Validates the Shot menu item. 192 | /// 193 | /// The item will be disabled if no cutscene is selected. 194 | [MenuItem("Component/Cutscene/Track/Shot", true)] 195 | static bool ValidateCreateShotTrack () 196 | { 197 | return CutsceneSelected; 198 | } 199 | 200 | /// 201 | /// Adds the option to create a new actor track in the Component > Cutscene > Track menu. 202 | /// 203 | [MenuItem("Component/Cutscene/Track/Actor")] 204 | static void CreateActorTrack () 205 | { 206 | Selection.activeGameObject.GetComponent().AddTrack(Cutscene.MediaType.Actors); 207 | } 208 | 209 | /// 210 | /// Validates the Actor menu item. 211 | /// 212 | /// The item will be disabled if no cutscene is selected. 213 | [MenuItem("Component/Cutscene/Track/Actor", true)] 214 | static bool ValidateCreateActorTrack () 215 | { 216 | return CutsceneSelected; 217 | } 218 | 219 | /// 220 | /// Adds the option to create a new audio track in the Component > Cutscene > Track menu. 221 | /// 222 | [MenuItem("Component/Cutscene/Track/Audio")] 223 | static void CreateAudioTrack () 224 | { 225 | Selection.activeGameObject.GetComponent().AddTrack(Cutscene.MediaType.Audio); 226 | } 227 | 228 | /// 229 | /// Validates the Audio menu item. 230 | /// 231 | /// The item will be disabled if no cutscene is selected. 232 | [MenuItem("Component/Cutscene/Track/Audio", true)] 233 | static bool ValidateCreateAudioTrack () 234 | { 235 | return CutsceneSelected; 236 | } 237 | 238 | /// 239 | /// Adds the option to create a new subtitle track in the Component > Cutscene > Track menu. 240 | /// 241 | [MenuItem("Component/Cutscene/Track/Subtitle")] 242 | static void CreateSubtitleTrack () 243 | { 244 | Selection.activeGameObject.GetComponent().AddTrack(Cutscene.MediaType.Subtitles); 245 | } 246 | 247 | /// 248 | /// Validates the Subtitle menu item. 249 | /// 250 | /// The item will be disabled if no cutscene is selected. 251 | [MenuItem("Component/Cutscene/Track/Subtitle", true)] 252 | static bool ValidateCreateSubtitleTrack () 253 | { 254 | return CutsceneSelected; 255 | } 256 | 257 | void OnEnable () 258 | { 259 | style = EditorGUIUtility.LoadRequired("Cutscene Ed/cutscene_editor_style.guiskin") as GUISkin; 260 | 261 | if (style == null) { 262 | Debug.LogError("GUISkin for Cutscene Editor missing"); 263 | return; 264 | } 265 | 266 | //options = new CutsceneOptions(this); 267 | media = new CutsceneMediaWindow(this); 268 | effects = new CutsceneEffectsWindow(this); 269 | tools = new CutsceneTools(this); 270 | timeline = new CutsceneTimeline(this); 271 | } 272 | 273 | /// 274 | /// Displays the editor GUI. 275 | /// 276 | void OnGUI () 277 | { 278 | if (style == null) { 279 | style = EditorGUIUtility.LoadRequired("Cutscene Ed/cutscene_editor_style.guiskin") as GUISkin; 280 | } 281 | 282 | // If no cutscene is selected, present the user with the option to create one 283 | if (scene == null) { 284 | if (GUILayout.Button("Create New Cutscene", GUILayout.ExpandWidth(false))) { 285 | CreateCutscene(); 286 | } 287 | } else { // Otherwise present the cutscene editor 288 | float windowHeight = style.GetStyle("Pane").fixedHeight; 289 | 290 | // Options window 291 | //Rect optionsRect = new Rect(0, 0, position.width / 3, windowHeight); 292 | //options.OnGUI(optionsRect); 293 | 294 | // Media window 295 | Rect mediaRect = new Rect(2, 2, position.width / 2, windowHeight); 296 | media.OnGUI(mediaRect); 297 | 298 | // Effects window 299 | Rect effectsRect = new Rect(mediaRect.xMax + 2, 2, position.width - mediaRect.xMax - 4, windowHeight); 300 | effects.OnGUI(effectsRect); 301 | 302 | // Cutting tools 303 | Rect toolsRect = new Rect(0, mediaRect.yMax, position.width, 25); 304 | tools.OnGUI(toolsRect); 305 | 306 | // Timeline 307 | Rect timelineRect = new Rect(0, toolsRect.yMax, position.width, position.height - toolsRect.yMax); 308 | timeline.OnGUI(timelineRect); 309 | } 310 | } 311 | 312 | // Context menus: 313 | 314 | /// 315 | /// Deletes a piece of media by invoking a context menu item. 316 | /// 317 | /// The context menu command. 318 | [MenuItem("CONTEXT/CutsceneObject/Delete")] 319 | static void DeleteCutsceneMedia (MenuCommand command) 320 | { 321 | DeleteCutsceneMedia(command.context as CutsceneMedia); 322 | } 323 | 324 | /// 325 | /// Deletes a piece of media. 326 | /// 327 | /// The media to delete. 328 | /// This has to be in CutsceneEditor rather than CutsceneTimeline because it uses the DestroyImmediate function, which is only available to classes which inherit from UnityEngine.Object. 329 | static void DeleteCutsceneMedia (CutsceneMedia obj) 330 | { 331 | bool delete = true; 332 | 333 | // Display a dialog to prevent accidental deletions 334 | if (EditorPrefs.GetBool("Cutscene Warn Before Delete", true)) { 335 | delete = EditorUtility.DisplayDialog("Delete Object", "Are you sure you wish to delete this object? Changes cannot be undone.", "Delete", "Cancel"); 336 | } 337 | 338 | // Only delete the cutscene object if the user chose to 339 | if (delete) { 340 | Debug.Log("Cutscene Editor: deleting media " + obj.name); 341 | if (obj.type == Cutscene.MediaType.Actors || obj.type == Cutscene.MediaType.Subtitles) { // Delete the CutsceneObject component 342 | DestroyImmediate(obj); 343 | } else { // Delete the actual game object 344 | DestroyImmediate(obj.gameObject); 345 | } 346 | } 347 | } 348 | 349 | /// 350 | /// Deletes a track by invoking a context menu item. 351 | /// 352 | /// The context menu command. 353 | /// True if the track was successfully deleted, false otherwise. 354 | [MenuItem("CONTEXT/CutsceneTrack/Delete Track")] 355 | static bool DeleteTrack (MenuCommand command) 356 | { 357 | return DeleteTrack(command.context as CutsceneTrack); 358 | } 359 | 360 | /// 361 | /// Deletes a track. 362 | /// 363 | /// The track to delete. 364 | /// True if the track was successfully deleted, false otherwise. 365 | static bool DeleteTrack (CutsceneTrack track) 366 | { 367 | bool delete = true; 368 | 369 | // Display a dialog to prevent accidental deletions 370 | if (EditorPrefs.GetBool("Cutscene Warn Before Delete", true)) { 371 | delete = EditorUtility.DisplayDialog("Delete Track", "Are you sure you wish to delete this track? Changes cannot be undone.", "Delete", "Cancel"); 372 | } 373 | 374 | if (delete) { 375 | DestroyImmediate(track); 376 | } 377 | 378 | return delete; 379 | } 380 | 381 | /// 382 | /// Deletes a clip by invoking a context menu item. 383 | /// 384 | /// The context menu command. 385 | /// True if the clip was successfully deleted, false otherwise. 386 | [MenuItem("CONTEXT/CutsceneClip/Delete Clip")] 387 | static bool DeleteClip (MenuCommand command) 388 | { 389 | return DeleteClip(command.context as CutsceneClip); 390 | } 391 | 392 | /// 393 | /// Deletes a clip. 394 | /// 395 | /// The clip to delete. 396 | /// True if the clip was successfully deleted, false otherwise. 397 | static bool DeleteClip (CutsceneClip clip) 398 | { 399 | bool delete = true; 400 | 401 | // Display a dialog to prevent accidental deletions 402 | if (EditorPrefs.GetBool("Cutscene Warn Before Delete", true)) { 403 | delete = EditorUtility.DisplayDialog("Delete Clip", "Are you sure you wish to delete this clip? Changes cannot be undone.", "Delete", "Cancel"); 404 | } 405 | 406 | clip.setToDelete = delete; 407 | return delete; 408 | } 409 | 410 | /// 411 | /// Selects the track at the specified index. 412 | /// 413 | /// The track to select. 414 | void SelectTrackAtIndex (int index) 415 | { 416 | if (scene.tracks.Length > 0 && index > 0 && index <= scene.tracks.Length) { 417 | selectedTrack = scene.tracks[index - 1]; 418 | EDebug.Log("Cutscene Editor: track " + index + " is selected"); 419 | } 420 | } 421 | 422 | /// 423 | /// Determines which key command is pressed and responds accordingly. 424 | /// 425 | /// The keyboard event. 426 | /// True if the keyboard shortcut exists, false otherwise. 427 | public void HandleKeyboardShortcuts (Event keyDownEvent) 428 | { 429 | KeyCode key = keyDownEvent.keyCode; 430 | 431 | // Tools: 432 | 433 | // Move/resize 434 | if (key == CutsceneHotkeys.MoveResizeTool.key) { 435 | currentTool = Tool.MoveResize; 436 | EDebug.Log("Cutscene Editor: switching to Move/Resize tool"); 437 | // Scissors 438 | } else if (key == CutsceneHotkeys.ScissorsTool.key) { 439 | currentTool = Tool.Scissors; 440 | EDebug.Log("Cutscene Editor: switching to Scissors tool"); 441 | // Zoom 442 | } else if (key == CutsceneHotkeys.ZoomTool.key) { 443 | currentTool = Tool.Zoom; 444 | EDebug.Log("Cutscene Editor: switching to Zoom tool"); 445 | } 446 | 447 | // Timeline navigation: 448 | 449 | // Set in point 450 | else if (key == CutsceneHotkeys.SetInPont.key) { 451 | scene.inPoint = scene.playhead; 452 | EDebug.Log("Cutscene Editor: setting in point"); 453 | // Set out point 454 | } else if (key == CutsceneHotkeys.SetOutPoint.key) { 455 | scene.outPoint = scene.playhead; 456 | EDebug.Log("Cutscene Editor: setting out point"); 457 | // Scrub left 458 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("left"))) { 459 | scene.playhead -= CutsceneTimeline.scrubSmallJump; 460 | EDebug.Log("Cutscene Editor: moving playhead left"); 461 | // Scrub left large 462 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("#left"))) { 463 | scene.playhead -= CutsceneTimeline.scrubLargeJump; 464 | EDebug.Log("Cutscene Editor: moving playhead left"); 465 | // Scrub right 466 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("right"))) { 467 | scene.playhead += CutsceneTimeline.scrubSmallJump; 468 | EDebug.Log("Cutscene Editor: moving playhead right"); 469 | // Scrub right large 470 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("#right"))) { 471 | scene.playhead += CutsceneTimeline.scrubLargeJump; 472 | EDebug.Log("Cutscene Editor: moving playhead right"); 473 | // Go to previous split point 474 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("up"))) { 475 | scene.playhead = selectedTrack.GetTimeOfNextSplit(scene.playhead); 476 | EDebug.Log("Cutscene Editor: moving playhead to previous split point"); 477 | // Go to next split point 478 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("down"))) { 479 | scene.playhead = selectedTrack.GetTimeOfPreviousSplit(scene.playhead); 480 | EDebug.Log("Cutscene Editor: moving playhead to next split point"); 481 | // Go to in point 482 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("#up"))) { 483 | scene.playhead = scene.inPoint; 484 | EDebug.Log("Cutscene Editor: moving playhead to next split point"); 485 | // Go to out point 486 | } else if (keyDownEvent.Equals(Event.KeyboardEvent("#down"))) { 487 | scene.playhead = scene.outPoint; 488 | EDebug.Log("Cutscene Editor: moving playhead to next split point"); 489 | } 490 | 491 | // Track selection: 492 | 493 | // Select track 1 494 | else if (key == CutsceneHotkeys.SelectTrack1.key) { 495 | SelectTrackAtIndex(1); 496 | // Select track 2 497 | } else if (key == CutsceneHotkeys.SelectTrack2.key) { 498 | SelectTrackAtIndex(2); 499 | // Select track 3 500 | } else if (key == CutsceneHotkeys.SelectTrack3.key) { 501 | SelectTrackAtIndex(3); 502 | // Select track 4 503 | } else if (key == CutsceneHotkeys.SelectTrack4.key) { 504 | SelectTrackAtIndex(4); 505 | // Select track 5 506 | } else if (key == CutsceneHotkeys.SelectTrack5.key) { 507 | SelectTrackAtIndex(5); 508 | // Select track 6 509 | } else if (key == CutsceneHotkeys.SelectTrack6.key) { 510 | SelectTrackAtIndex(6); 511 | // Select track 7 512 | } else if (key == CutsceneHotkeys.SelectTrack7.key) { 513 | SelectTrackAtIndex(7); 514 | // Select track 8 515 | } else if (key == CutsceneHotkeys.SelectTrack8.key) { 516 | SelectTrackAtIndex(8); 517 | // Select track 9 518 | } else if (key == CutsceneHotkeys.SelectTrack9.key) { 519 | SelectTrackAtIndex(9); 520 | } 521 | 522 | // Other: 523 | 524 | else { 525 | EDebug.Log("Cutscene Editor: unknown keyboard shortcut " + keyDownEvent); 526 | return; 527 | } 528 | 529 | // If we get to this point, a shortcut matching the user's keystroke has been found 530 | Event.current.Use(); 531 | } 532 | 533 | public static float PaneTabsWidth (int count) 534 | { 535 | return count * 80f; 536 | } 537 | } 538 | --------------------------------------------------------------------------------