Exemple #1
0
        /// <summary>
        /// Retrieves import options for the texture we're currently inspecting.
        /// </summary>
        /// <returns>Texture import options object.</returns>
        private TextureImportOptions GetImportOptions()
        {
            TextureImportOptions output = null;

            LibraryEntry texEntry = ProjectLibrary.GetEntry(InspectedResourcePath);

            if (texEntry != null && texEntry.Type == LibraryEntryType.File)
            {
                FileEntry texFileEntry = (FileEntry)texEntry;
                output = texFileEntry.Options as TextureImportOptions;
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new TextureImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
        /// <summary>
        /// Triggered when a resource is (re)imported in the project library.
        /// </summary>
        /// <param name="path">Path of the imported resource, relative to the project's resource folder.</param>
        private void OnEntryImported(string path)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry == null || entry.Type != LibraryEntryType.File)
            {
                return;
            }

            FileEntry fileEntry = (FileEntry)entry;

            if (fileEntry.ResType != ResourceType.ScriptCode)
            {
                return;
            }

            ScriptCode codeFile = ProjectLibrary.Load <ScriptCode>(path);

            if (codeFile == null)
            {
                return;
            }

            if (codeFile.EditorScript)
            {
                isEditorAssemblyDirty = true;
            }
            else
            {
                isGameAssemblyDirty = true;
            }
        }
        /// <summary>
        /// Triggered when the user double-clicked on the entry.
        /// </summary>
        /// <param name="path">Project library path of the double-clicked entry.</param>
        private void OnEntryDoubleClicked(string path)
        {
            delayedSelect = false;

            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry != null)
            {
                if (entry.Type == LibraryEntryType.Directory)
                {
                    owner.Window.EnterDirectory(path);
                }
                else
                {
                    ResourceMeta meta = ProjectLibrary.GetMeta(path);

                    FileEntry fileEntry = (FileEntry)entry;
                    if (meta.ResType == ResourceType.Prefab)
                    {
                        EditorApplication.LoadScene(fileEntry.Path);
                    }
                    else if (meta.ResType == ResourceType.ScriptCode)
                    {
                        ProgressBar.Show("Opening external code editor...", 1.0f);

                        delayedOpenCodeEditorFrame = Time.FrameIdx + 1;
                    }
                }
            }
        }
        /// <summary>
        /// Retrieves import options for the audio clip we're currently inspecting.
        /// </summary>
        /// <returns>Audio clip import options object.</returns>
        private AudioClipImportOptions GetImportOptions()
        {
            AudioClip audioClip           = InspectedObject as AudioClip;
            AudioClipImportOptions output = null;

            if (audioClip != null)
            {
                LibraryEntry meshEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(audioClip));
                if (meshEntry != null && meshEntry.Type == LibraryEntryType.File)
                {
                    FileEntry meshFileEntry = (FileEntry)meshEntry;
                    output = meshFileEntry.Options as AudioClipImportOptions;
                }
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new AudioClipImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
        /// <summary>
        /// Retrieves import options for the mesh we're currently inspecting.
        /// </summary>
        /// <returns>Mesh import options object.</returns>
        private MeshImportOptions GetImportOptions()
        {
            Mesh mesh = InspectedObject as Mesh;
            MeshImportOptions output = null;

            if (mesh != null)
            {
                LibraryEntry meshEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(mesh));
                if (meshEntry != null && meshEntry.Type == LibraryEntryType.File)
                {
                    FileEntry meshFileEntry = (FileEntry)meshEntry;
                    output = meshFileEntry.Options as MeshImportOptions;
                }
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new MeshImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
Exemple #6
0
        /// <summary>
        /// Checks is the resource at the provided path a file relevant to the code editor.
        /// </summary>
        /// <param name="path">Path to the resource, absolute or relative to the project's resources folder.</param>
        /// <returns>True if the file is relevant to the code editor, false otherwise.</returns>
        private bool IsCodeEditorFile(string path)
        {
            if (Path.GetExtension(path) == ".dll")
            {
                return(true);                                   //Include assemblies. TODO: Make platform-agnostic.
            }
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry != null && entry.Type == LibraryEntryType.File)
            {
                FileEntry      fileEntry     = (FileEntry)entry;
                ResourceMeta[] resourceMetas = fileEntry.ResourceMetas;

                foreach (var codeType in CodeEditor.CodeTypes)
                {
                    foreach (var meta in resourceMetas)
                    {
                        if (meta.ResType == codeType)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemple #7
0
        /// <summary>
        /// Retrieves import options for the texture we're currently inspecting.
        /// </summary>
        /// <returns>Font import options object.</returns>
        private FontImportOptions GetImportOptions()
        {
            Font font = InspectedObject as Font;
            FontImportOptions output = null;

            if (font != null)
            {
                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(font));
                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
                {
                    FileEntry texFileEntry = (FileEntry)texEntry;
                    output = texFileEntry.Options as FontImportOptions;
                }
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new FontImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
Exemple #8
0
        /// <summary>
        /// Retrieves import options for the resource we're currently inspecting.
        /// </summary>
        /// <returns>Script code import options object.</returns>
        private ScriptCodeImportOptions GetImportOptions()
        {
            ScriptCode scriptCode          = InspectedObject as ScriptCode;
            ScriptCodeImportOptions output = null;

            if (scriptCode != null)
            {
                LibraryEntry libEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(scriptCode));
                if (libEntry != null && libEntry.Type == LibraryEntryType.File)
                {
                    FileEntry fileEntry = (FileEntry)libEntry;
                    output = fileEntry.Options as ScriptCodeImportOptions;
                }
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new ScriptCodeImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
Exemple #9
0
        /// <summary>
        /// Retrieves import options for the mesh we're currently inspecting.
        /// </summary>
        /// <returns>Mesh import options object.</returns>
        private MeshImportOptions GetImportOptions()
        {
            MeshImportOptions output = null;

            LibraryEntry meshEntry = ProjectLibrary.GetEntry(InspectedResourcePath);

            if (meshEntry != null && meshEntry.Type == LibraryEntryType.File)
            {
                FileEntry meshFileEntry = (FileEntry)meshEntry;
                output = meshFileEntry.Options as MeshImportOptions;
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new MeshImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
Exemple #10
0
        /// <summary>
        /// Retrieves import options for the texture we're currently inspecting.
        /// </summary>
        /// <returns>Texture import options object.</returns>
        private TextureImportOptions GetImportOptions()
        {
            Texture2D            texture = InspectedObject as Texture2D;
            TextureImportOptions output  = null;

            if (texture != null)
            {
                LibraryEntry texEntry = ProjectLibrary.GetEntry(ProjectLibrary.GetPath(texture));
                if (texEntry != null && texEntry.Type == LibraryEntryType.File)
                {
                    FileEntry texFileEntry = (FileEntry)texEntry;
                    output = texFileEntry.Options as TextureImportOptions;
                }
            }

            if (output == null)
            {
                if (importOptions == null)
                {
                    output = new TextureImportOptions();
                }
                else
                {
                    output = importOptions;
                }
            }

            return(output);
        }
Exemple #11
0
        /// <summary>
        /// Returns an icon that can be used for displaying a resource of the specified type.
        /// </summary>
        /// <param name="path">Path to the project library entry to display data for.</param>
        /// <param name="size">Size of the icon to retrieve, in pixels.</param>
        /// <returns>Icon to display for the specified entry.</returns>
        private static SpriteTexture GetIcon(string path, int size)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry.Type == LibraryEntryType.Directory)
            {
                return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Folder, size));
            }
            else
            {
                ResourceMeta meta = ProjectLibrary.GetMeta(path);
                switch (meta.ResType)
                {
                case ResourceType.Font:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Font, size));

                case ResourceType.Mesh:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Mesh, size));

                case ResourceType.Texture:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Texture, size));

                case ResourceType.PlainText:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PlainText, size));

                case ResourceType.ScriptCode:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.ScriptCode, size));

                case ResourceType.SpriteTexture:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.SpriteTexture, size));

                case ResourceType.Shader:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Shader, size));

                case ResourceType.ShaderInclude:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Shader, size));

                case ResourceType.Material:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Material, size));

                case ResourceType.Prefab:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Prefab, size));

                case ResourceType.GUISkin:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.GUISkin, size));

                case ResourceType.PhysicsMaterial:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PhysicsMaterial, size));

                case ResourceType.PhysicsMesh:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PhysicsMesh, size));

                case ResourceType.AudioClip:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.AudioClip, size));
                }
            }

            return(null);
        }
        /// <summary>
        /// Triggered by the runtime when a resource is dropped on the scene tree view.
        /// </summary>
        private void Internal_DoOnResourceDropped(SceneObject parent, string[] resourcePaths)
        {
            if (resourcePaths == null)
            {
                return;
            }

            List <SceneObject> addedObjects = new List <SceneObject>();

            for (int i = 0; i < resourcePaths.Length; i++)
            {
                LibraryEntry entry = ProjectLibrary.GetEntry(resourcePaths[i]);
                if (entry != null && entry.Type == LibraryEntryType.File)
                {
                    FileEntry fileEntry = (FileEntry)entry;
                    if (fileEntry.ResType == ResourceType.Mesh)
                    {
                        if (!string.IsNullOrEmpty(resourcePaths[i]))
                        {
                            string meshName = Path.GetFileNameWithoutExtension(resourcePaths[i]);

                            Mesh mesh = ProjectLibrary.Load <Mesh>(resourcePaths[i]);
                            if (mesh == null)
                            {
                                continue;
                            }

                            SceneObject so = UndoRedo.CreateSO(meshName, "Created a new Renderable \"" + meshName + "\"");
                            so.Parent = parent;

                            Renderable renderable = so.AddComponent <Renderable>();
                            renderable.Mesh = mesh;

                            addedObjects.Add(so);
                        }
                    }
                    else if (fileEntry.ResType == ResourceType.Prefab)
                    {
                        if (!string.IsNullOrEmpty(resourcePaths[i]))
                        {
                            Prefab      prefab = ProjectLibrary.Load <Prefab>(resourcePaths[i]);
                            SceneObject so     = UndoRedo.Instantiate(prefab, "Instantiating " + prefab.Name);
                            so.Parent = parent;

                            addedObjects.Add(so);
                        }
                    }
                }
            }

            if (addedObjects.Count > 0)
            {
                EditorApplication.SetSceneDirty();
            }

            Selection.SceneObjects = addedObjects.ToArray();
        }
        /// <summary>
        /// Saves the animation curves and events stored in this object, into the associated animation clip resource.
        /// Relevant animation clip resource must already be created and exist in the project library.
        /// </summary>
        public void SaveToClip()
        {
            if (!isImported)
            {
                EditorAnimClipTangents tangents;
                Apply(out tangents);

                string resourcePath = ProjectLibrary.GetPath(clip);
                ProjectLibrary.Save(clip);

                ProjectLibrary.SetEditorData(resourcePath, tangents);
            }
            else
            {
                string       resourcePath = ProjectLibrary.GetPath(clip);
                LibraryEntry entry        = ProjectLibrary.GetEntry(resourcePath);

                if (entry != null && entry.Type == LibraryEntryType.File)
                {
                    FileEntry         fileEntry         = (FileEntry)entry;
                    MeshImportOptions meshImportOptions = (MeshImportOptions)fileEntry.Options;

                    string clipName = PathEx.GetTail(resourcePath);

                    List <ImportedAnimationEvents> newEvents = new List <ImportedAnimationEvents>();
                    newEvents.AddRange(meshImportOptions.AnimationEvents);

                    bool isExisting = false;
                    for (int i = 0; i < newEvents.Count; i++)
                    {
                        if (newEvents[i].name == clipName)
                        {
                            newEvents[i].events = events;
                            isExisting          = true;
                            break;
                        }
                    }

                    if (!isExisting)
                    {
                        ImportedAnimationEvents newEntry = new ImportedAnimationEvents();
                        newEntry.name   = clipName;
                        newEntry.events = events;

                        newEvents.Add(newEntry);
                    }

                    meshImportOptions.AnimationEvents = newEvents.ToArray();

                    ProjectLibrary.Reimport(resourcePath, meshImportOptions, true);
                }
            }
        }
        /// <summary>
        /// Triggered when a resource is (re)imported in the project library.
        /// </summary>
        /// <param name="path">Path of the imported resource, relative to the project's resource folder.</param>
        private void OnEntryImported(string path)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry == null || entry.Type != LibraryEntryType.File)
            {
                return;
            }

            FileEntry fileEntry = (FileEntry)entry;

            ResourceMeta[] resourceMetas = fileEntry.ResourceMetas;

            bool found = false;

            foreach (var meta in resourceMetas)
            {
                if (meta.ResType == ResourceType.ScriptCode)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                return;
            }

            ScriptCode codeFile = ProjectLibrary.Load <ScriptCode>(path);

            if (codeFile == null)
            {
                return;
            }

            if (codeFile.EditorScript)
            {
                isEditorAssemblyDirty = true;
            }
            else
            {
                isGameAssemblyDirty = true;
            }
        }
        /// <summary>
        /// Triggered when the user clicks on the entry.
        /// </summary>
        /// <param name="path">Project library path of the clicked entry.</param>
        private void OnEntryClicked(string path)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry != null && entry.Type == LibraryEntryType.Directory)
            {
                // If entry is a directory delay selection as it might be a double-click, in which case we want to keep
                // whatever selection is active currently so that user can perform drag and drop with its inspector
                // from the folder he is browsing to.

                delayedSelect     = true;
                delayedSelectTime = Time.RealElapsed + 0.5f;
            }
            else
            {
                owner.Window.Select(path);
            }
        }
        /// <summary>
        /// Checks is the resource at the provided path a file relevant to the code editor.
        /// </summary>
        /// <param name="path">Path to the resource, absolute or relative to the project's resources folder.</param>
        /// <returns>True if the file is relevant to the code editor, false otherwise.</returns>
        private bool IsCodeEditorFile(string path)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry != null && entry.Type == LibraryEntryType.File)
            {
                FileEntry fileEntry = (FileEntry)entry;

                foreach (var codeType in CodeEditor.CodeTypes)
                {
                    if (fileEntry.ResType == codeType)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Called every frame.
        /// </summary>
        public void Update()
        {
            if (delayedSelect && Time.RealElapsed > delayedSelectTime)
            {
                owner.Window.Select(path);
                delayedSelect = false;
            }

            if (delayedOpenCodeEditorFrame == Time.FrameIdx)
            {
                LibraryEntry entry = ProjectLibrary.GetEntry(path);
                if (entry != null && entry.Type == LibraryEntryType.File)
                {
                    FileEntry resEntry = (FileEntry)entry;
                    CodeEditor.OpenFile(resEntry.Path, 0);
                }

                ProgressBar.Hide();
            }
        }
Exemple #18
0
        private void OnEditorUpdate()
        {
            if (currentType == InspectorType.SceneObject)
            {
                Component[] allComponents   = activeSO.GetComponents();
                bool        requiresRebuild = allComponents.Length != inspectorComponents.Count;

                if (!requiresRebuild)
                {
                    for (int i = 0; i < inspectorComponents.Count; i++)
                    {
                        if (inspectorComponents[i].instanceId != allComponents[i].InstanceId)
                        {
                            requiresRebuild = true;
                            break;
                        }
                    }
                }

                if (requiresRebuild)
                {
                    SceneObject so = activeSO;
                    Clear();
                    SetObjectToInspect(so);
                }
                else
                {
                    RefreshSceneObjectFields(false);

                    InspectableState componentModifyState = InspectableState.NotModified;
                    for (int i = 0; i < inspectorComponents.Count; i++)
                    {
                        componentModifyState |= inspectorComponents[i].inspector.Refresh();
                    }

                    if (componentModifyState.HasFlag(InspectableState.ModifyInProgress))
                    {
                        EditorApplication.SetSceneDirty();
                    }

                    modifyState |= componentModifyState;
                }
            }
            else if (currentType == InspectorType.Resource)
            {
                inspectorResource.inspector.Refresh();
            }

            // Detect drag and drop
            bool isValidDrag = false;

            if (activeSO != null)
            {
                if ((DragDrop.DragInProgress || DragDrop.DropInProgress) && DragDrop.Type == DragDropType.Resource)
                {
                    Vector2I windowPos     = ScreenToWindowPos(Input.PointerPosition);
                    Vector2I scrollPos     = windowPos;
                    Rect2I   contentBounds = inspectorLayout.Bounds;
                    scrollPos.x -= contentBounds.x;
                    scrollPos.y -= contentBounds.y;

                    bool   isInBounds = false;
                    Rect2I dropArea   = new Rect2I();
                    foreach (var bounds in dropAreas)
                    {
                        if (bounds.Contains(scrollPos))
                        {
                            isInBounds = true;
                            dropArea   = bounds;
                            break;
                        }
                    }

                    Type draggedComponentType = null;
                    if (isInBounds)
                    {
                        ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData;
                        if (dragData != null)
                        {
                            foreach (var resPath in dragData.Paths)
                            {
                                LibraryEntry entry     = ProjectLibrary.GetEntry(resPath);
                                FileEntry    fileEntry = entry as FileEntry;
                                if (fileEntry != null)
                                {
                                    if (fileEntry.ResType == ResourceType.ScriptCode)
                                    {
                                        ScriptCode scriptFile = ProjectLibrary.Load <ScriptCode>(resPath);

                                        if (scriptFile != null)
                                        {
                                            Type[] scriptTypes = scriptFile.Types;
                                            foreach (var type in scriptTypes)
                                            {
                                                if (type.IsSubclassOf(typeof(Component)))
                                                {
                                                    draggedComponentType = type;
                                                    isValidDrag          = true;
                                                    break;
                                                }
                                            }

                                            if (draggedComponentType != null)
                                            {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (isValidDrag)
                    {
                        scrollAreaHighlight.Bounds = dropArea;

                        if (DragDrop.DropInProgress)
                        {
                            activeSO.AddComponent(draggedComponentType);

                            modifyState = InspectableState.Modified;
                            EditorApplication.SetSceneDirty();
                        }
                    }
                }
            }

            if (scrollAreaHighlight != null)
            {
                scrollAreaHighlight.Active = isValidDrag;
            }
        }
        /// <summary>
        /// Loads curve and event information from the provided clip, and creates a new instance of this object containing
        /// the required data for editing the source clip in the animation editor.
        /// </summary>
        /// <param name="clip">Clip to load.</param>
        /// <returns>Editor specific editable information about an animation clip.</returns>
        public static EditorAnimClipInfo Create(AnimationClip clip)
        {
            EditorAnimClipInfo clipInfo = new EditorAnimClipInfo();

            clipInfo.clip       = clip;
            clipInfo.isImported = IsClipImported(clip);
            clipInfo.sampleRate = (int)clip.SampleRate;

            AnimationCurves        clipCurves      = clip.Curves;
            EditorAnimClipTangents editorCurveData = null;

            string resourcePath = ProjectLibrary.GetPath(clip);

            if (!string.IsNullOrEmpty(resourcePath))
            {
                LibraryEntry entry    = ProjectLibrary.GetEntry(resourcePath);
                string       clipName = PathEx.GetTail(resourcePath);

                if (entry != null && entry.Type == LibraryEntryType.File)
                {
                    FileEntry      fileEntry = (FileEntry)entry;
                    ResourceMeta[] metas     = fileEntry.ResourceMetas;

                    if (clipInfo.isImported)
                    {
                        for (int i = 0; i < metas.Length; i++)
                        {
                            if (clipName == metas[i].SubresourceName)
                            {
                                editorCurveData = metas[i].EditorData as EditorAnimClipTangents;
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (metas.Length > 0)
                        {
                            editorCurveData = metas[0].EditorData as EditorAnimClipTangents;
                        }
                    }
                }
            }

            if (editorCurveData == null)
            {
                editorCurveData = new EditorAnimClipTangents();
            }

            int globalCurveIdx = 0;
            Action <NamedVector3Curve[], EditorVector3CurveTangents[], string> loadVector3Curve =
                (curves, tangents, subPath) =>
            {
                foreach (var curveEntry in curves)
                {
                    TangentMode[] tangentsX = null;
                    TangentMode[] tangentsY = null;
                    TangentMode[] tangentsZ = null;

                    if (tangents != null)
                    {
                        foreach (var tangentEntry in tangents)
                        {
                            if (tangentEntry.name == curveEntry.name)
                            {
                                tangentsX = tangentEntry.tangentsX;
                                tangentsY = tangentEntry.tangentsY;
                                tangentsZ = tangentEntry.tangentsZ;
                                break;
                            }
                        }
                    }

                    // Convert compound curve to three per-component curves
                    AnimationCurve[] componentCurves = AnimationUtility.SplitCurve(curveEntry.curve);

                    FieldAnimCurves fieldCurves = new FieldAnimCurves();
                    fieldCurves.type            = SerializableProperty.FieldType.Vector3;
                    fieldCurves.curveInfos      = new CurveDrawInfo[3];
                    fieldCurves.isPropertyCurve = !clipInfo.isImported;

                    fieldCurves.curveInfos[0]       = new CurveDrawInfo();
                    fieldCurves.curveInfos[0].curve = new EdAnimationCurve(componentCurves[0], tangentsX);
                    fieldCurves.curveInfos[0].color = GUICurveDrawing.GetUniqueColor(globalCurveIdx++);

                    fieldCurves.curveInfos[1]       = new CurveDrawInfo();
                    fieldCurves.curveInfos[1].curve = new EdAnimationCurve(componentCurves[1], tangentsY);
                    fieldCurves.curveInfos[1].color = GUICurveDrawing.GetUniqueColor(globalCurveIdx++);

                    fieldCurves.curveInfos[2]       = new CurveDrawInfo();
                    fieldCurves.curveInfos[2].curve = new EdAnimationCurve(componentCurves[2], tangentsZ);
                    fieldCurves.curveInfos[2].color = GUICurveDrawing.GetUniqueColor(globalCurveIdx++);

                    string curvePath = curveEntry.name.TrimEnd('/') + subPath;
                    clipInfo.curves[curvePath] = fieldCurves;
                }
            };

            // Convert rotation from quaternion to euler
            NamedQuaternionCurve[] rotationCurves      = clipCurves.Rotation;
            NamedVector3Curve[]    eulerRotationCurves = new NamedVector3Curve[rotationCurves.Length];
            for (int i = 0; i < rotationCurves.Length; i++)
            {
                eulerRotationCurves[i]       = new NamedVector3Curve();
                eulerRotationCurves[i].name  = rotationCurves[i].name;
                eulerRotationCurves[i].flags = rotationCurves[i].flags;
                eulerRotationCurves[i].curve = AnimationUtility.QuaternionToEulerCurve(rotationCurves[i].curve);
            }

            loadVector3Curve(clipCurves.Position, editorCurveData.positionCurves, "/Position");
            loadVector3Curve(eulerRotationCurves, editorCurveData.rotationCurves, "/Rotation");
            loadVector3Curve(clipCurves.Scale, editorCurveData.scaleCurves, "/Scale");

            // Find which individual float curves belong to the same field
            Dictionary <string, Tuple <int, int, bool>[]> floatCurveMapping = new Dictionary <string, Tuple <int, int, bool>[]>();

            {
                int curveIdx = 0;
                foreach (var curveEntry in clipCurves.Generic)
                {
                    string path         = curveEntry.name;
                    string pathNoSuffix = null;

                    string pathSuffix;
                    if (path.Length >= 2)
                    {
                        pathSuffix   = path.Substring(path.Length - 2, 2);
                        pathNoSuffix = path.Substring(0, path.Length - 2);
                    }
                    else
                    {
                        pathSuffix = "";
                    }

                    int tangentIdx        = -1;
                    int currentTangentIdx = 0;
                    foreach (var tangentEntry in editorCurveData.floatCurves)
                    {
                        if (tangentEntry.name == curveEntry.name)
                        {
                            tangentIdx = currentTangentIdx;
                            break;
                        }

                        currentTangentIdx++;
                    }

                    Animation.PropertySuffixInfo suffixInfo;
                    if (Animation.PropertySuffixInfos.TryGetValue(pathSuffix, out suffixInfo))
                    {
                        Tuple <int, int, bool>[] curveInfo;
                        if (!floatCurveMapping.TryGetValue(pathNoSuffix, out curveInfo))
                        {
                            curveInfo = new Tuple <int, int, bool> [4];
                        }

                        curveInfo[suffixInfo.elementIdx] = Tuple.Create(curveIdx, tangentIdx, suffixInfo.isVector);
                        floatCurveMapping[pathNoSuffix]  = curveInfo;
                    }
                    else
                    {
                        Tuple <int, int, bool>[] curveInfo = new Tuple <int, int, bool> [4];
                        curveInfo[0] = Tuple.Create(curveIdx, tangentIdx, suffixInfo.isVector);

                        floatCurveMapping[path] = curveInfo;
                    }

                    curveIdx++;
                }
            }

            foreach (var KVP in floatCurveMapping)
            {
                int numCurves = 0;
                for (int i = 0; i < 4; i++)
                {
                    if (KVP.Value[i] == null)
                    {
                        continue;
                    }

                    numCurves++;
                }

                if (numCurves == 0)
                {
                    continue; // Invalid curve
                }
                FieldAnimCurves fieldCurves = new FieldAnimCurves();

                // Deduce type (note that all single value types are assumed to be float even if their source type is int or bool)
                if (numCurves == 1)
                {
                    fieldCurves.type = SerializableProperty.FieldType.Float;
                }
                else if (numCurves == 2)
                {
                    fieldCurves.type = SerializableProperty.FieldType.Vector2;
                }
                else if (numCurves == 3)
                {
                    fieldCurves.type = SerializableProperty.FieldType.Vector3;
                }
                else // 4 curves
                {
                    bool isVector = KVP.Value[0].Item3;
                    if (isVector)
                    {
                        fieldCurves.type = SerializableProperty.FieldType.Vector4;
                    }
                    else
                    {
                        fieldCurves.type = SerializableProperty.FieldType.Color;
                    }
                }

                bool   isMorphCurve = false;
                string curvePath    = KVP.Key;

                fieldCurves.curveInfos = new CurveDrawInfo[numCurves];
                for (int i = 0; i < numCurves; i++)
                {
                    int curveIdx   = KVP.Value[i].Item1;
                    int tangentIdx = KVP.Value[i].Item2;

                    TangentMode[] tangents = null;
                    if (tangentIdx != -1)
                    {
                        tangents = editorCurveData.floatCurves[tangentIdx].tangents;
                    }

                    fieldCurves.curveInfos[i]       = new CurveDrawInfo();
                    fieldCurves.curveInfos[i].curve = new EdAnimationCurve(clipCurves.Generic[curveIdx].curve, tangents);
                    fieldCurves.curveInfos[i].color = GUICurveDrawing.GetUniqueColor(globalCurveIdx++);

                    if (clipCurves.Generic[curveIdx].flags.HasFlag(AnimationCurveFlags.MorphFrame))
                    {
                        curvePath    = "MorphShapes/Frames/" + KVP.Key;
                        isMorphCurve = true;
                    }
                    else if (clipCurves.Generic[curveIdx].flags.HasFlag(AnimationCurveFlags.MorphWeight))
                    {
                        curvePath    = "MorphShapes/Weight/" + KVP.Key;
                        isMorphCurve = true;
                    }
                }

                fieldCurves.isPropertyCurve = !clipInfo.isImported && !isMorphCurve;

                clipInfo.curves[curvePath] = fieldCurves;
            }

            // Add events
            clipInfo.events = clip.Events;
            return(clipInfo);
        }
        private void OnEditorUpdate()
        {
            if (HasFocus)
            {
                if (!Input.IsPointerButtonHeld(PointerButton.Right))
                {
                    if (VirtualInput.IsButtonDown(toggleProfilerOverlayKey))
                        EditorSettings.SetBool(ProfilerOverlayActiveKey, !EditorSettings.GetBool(ProfilerOverlayActiveKey));

                    if (VirtualInput.IsButtonDown(viewToolKey))
                        EditorApplication.ActiveSceneTool = SceneViewTool.View;

                    if (VirtualInput.IsButtonDown(moveToolKey))
                        EditorApplication.ActiveSceneTool = SceneViewTool.Move;

                    if (VirtualInput.IsButtonDown(rotateToolKey))
                        EditorApplication.ActiveSceneTool = SceneViewTool.Rotate;

                    if (VirtualInput.IsButtonDown(scaleToolKey))
                        EditorApplication.ActiveSceneTool = SceneViewTool.Scale;

                    if (VirtualInput.IsButtonDown(duplicateKey))
                    {
                        SceneObject[] selectedObjects = Selection.SceneObjects;
                        CleanDuplicates(ref selectedObjects);

                        if (selectedObjects.Length > 0)
                        {
                            String message;
                            if (selectedObjects.Length == 1)
                                message = "Duplicated " + selectedObjects[0].Name;
                            else
                                message = "Duplicated " + selectedObjects.Length + " elements";

                            UndoRedo.CloneSO(selectedObjects, message);
                            EditorApplication.SetSceneDirty();
                        }
                    }

                    if (VirtualInput.IsButtonDown(deleteKey))
                    {
                        SceneObject[] selectedObjects = Selection.SceneObjects;
                        CleanDuplicates(ref selectedObjects);

                        if (selectedObjects.Length > 0)
                        {
                            foreach (var so in selectedObjects)
                            {
                                string message = "Deleted " + so.Name;
                                UndoRedo.DeleteSO(so, message);
                            }

                            EditorApplication.SetSceneDirty();
                        }
                    }
                }
            }

            // Refresh GUI buttons if needed (in case someones changes the values from script)
            if (editorSettingsHash != EditorSettings.Hash)
            {
                UpdateButtonStates();
                UpdateProfilerOverlay();
                editorSettingsHash = EditorSettings.Hash;
            }

            // Update scene view handles and selection
            sceneGizmos.Draw();
            sceneGrid.Draw();

            bool handleActive = false;
            if (Input.IsPointerButtonUp(PointerButton.Left))
            {
                if (sceneHandles.IsActive())
                {
                    sceneHandles.ClearSelection();
                    handleActive = true;
                }

                if (sceneAxesGUI.IsActive())
                {
                    sceneAxesGUI.ClearSelection();
                    handleActive = true;
                }
            }

            Vector2I scenePos;
            bool inBounds = ScreenToScenePos(Input.PointerPosition, out scenePos);

            bool draggedOver = DragDrop.DragInProgress || DragDrop.DropInProgress;
            draggedOver &= IsPointerHovering && inBounds && DragDrop.Type == DragDropType.Resource;

            if (draggedOver)
            {
                if (DragDrop.DropInProgress)
                {
                    dragActive = false;

                    if (draggedSO != null)
                    {
                        Selection.SceneObject = draggedSO;
                        EditorApplication.SetSceneDirty();
                    }

                    draggedSO = null;
                }
                else
                {
                    if (!dragActive)
                    {
                        dragActive = true;

                        ResourceDragDropData dragData = (ResourceDragDropData)DragDrop.Data;

                        string[] draggedPaths = dragData.Paths;

                        for (int i = 0; i < draggedPaths.Length; i++)
                        {
                            LibraryEntry entry = ProjectLibrary.GetEntry(draggedPaths[i]);
                            if (entry != null && entry.Type == LibraryEntryType.File)
                            {
                                FileEntry fileEntry = (FileEntry) entry;
                                if (fileEntry.ResType == ResourceType.Mesh)
                                {
                                    if (!string.IsNullOrEmpty(draggedPaths[i]))
                                    {
                                        string meshName = Path.GetFileNameWithoutExtension(draggedPaths[i]);
                                        draggedSO = UndoRedo.CreateSO(meshName, "Created a new Renderable \"" + meshName + "\"");
                                        Mesh mesh = ProjectLibrary.Load<Mesh>(draggedPaths[i]);

                                        Renderable renderable = draggedSO.AddComponent<Renderable>();
                                        renderable.Mesh = mesh;
                                    }

                                    break;
                                }
                                else if (fileEntry.ResType == ResourceType.Prefab)
                                {
                                    if (!string.IsNullOrEmpty(draggedPaths[i]))
                                    {
                                        Prefab prefab = ProjectLibrary.Load<Prefab>(draggedPaths[i]);
                                        draggedSO = UndoRedo.Instantiate(prefab, "Instantiating " + prefab.Name);
                                    }

                                    break;
                                }
                            }
                        }
                    }

                    if (draggedSO != null)
                    {
                        Ray worldRay = camera.ScreenToWorldRay(scenePos);
                        draggedSO.Position = worldRay*DefaultPlacementDepth;
                    }
                }

                return;
            }
            else
            {
                if (dragActive)
                {
                    dragActive = false;

                    if (draggedSO != null)
                    {
                        draggedSO.Destroy();
                        draggedSO = null;
                    }
                }
            }

            if (HasFocus)
            {
                cameraController.EnableInput(true);

                if (inBounds)
                {
                    if (Input.IsPointerButtonDown(PointerButton.Left))
                    {
                        Rect2I sceneAxesGUIBounds = new Rect2I(Width - HandleAxesGUISize - HandleAxesGUIPaddingX, 
                            HandleAxesGUIPaddingY, HandleAxesGUISize, HandleAxesGUISize);

                        if (sceneAxesGUIBounds.Contains(scenePos))
                            sceneAxesGUI.TrySelect(scenePos);
                        else
                            sceneHandles.TrySelect(scenePos);
                    }
                    else if (Input.IsPointerButtonUp(PointerButton.Left))
                    {
                        if (!handleActive)
                        {
                            bool ctrlHeld = Input.IsButtonHeld(ButtonCode.LeftControl) ||
                                            Input.IsButtonHeld(ButtonCode.RightControl);

                            sceneSelection.PickObject(scenePos, ctrlHeld);
                        }
                    }
                }
            }
            else
                cameraController.EnableInput(false);

            SceneHandles.BeginInput();
            sceneHandles.UpdateInput(scenePos, Input.PointerDelta);
            sceneHandles.Draw();

            sceneAxesGUI.UpdateInput(scenePos);
            sceneAxesGUI.Draw();
            SceneHandles.EndInput();

            sceneSelection.Draw();

            UpdateGridMode();

            if (VirtualInput.IsButtonDown(frameKey))
                cameraController.FrameSelected();
        }
Exemple #21
0
        /// <summary>
        /// Saves the animation curves and events stored in this object, into the associated animation clip resource.
        /// Relevant animation clip resource must already be created and exist in the project library.
        /// </summary>
        public void SaveToClip()
        {
            if (!isImported)
            {
                List <NamedVector3Curve> positionCurves = new List <NamedVector3Curve>();
                List <NamedVector3Curve> rotationCurves = new List <NamedVector3Curve>();
                List <NamedVector3Curve> scaleCurves    = new List <NamedVector3Curve>();
                List <NamedFloatCurve>   floatCurves    = new List <NamedFloatCurve>();

                List <EditorVector3CurveTangents> positionTangents = new List <EditorVector3CurveTangents>();
                List <EditorVector3CurveTangents> rotationTangents = new List <EditorVector3CurveTangents>();
                List <EditorVector3CurveTangents> scaleTangents    = new List <EditorVector3CurveTangents>();
                List <EditorFloatCurveTangents>   floatTangents    = new List <EditorFloatCurveTangents>();

                foreach (var kvp in curves)
                {
                    string[] pathEntries = kvp.Key.Split('/');
                    if (pathEntries.Length == 0)
                    {
                        continue;
                    }

                    string lastEntry = pathEntries[pathEntries.Length - 1];

                    if (lastEntry == "Position" || lastEntry == "Rotation" || lastEntry == "Scale")
                    {
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < pathEntries.Length - 2; i++)
                        {
                            sb.Append(pathEntries[i] + "/");
                        }

                        if (pathEntries.Length > 1)
                        {
                            sb.Append(pathEntries[pathEntries.Length - 2]);
                        }

                        string curvePath = sb.ToString();

                        NamedVector3Curve curve = new NamedVector3Curve(curvePath,
                                                                        new AnimationCurve(kvp.Value.curveInfos[0].curve.KeyFrames),
                                                                        new AnimationCurve(kvp.Value.curveInfos[1].curve.KeyFrames),
                                                                        new AnimationCurve(kvp.Value.curveInfos[2].curve.KeyFrames));

                        EditorVector3CurveTangents tangents = new EditorVector3CurveTangents();
                        tangents.name      = curvePath;
                        tangents.tangentsX = kvp.Value.curveInfos[0].curve.TangentModes;
                        tangents.tangentsY = kvp.Value.curveInfos[1].curve.TangentModes;
                        tangents.tangentsZ = kvp.Value.curveInfos[2].curve.TangentModes;

                        if (lastEntry == "Position")
                        {
                            positionCurves.Add(curve);
                            positionTangents.Add(tangents);
                        }
                        else if (lastEntry == "Rotation")
                        {
                            rotationCurves.Add(curve);
                            rotationTangents.Add(tangents);
                        }
                        else if (lastEntry == "Scale")
                        {
                            scaleCurves.Add(curve);
                            scaleTangents.Add(tangents);
                        }
                    }
                    else
                    {
                        Action <int, string> addCurve = (idx, subPath) =>
                        {
                            string path = kvp.Key + subPath;

                            NamedFloatCurve curve = new NamedFloatCurve(path,
                                                                        new AnimationCurve(kvp.Value.curveInfos[idx].curve.KeyFrames));

                            EditorFloatCurveTangents tangents = new EditorFloatCurveTangents();
                            tangents.name     = path;
                            tangents.tangents = kvp.Value.curveInfos[idx].curve.TangentModes;

                            floatCurves.Add(curve);
                            floatTangents.Add(tangents);
                        };

                        switch (kvp.Value.type)
                        {
                        case SerializableProperty.FieldType.Vector2:
                            addCurve(0, ".x");
                            addCurve(1, ".y");
                            break;

                        case SerializableProperty.FieldType.Vector3:
                            addCurve(0, ".x");
                            addCurve(1, ".y");
                            addCurve(2, ".z");
                            break;

                        case SerializableProperty.FieldType.Vector4:
                            addCurve(0, ".x");
                            addCurve(1, ".y");
                            addCurve(2, ".z");
                            addCurve(3, ".w");
                            break;

                        case SerializableProperty.FieldType.Color:
                            addCurve(0, ".r");
                            addCurve(1, ".g");
                            addCurve(2, ".b");
                            addCurve(3, ".a");
                            break;

                        case SerializableProperty.FieldType.Bool:
                        case SerializableProperty.FieldType.Int:
                        case SerializableProperty.FieldType.Float:
                            addCurve(0, "");
                            break;
                        }
                    }
                }

                AnimationCurves newClipCurves = new AnimationCurves();
                newClipCurves.PositionCurves = positionCurves.ToArray();
                newClipCurves.RotationCurves = rotationCurves.ToArray();
                newClipCurves.ScaleCurves    = scaleCurves.ToArray();
                newClipCurves.FloatCurves    = floatCurves.ToArray();

                clip.Curves     = newClipCurves;
                clip.Events     = events;
                clip.SampleRate = sampleRate;

                string resourcePath = ProjectLibrary.GetPath(clip);
                ProjectLibrary.Save(clip);

                // Save tangents for editor only use
                EditorAnimClipTangents newCurveData = new EditorAnimClipTangents();
                newCurveData.positionCurves = positionTangents.ToArray();
                newCurveData.rotationCurves = rotationTangents.ToArray();
                newCurveData.scaleCurves    = scaleTangents.ToArray();
                newCurveData.floatCurves    = floatTangents.ToArray();

                ProjectLibrary.SetEditorData(resourcePath, newCurveData);
            }
            else
            {
                string       resourcePath = ProjectLibrary.GetPath(clip);
                LibraryEntry entry        = ProjectLibrary.GetEntry(resourcePath);

                if (entry != null && entry.Type == LibraryEntryType.File)
                {
                    FileEntry         fileEntry         = (FileEntry)entry;
                    MeshImportOptions meshImportOptions = (MeshImportOptions)fileEntry.Options;

                    string clipName = PathEx.GetTail(resourcePath);

                    List <ImportedAnimationEvents> newEvents = new List <ImportedAnimationEvents>();
                    newEvents.AddRange(meshImportOptions.AnimationEvents);

                    bool isExisting = false;
                    for (int i = 0; i < newEvents.Count; i++)
                    {
                        if (newEvents[i].name == clipName)
                        {
                            newEvents[i].events = events;
                            isExisting          = true;
                            break;
                        }
                    }

                    if (!isExisting)
                    {
                        ImportedAnimationEvents newEntry = new ImportedAnimationEvents();
                        newEntry.name   = clipName;
                        newEntry.events = events;

                        newEvents.Add(newEntry);
                    }

                    meshImportOptions.AnimationEvents = newEvents.ToArray();

                    ProjectLibrary.Reimport(resourcePath, meshImportOptions, true);
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// Returns an icon that can be used for displaying a resource of the specified type.
        /// </summary>
        /// <param name="path">Path to the project library entry to display data for.</param>
        /// <param name="size">Size of the icon to retrieve, in pixels.</param>
        /// <returns>Icon to display for the specified entry.</returns>
        private static SpriteTexture GetIcon(string path, int size)
        {
            LibraryEntry entry = ProjectLibrary.GetEntry(path);

            if (entry.Type == LibraryEntryType.Directory)
            {
                return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Folder, size));
            }
            else
            {
                ResourceMeta         meta  = ProjectLibrary.GetMeta(path);
                ProjectResourceIcons icons = meta.Icons;

                Texture icon;
                if (size <= 16)
                {
                    icon = icons.icon16;
                }
                else if (size <= 32)
                {
                    icon = icons.icon32;
                }
                else if (size <= 48)
                {
                    icon = icons.icon48;
                }
                else
                {
                    icon = icons.icon64;
                }

                if (icon != null)
                {
                    return(new SpriteTexture(icon));
                }

                switch (meta.ResType)
                {
                case ResourceType.Font:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Font, size));

                case ResourceType.Mesh:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Mesh, size));

                case ResourceType.Texture:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Texture, size));

                case ResourceType.PlainText:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PlainText, size));

                case ResourceType.ScriptCode:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.ScriptCode, size));

                case ResourceType.SpriteTexture:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.SpriteTexture, size));

                case ResourceType.Shader:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Shader, size));

                case ResourceType.ShaderInclude:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Shader, size));

                case ResourceType.Material:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Material, size));

                case ResourceType.Prefab:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.Prefab, size));

                case ResourceType.GUISkin:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.GUISkin, size));

                case ResourceType.PhysicsMaterial:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PhysicsMaterial, size));

                case ResourceType.PhysicsMesh:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.PhysicsMesh, size));

                case ResourceType.AudioClip:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.AudioClip, size));

                case ResourceType.AnimationClip:
                    return(EditorBuiltin.GetLibraryItemIcon(LibraryItemIcon.AnimationClip, size));
                }
            }

            return(null);
        }