浏览代码

Initial Commit

/main
peeweek 6 年前
当前提交
515c9969
共有 227 个文件被更改,包括 7560 次插入1 次删除
  1. 8
      README.md
  2. 5
      LICENSE.md
  3. 9
      com.unity.vfx-toolbox/Editor.meta
  4. 9
      com.unity.vfx-toolbox/Editor/Canvas.meta
  5. 9
      com.unity.vfx-toolbox/Editor/Canvas/Shaders.meta
  6. 69
      com.unity.vfx-toolbox/Editor/Canvas/Shaders/VFXToolboxCanvas.shader
  7. 9
      com.unity.vfx-toolbox/Editor/Canvas/Shaders/VFXToolboxCanvas.shader.meta
  8. 638
      com.unity.vfx-toolbox/Editor/Canvas/VFXToolboxCanvas.cs
  9. 12
      com.unity.vfx-toolbox/Editor/Canvas/VFXToolboxCanvas.cs.meta
  10. 9
      com.unity.vfx-toolbox/Editor/Examples.meta
  11. 73
      com.unity.vfx-toolbox/Editor/Examples/ImageSequencerSourcePostprocessor.cs
  12. 12
      com.unity.vfx-toolbox/Editor/Examples/ImageSequencerSourcePostprocessor.cs.meta
  13. 9
      com.unity.vfx-toolbox/Editor/External.meta
  14. 860
      com.unity.vfx-toolbox/Editor/External/CurveEditor.cs
  15. 12
      com.unity.vfx-toolbox/Editor/External/CurveEditor.cs.meta
  16. 9
      com.unity.vfx-toolbox/Editor/Resources.meta
  17. 34
      com.unity.vfx-toolbox/Editor/Resources/MissingTexture.png
  18. 76
      com.unity.vfx-toolbox/Editor/Resources/MissingTexture.png.meta
  19. 9
      com.unity.vfx-toolbox/Editor/Utility.meta
  20. 275
      com.unity.vfx-toolbox/Editor/Utility/CurveDrawer.cs
  21. 12
      com.unity.vfx-toolbox/Editor/Utility/CurveDrawer.cs.meta
  22. 59
      com.unity.vfx-toolbox/Editor/Utility/CurveToTextureUtility.cs
  23. 12
      com.unity.vfx-toolbox/Editor/Utility/CurveToTextureUtility.cs.meta
  24. 699
      com.unity.vfx-toolbox/Editor/Utility/FilterPopupWindow.cs
  25. 12
      com.unity.vfx-toolbox/Editor/Utility/FilterPopupWindow.cs.meta
  26. 21
      com.unity.vfx-toolbox/Editor/Utility/FloatSliderPropertyDrawer.cs
  27. 12
      com.unity.vfx-toolbox/Editor/Utility/FloatSliderPropertyDrawer.cs.meta
  28. 9
      com.unity.vfx-toolbox/Editor/Utility/Shaders.meta
  29. 56
      com.unity.vfx-toolbox/Editor/Utility/Shaders/BlitRect.shader
  30. 9
      com.unity.vfx-toolbox/Editor/Utility/Shaders/BlitRect.shader.meta
  31. 108
      com.unity.vfx-toolbox/Editor/Utility/Splitter.cs
  32. 12
      com.unity.vfx-toolbox/Editor/Utility/Splitter.cs.meta
  33. 210
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxGUIUtility.cs
  34. 12
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxGUIUtility.cs.meta
  35. 80
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxStyles.cs
  36. 12
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxStyles.cs.meta
  37. 116
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxUtility.cs
  38. 12
      com.unity.vfx-toolbox/Editor/Utility/VFXToolboxUtility.cs.meta
  39. 9
      com.unity.vfx-toolbox/ImageSequencer.meta
  40. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders.meta
  41. 97
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Blur.shader
  42. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Blur.shader.meta
  43. 140
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/HeightToNormal.shader
  44. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/HeightToNormal.shader.meta
  45. 100
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/LightNormals.shader
  46. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/LightNormals.shader.meta
  47. 68
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Negative.shader
  48. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Negative.shader.meta
  49. 89
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Rotate.shader
  50. 9
      com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Rotate.shader.meta
  51. 9
      com.unity.vfx-toolbox/ImageSequencer/Editor.meta
  52. 9
      com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes.meta
  53. 20
      com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes/ProcessorAttribute.cs
  54. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes/ProcessorAttribute.cs.meta
  55. 8
      com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources.meta
  56. 4
      com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources/ImageSequence Icon.png
  57. 92
      com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources/ImageSequence Icon.png.meta
  58. 9
      com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters.meta
  59. 477
      com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniEXR.cs
  60. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniEXR.cs.meta
  61. 65
      com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniTGA.cs
  62. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniTGA.cs.meta
  63. 9
      com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup.meta
  64. 121
      com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup/ProcessorDataProvider.cs
  65. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup/ProcessorDataProvider.cs.meta
  66. 278
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessor.cs
  67. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessor.cs.meta
  68. 158
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.Serialization.cs
  69. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.Serialization.cs.meta
  70. 143
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.cs
  71. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.cs.meta
  72. 54
      com.unity.vfx-toolbox/ImageSequencer/Editor/GPUFrameProcessor.cs
  73. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/GPUFrameProcessor.cs.meta
  74. 218
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetEditor.cs
  75. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetEditor.cs.meta
  76. 52
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetFactory.cs
  77. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetFactory.cs.meta
  78. 357
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Export.cs
  79. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Export.cs.meta
  80. 779
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.GUI.cs
  81. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.GUI.cs.meta
  82. 192
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.InputFrames.cs
  83. 12
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.InputFrames.cs.meta
  84. 185
      com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Processors.cs

8
README.md


# VFXToolbox
VFX Tools
Additional tools for Visual Effect Artists.
## Image Sequencer
This utility enables the authoring of Flipbook Texture Sheets in an easy way. Create Image Sequence assets, import your texture sequences and start retiming, loop, and assemble into a flipbook texture sheet.
By using templates, you can go back, make adjustments then re-export with only one click.

5
LICENSE.md


Copyright © 2018 Unity Technologies ApS
Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License).
Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions.

9
com.unity.vfx-toolbox/Editor.meta


fileFormatVersion: 2
guid: b78adc1efd7b8084ebcc10daf51ab527
folderAsset: yes
timeCreated: 1471966525
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Canvas.meta


fileFormatVersion: 2
guid: 32d359bec3922dd42bb2ec1e37f0d997
folderAsset: yes
timeCreated: 1475496311
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Canvas/Shaders.meta


fileFormatVersion: 2
guid: 7ff2e73f8967b4146ba5168de55dfe65
folderAsset: yes
timeCreated: 1475496541
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

69
com.unity.vfx-toolbox/Editor/Canvas/Shaders/VFXToolboxCanvas.shader


Shader "Hidden/VFXToolbox/ImageSequencer/ImageSequencerCanvas"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_RGBAMask("RGBAMask", Color) = (1.0,1.0,1.0,1.0)
_MipMap("MipMap", float) = 0.0
}
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex;
float4 _RGBAMask;
float _MipMap;
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2Dlod(_MainTex, float4(i.uv,0.0f,_MipMap));
if(_RGBAMask.r + _RGBAMask.g + _RGBAMask.b == 0.0f)
{
// As we preview alpha, we need to linearize
float a = GammaToLinearSpaceExact(col.a);
col = float4(a,a,a,1.0f);
}
else
{
if(_RGBAMask.a == 0.0f)
{
col.a = 1.0f;
}
col.rgb *= _RGBAMask.rgb;
}
return col;
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/Editor/Canvas/Shaders/VFXToolboxCanvas.shader.meta


fileFormatVersion: 2
guid: 327f9df1e15b2fa48ba14251e55689e2
timeCreated: 1471965342
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

638
com.unity.vfx-toolbox/Editor/Canvas/VFXToolboxCanvas.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.VFXToolbox
{
public abstract class VFXToolboxCanvas
{
public Rect displayRect
{
get { return m_Rect; }
set { m_Rect = value; }
}
public bool maskR
{
get { return m_Material.GetColor("_RGBAMask").r == 1.0f; }
set
{
Color c = m_Material.GetColor("_RGBAMask");
if (value) c.r = 1.0f; else c.r = 0.0f;
m_Material.SetColor("_RGBAMask", c);
Invalidate(true);
}
}
public bool maskG
{
get { return m_Material.GetColor("_RGBAMask").g == 1.0f; }
set
{
Color c = m_Material.GetColor("_RGBAMask");
if (value) c.g = 1.0f; else c.g = 0.0f;
m_Material.SetColor("_RGBAMask", c);
Invalidate(true);
}
}
public bool maskB
{
get { return m_Material.GetColor("_RGBAMask").b == 1.0f; }
set
{
Color c = m_Material.GetColor("_RGBAMask");
if (value) c.b = 1.0f; else c.b = 0.0f;
m_Material.SetColor("_RGBAMask", c);
Invalidate(true);
}
}
public bool maskA
{
get { return m_Material.GetColor("_RGBAMask").a == 1.0f; }
set
{
Color c = m_Material.GetColor("_RGBAMask");
if (value) c.a = 1.0f; else c.a = 0.0f;
m_Material.SetColor("_RGBAMask", c);
Invalidate(true);
}
}
public bool filter
{
get { return m_bFilter; }
set {
if(m_bFilter!=value)
{
m_bFilter = value;
InvalidateRenderTarget();
}
}
}
public int mipMap
{
get {
return m_MipMap;
}
set {
if(m_MipMap != value)
{
m_MipMap = value;
m_Material.SetFloat("_MipMap", (float)value);
InvalidateRenderTarget();
}
else
{
m_MipMap = value;
}
}
}
public int mipMapCount
{
get { return GetMipMapCount(); }
}
public bool showGrid
{
get
{
return m_bShowGrid;
}
set
{
m_bShowGrid = value;
}
}
public float BackgroundBrightness
{
get
{
return m_bgBrightness;
}
set
{
SetBGBrightness(value);
}
}
public Styles styles
{
get
{
if (m_Styles == null)
m_Styles = new Styles(this);
return m_Styles;
}
}
public float zoom
{
get
{
return m_Zoom;
}
set
{
m_Zoom = value;
Invalidate(false);
}
}
private Vector2 m_CameraPosition = Vector2.zero;
private float m_Zoom = 1.0f;
private bool m_DragPreview = false;
private bool m_ZoomPreview = false;
private Vector2 m_ZoomPreviewCenter;
private Vector2 m_PreviousMousePosition;
private Styles m_Styles;
private Vector2 m_ZoomMinMax = new Vector2(0.2f, 10.0f);
private bool m_bFilter = true;
private int m_MipMap = 0;
private bool m_bShowGrid = true;
protected Rect m_Rect;
private Shader m_Shader;
private Material m_Material;
private RenderTexture m_RenderTexture;
private bool m_IsDirtyRenderTarget;
private bool m_bNeedRedraw;
private float m_bgBrightness = -1.0f;
public Texture texture
{
get { return GetTexture(); }
set { SetTexture(value); }
}
private Texture m_Texture;
public CanvasGUIDelegate onCanvasGUI;
public delegate void CanvasGUIDelegate();
public VFXToolboxCanvas(Rect displayRect, string shaderName = "Packages/com.unity.vfx-toolbox/Editor/Canvas/Shaders/VFXToolboxCanvas.shader")
{
m_Rect = displayRect;
m_IsDirtyRenderTarget = true;
m_bNeedRedraw = true;
m_Shader = AssetDatabase.LoadAssetAtPath<Shader>(shaderName);
m_Material = new Material(m_Shader) { hideFlags = HideFlags.DontSave };
m_RenderTexture = RenderTexture.GetTemporary(1,1,0);
}
public virtual void Invalidate(bool needRedraw)
{
m_bNeedRedraw = m_bNeedRedraw | needRedraw;
}
protected abstract void SetTexture(Texture tex);
protected abstract Texture GetTexture();
protected virtual int GetMipMapCount()
{
if (texture != null)
{
if (texture is Texture2D)
{
return (texture as Texture2D).mipmapCount;
}
else
return 0;
}
else
return 0;
}
public void InvalidateRenderTarget()
{
m_IsDirtyRenderTarget = true;
}
private void UpdateRenderTarget()
{
int width = Mathf.Max(1, texture.width / (int)Mathf.Pow(2, (mipMap)));
int height = Mathf.Max(1, texture.height / (int)Mathf.Pow(2, (mipMap)));
if(m_RenderTexture.width != width || m_RenderTexture.height != height)
{
RenderTexture.ReleaseTemporary(m_RenderTexture);
m_RenderTexture = RenderTexture.GetTemporary(width,height,0,RenderTextureFormat.ARGBHalf);
}
if (filter)
m_RenderTexture.filterMode = FilterMode.Bilinear;
else
m_RenderTexture.filterMode = FilterMode.Point;
m_IsDirtyRenderTarget = false;
Invalidate(true);
}
public void Recenter(bool Refit)
{
m_CameraPosition = Vector2.zero;
if(Refit)
{
float hZoom = (m_Rect.height - 70) / texture.height;
float wZoom = (m_Rect.width - 70) / texture.width;
m_Zoom = Mathf.Min(hZoom, wZoom);
}
else
{
m_Zoom = 1.0f;
}
}
private void Zoom(float ZoomDelta, Vector2 zoomCenter)
{
Vector2 centerPos = - new Vector2(zoomCenter.x - m_Rect.width / 2, zoomCenter.y - m_Rect.height / 2) - m_CameraPosition;
float prevZoom = m_Zoom;
m_Zoom -= ZoomDelta;
if(m_Zoom < m_ZoomMinMax.x)
m_Zoom = m_ZoomMinMax.x;
else if(m_Zoom > m_ZoomMinMax.y)
m_Zoom = m_ZoomMinMax.y;
else
{
m_CameraPosition += centerPos - ((m_Zoom / prevZoom) * centerPos);
}
}
protected virtual void HandleKeyboardEvents()
{
if(Event.current.type == EventType.KeyDown)
{
switch(Event.current.keyCode)
{
// Viewport Toggles
case KeyCode.F:
Recenter(!Event.current.shift);
break;
case KeyCode.G:
showGrid = !showGrid;
break;
case KeyCode.J:
filter = !filter;
Invalidate(true);
break;
// Brightness Control
case KeyCode.V:
BrightnessDown(0.1f);
break;
case KeyCode.B:
ResetBrightness();
break;
case KeyCode.N:
BrightnessUp(0.1f);
break;
default:
return; // Return without using event.
}
Invalidate(false);
Event.current.Use();
}
}
private void DrawCurrentTexture()
{
Rect rect = new Rect(0, 0, m_Rect.width, m_Rect.height);
// Pan : use Middle Mouse button or Alt+Click
if(Event.current.type == EventType.MouseDown && (Event.current.button == 2 || (Event.current.button == 0 && Event.current.alt)))
{
m_DragPreview = true;
}
if((Event.current.rawType == EventType.MouseUp || Event.current.rawType == EventType.DragExited) && (Event.current.button == 2 || Event.current.button == 0))
{
m_DragPreview = false;
Invalidate(false);
}
if((!m_DragPreview && Event.current.alt) || m_DragPreview)
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.Pan);
Invalidate(false);
}
if(m_DragPreview && Event.current.type == EventType.MouseDrag)
{
m_CameraPosition -= Event.current.delta;
Invalidate(false);
}
// Zoom : using MouseWheel
if (Event.current.type == EventType.ScrollWheel && rect.Contains(Event.current.mousePosition) )
{
// Delta negative when zooming In, Positive when zooming out
Zoom(Event.current.delta.y * 0.05f, Event.current.mousePosition);
Invalidate(false);
}
// Zoom : using Alt + RightClick
if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && Event.current.alt)
{
m_ZoomPreview = true;
m_ZoomPreviewCenter = Event.current.mousePosition;
m_PreviousMousePosition = m_ZoomPreviewCenter;
}
if (Event.current.rawType == EventType.MouseUp && Event.current.button == 1)
{
m_ZoomPreview = false;
}
if(m_ZoomPreview)
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.Zoom);
Vector2 mouseDelta = Event.current.mousePosition - m_PreviousMousePosition;
Zoom((mouseDelta.x + mouseDelta.y) * -0.002f, m_ZoomPreviewCenter);
Invalidate(false);
m_PreviousMousePosition = Event.current.mousePosition;
}
// Draw Texture
if(Event.current.type == EventType.Repaint)
{
GUI.DrawTexture
(
new Rect(
(rect.width/2) - m_CameraPosition.x - (texture.width*m_Zoom*0.5f),
(rect.height/2) - m_CameraPosition.y - (texture.height*m_Zoom*0.5f),
texture.width*m_Zoom,
texture.height*m_Zoom
),
m_RenderTexture,
ScaleMode.ScaleToFit
);
}
}
public Vector2 CanvasToScreen(Vector2 Position)
{
return new Vector2(
(m_Rect.width / 2) - m_CameraPosition.x - (Position.x * m_Zoom),
(m_Rect.height / 2) - m_CameraPosition.y - (Position.y * m_Zoom)
);
}
protected virtual void DrawGrid()
{
Vector2 src, dst;
if(BackgroundBrightness < 0.5f)
Handles.color = new Color(1.0f,1.0f,1.0f,0.33333f);
else
Handles.color = new Color(0.0f,0.0f,0.0f,0.66666f);
src = CanvasToScreen(new Vector2(-texture.width/2, -texture.height/2));
dst = CanvasToScreen(new Vector2(texture.width/2, texture.height/2));
Handles.DrawLine(new Vector2(src.x,src.y), new Vector2(dst.x,src.y));
Handles.DrawLine(new Vector2(dst.x,src.y), new Vector2(dst.x,dst.y));
Handles.DrawLine(new Vector2(dst.x,dst.y), new Vector2(src.x,dst.y));
Handles.DrawLine(new Vector2(src.x,dst.y), new Vector2(src.x,src.y));
Handles.color = Color.white;
}
private void BlitIntoRenderTarget()
{
// Backup GUI RenderTarget
var oldrendertarget = RenderTexture.active;
Graphics.Blit(texture, m_RenderTexture, m_Material);
// Restore GUI RenderTarget
RenderTexture.active = oldrendertarget;
}
public virtual void OnGUI()
{
if(m_bgBrightness < 0.0f)
{
ResetBrightness();
}
// Focus taken when clicked in viewport
if (Event.current.type == EventType.MouseDown && m_Rect.Contains(Event.current.mousePosition))
{
GUI.FocusControl("");
}
if(texture != null && Event.current.type == EventType.Repaint)
{
if (m_IsDirtyRenderTarget)
UpdateRenderTarget();
if(m_bNeedRedraw)
{
BlitIntoRenderTarget();
m_bNeedRedraw = false;
}
}
GUI.BeginGroup(m_Rect);
Rect LocalRect = new Rect(Vector2.zero, m_Rect.size);
#if !UNITY_2018_2_OR_NEWER
GL.sRGBWrite = (QualitySettings.activeColorSpace == ColorSpace.Linear);
#endif
GUI.DrawTextureWithTexCoords(LocalRect, BackgroundTexture, new Rect(0, 0, m_Rect.width / 64, m_Rect.height / 64));
#if !UNITY_2018_2_OR_NEWER
//GL.sRGBWrite = false;
#endif
if (texture != null)
{
HandleKeyboardEvents();
#if !UNITY_2018_2_OR_NEWER
GL.sRGBWrite = (QualitySettings.activeColorSpace == ColorSpace.Linear);
#endif
DrawCurrentTexture();
#if !UNITY_2018_2_OR_NEWER
//GL.sRGBWrite = false;
#endif
if (showGrid) DrawGrid();
if (onCanvasGUI != null)
onCanvasGUI();
}
else
GUI.Label(LocalRect, VFXToolboxGUIUtility.Get("No Texture"), EditorStyles.centeredGreyMiniLabel);
#if !UNITY_2018_2_OR_NEWER
//GL.sRGBWrite = false;
#endif
GUI.EndGroup();
}
#region BRIGHTNESS CONTROLS
public Texture2D BackgroundTexture { get { return m_BackgroundTexture; } }
private Texture2D m_BackgroundTexture;
public void SetBGBrightness(float value)
{
m_bgBrightness = value;
m_BackgroundTexture = Styles.GetBGTexture(value);
}
public void ResetBrightness()
{
if (EditorGUIUtility.isProSkin)
BackgroundBrightness = 0.2f;
else
BackgroundBrightness = 0.4f;
}
public void BrightnessUp(float value)
{
BackgroundBrightness = Mathf.Min(BackgroundBrightness + value,1.0f);
}
public void BrightnessDown(float value)
{
BackgroundBrightness = Mathf.Max(0.0f, BackgroundBrightness - value);
}
#endregion
#region STYLES
public class Styles
{
public GUIStyle miniLabel
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_ViewportMiniLabel : m_ViewportMiniLabelDark; }
}
public GUIStyle miniLabelRight
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_ViewportMiniLabelRight : m_ViewportMiniLabelRightDark; }
}
public GUIStyle miniLabelCenter
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_ViewportMiniLabelCenter : m_ViewportMiniLabelCenterDark; }
}
public GUIStyle label
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_ViewportLabel : m_ViewportLabelDark; }
}
public GUIStyle largeLabel
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_ViewportLargeLabel : m_ViewportLargeLabelDark; }
}
public Color backgroundPanelColor
{
get { return m_Canvas.BackgroundBrightness < 0.5f ? m_BackgroundPanelColor : m_BackgroundPanelColorDark; }
}
public Color red { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(1, 0, 0, 1) : new Color(0.7f, 0, 0, 1); } }
public Color green { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(0, 1, 0, 1) : new Color(0, 0.5f, 0, 1); } }
public Color blue { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(0, 0, 1, 1) : new Color(0, 0, 0.5f, 1); } }
public Color white { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(1, 1, 1, 1) : new Color(0, 0, 0, 1); } }
public Color black { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(0, 0, 0, 1) : new Color(1, 1, 1, 1); } }
public Color yellow { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(1.0f, 0.8f, 0.25f) : new Color(0.5f, 0.4f, 0.1f); } }
public Color cyan { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(0.25f, 0.8f, 1.0f) : new Color(0.1f, 0.4f, 0.5f); } }
public Color fadewhite { get { return m_Canvas.BackgroundBrightness < 0.5f ? new Color(1, 1, 1, 0.25f) : new Color(0, 0, 0, 0.25f); } }
private GUIStyle m_ViewportMiniLabel;
private GUIStyle m_ViewportMiniLabelDark;
private GUIStyle m_ViewportMiniLabelRight;
private GUIStyle m_ViewportMiniLabelRightDark;
private GUIStyle m_ViewportMiniLabelCenter;
private GUIStyle m_ViewportMiniLabelCenterDark;
private GUIStyle m_ViewportLabel;
private GUIStyle m_ViewportLabelDark;
private GUIStyle m_ViewportLargeLabel;
private GUIStyle m_ViewportLargeLabelDark;
private VFXToolboxCanvas m_Canvas;
private Color m_BackgroundPanelColor;
private Color m_BackgroundPanelColorDark;
public Styles(VFXToolboxCanvas canvas)
{
m_Canvas = canvas;
m_ViewportMiniLabel = new GUIStyle(EditorStyles.miniLabel);
m_ViewportMiniLabel.normal.textColor = Color.white;
m_ViewportMiniLabelDark = new GUIStyle(EditorStyles.miniLabel);
m_ViewportMiniLabelDark.normal.textColor = Color.black;
m_ViewportMiniLabelRight = new GUIStyle(m_ViewportMiniLabel);
m_ViewportMiniLabelRight.alignment = TextAnchor.MiddleRight;
m_ViewportMiniLabelRightDark = new GUIStyle(m_ViewportMiniLabelDark);
m_ViewportMiniLabelRightDark.alignment = TextAnchor.MiddleRight;
m_ViewportMiniLabelCenter = new GUIStyle(m_ViewportMiniLabel);
m_ViewportMiniLabelCenter.alignment = TextAnchor.MiddleCenter;
m_ViewportMiniLabelCenterDark = new GUIStyle(m_ViewportMiniLabelDark);
m_ViewportMiniLabelCenterDark.alignment = TextAnchor.MiddleCenter;
m_ViewportLabel = new GUIStyle(EditorStyles.largeLabel);
m_ViewportLabel.normal.textColor = Color.white;
m_ViewportLabelDark = new GUIStyle(EditorStyles.largeLabel);
m_ViewportLabelDark.normal.textColor = Color.black;
m_ViewportLargeLabel = new GUIStyle(EditorStyles.largeLabel);
m_ViewportLargeLabel.fontSize = 24;
m_ViewportLargeLabel.normal.textColor = Color.white;
m_ViewportLargeLabelDark = new GUIStyle(EditorStyles.largeLabel);
m_ViewportLargeLabelDark.fontSize = 24;
m_ViewportLargeLabelDark.normal.textColor = Color.black;
m_BackgroundPanelColor = new Color(0.02f, 0.02f, 0.02f, 0.85f);
m_BackgroundPanelColorDark = new Color(0.25f, 0.25f, 0.25f, 0.85f);
}
public static Texture2D GetBGTexture(float brightness)
{
Texture2D out_tex = new Texture2D(2, 2) { hideFlags = HideFlags.DontSave };
Color[] bgcolors = new Color[4];
brightness *= 0.95f;
bgcolors[0] = new Color(brightness+0.05f, brightness+0.05f, brightness+0.05f);
bgcolors[1] = new Color(brightness, brightness, brightness);
bgcolors[2] = new Color(brightness, brightness, brightness);
bgcolors[3] = new Color(brightness+0.05f, brightness+0.05f, brightness+0.05f);
out_tex.SetPixels(bgcolors);
out_tex.wrapMode = TextureWrapMode.Repeat;
out_tex.filterMode = FilterMode.Point;
out_tex.Apply();
return out_tex;
}
}
#endregion
}
}

12
com.unity.vfx-toolbox/Editor/Canvas/VFXToolboxCanvas.cs.meta


fileFormatVersion: 2
guid: ea792668228c44546a965aa9034a163d
timeCreated: 1475496324
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Examples.meta


fileFormatVersion: 2
guid: cb01cd6b53c5afb4e932d16ea337934c
folderAsset: yes
timeCreated: 1475064740
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

73
com.unity.vfx-toolbox/Editor/Examples/ImageSequencerSourcePostprocessor.cs


using System.IO;
namespace UnityEditor.VFXToolbox
{
/// <summary>
/// Example of an Asset PostProcessor that configures all textures within a given folder (default Asset/Resources)
/// to be imported with settings according to VFX Toolbox Image Sequencer recommandations.
/// </summary>
public class ImageSequencerSourcePostprocessor : AssetPostprocessor
{
// Internal flags for usage
public enum Usage
{
Color,
LinearData
}
public const string m_RootFolder = "Assets/VFXResources";
public const string m_NormalNomenclaturePostFix = "_nrm";
public const string m_LinearNomenclatureSuffix = "_lin";
public readonly string[] m_Labels = new string[] { "Weapon", "Audio" };
void OnPreprocessTexture()
{
if (assetPath.StartsWith(m_RootFolder)) // for all assets in VFX resources folder
{
string filename = Path.GetFileName(assetPath);
string extension = Path.GetExtension(assetPath);
// Default usage is color
Usage usage = Usage.Color;
// if containing normal suffix, switch to linear
if (filename.ToLower().Contains(m_NormalNomenclaturePostFix.ToLower()))
usage = Usage.LinearData;
// if containing linear suffix, switch to linear
if (filename.ToLower().Contains(m_LinearNomenclatureSuffix.ToLower()))
usage = Usage.LinearData;
// if HDR, switch to linear
if(extension.ToLower() == "EXR".ToLower())
usage = Usage.LinearData;
TextureImporter importer = (TextureImporter)assetImporter;
// Even if we have normalmaps, we don't want to encode them in swizzled NM yet.
importer.textureType = TextureImporterType.Default;
switch(usage)
{
default: // Color, but should not happen
case Usage.Color:
importer.sRGBTexture = true;
break;
case Usage.LinearData:
importer.sRGBTexture = false;
break;
}
importer.alphaSource = TextureImporterAlphaSource.FromInput;
importer.alphaIsTransparency = false;
importer.maxTextureSize = 8192;
importer.mipmapEnabled = true;
importer.mipmapFilter = TextureImporterMipFilter.KaiserFilter;
importer.npotScale = TextureImporterNPOTScale.None;
importer.textureShape = TextureImporterShape.Texture2D;
importer.textureCompression = TextureImporterCompression.Uncompressed;
}
}
}
}

12
com.unity.vfx-toolbox/Editor/Examples/ImageSequencerSourcePostprocessor.cs.meta


fileFormatVersion: 2
guid: 1e7e4f3b8c8b7044993e1c771fe77dfe
timeCreated: 1475062871
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/External.meta


fileFormatVersion: 2
guid: 79e4635bcb669464dad7c404d7fe4963
folderAsset: yes
timeCreated: 1478099486
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

860
com.unity.vfx-toolbox/Editor/External/CurveEditor.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.VFXToolbox
{
public sealed class CurveEditor
{
#region Enums
enum EditMode
{
None,
Moving,
TangentEdit
}
enum Tangent
{
In,
Out
}
#endregion
#region Structs
public struct Settings
{
public Rect bounds;
public RectOffset padding;
public Color selectionColor;
public float curvePickingDistance;
public float keyTimeClampingDistance;
public static Settings defaultSettings
{
get
{
return new Settings
{
bounds = new Rect(0f, 0f, 1f, 1f),
padding = new RectOffset(10, 10, 10, 10),
selectionColor = Color.yellow,
curvePickingDistance = 6f,
keyTimeClampingDistance = 1e-4f
};
}
}
}
public struct CurveState
{
public bool visible;
public bool editable;
public uint minPointCount;
public float zeroKeyConstantValue;
public Color color;
public float width;
public float handleWidth;
public bool showNonEditableHandles;
public bool onlyShowHandlesOnSelection;
public bool loopInBounds;
public static CurveState defaultState
{
get
{
return new CurveState
{
visible = true,
editable = true,
minPointCount = 2,
zeroKeyConstantValue = 0f,
color = Color.white,
width = 2f,
handleWidth = 2f,
showNonEditableHandles = true,
onlyShowHandlesOnSelection = false,
loopInBounds = false
};
}
}
}
public struct Selection
{
public SerializedProperty curve;
public int keyframeIndex;
public Keyframe? keyframe;
public Selection(SerializedProperty curve, int keyframeIndex, Keyframe? keyframe)
{
this.curve = curve;
this.keyframeIndex = keyframeIndex;
this.keyframe = keyframe;
}
}
internal struct MenuAction
{
internal SerializedProperty curve;
internal int index;
internal Vector3 position;
internal MenuAction(SerializedProperty curve)
{
this.curve = curve;
this.index = -1;
this.position = Vector3.zero;
}
internal MenuAction(SerializedProperty curve, int index)
{
this.curve = curve;
this.index = index;
this.position = Vector3.zero;
}
internal MenuAction(SerializedProperty curve, Vector3 position)
{
this.curve = curve;
this.index = -1;
this.position = position;
}
}
#endregion
#region Fields & properties
public Settings settings { get; private set; }
Dictionary<SerializedProperty, CurveState> m_Curves;
Rect m_CurveArea;
SerializedProperty m_SelectedCurve;
int m_SelectedKeyframeIndex = -1;
EditMode m_EditMode = EditMode.None;
Tangent m_TangentEditMode;
bool m_Dirty;
#endregion
#region Constructors & destructors
public CurveEditor()
: this(Settings.defaultSettings)
{}
public CurveEditor(Settings settings)
{
this.settings = settings;
m_Curves = new Dictionary<SerializedProperty, CurveState>();
}
#endregion
#region Public API
public void Add(params SerializedProperty[] curves)
{
foreach (var curve in curves)
Add(curve, CurveState.defaultState);
}
public void Add(SerializedProperty curve)
{
Add(curve, CurveState.defaultState);
}
public void Add(SerializedProperty curve, CurveState state)
{
// Make sure the property is in fact an AnimationCurve
var animCurve = curve.animationCurveValue;
if (animCurve == null)
throw new ArgumentException("curve");
if (m_Curves.ContainsKey(curve))
Debug.LogWarning("Curve has already been added to the editor");
m_Curves.Add(curve, state);
}
public void Remove(SerializedProperty curve)
{
m_Curves.Remove(curve);
}
public void RemoveAll()
{
m_Curves.Clear();
}
public CurveState GetCurveState(SerializedProperty curve)
{
CurveState state;
if (!m_Curves.TryGetValue(curve, out state))
throw new KeyNotFoundException("curve");
return state;
}
public void SetCurveState(SerializedProperty curve, CurveState state)
{
if (!m_Curves.ContainsKey(curve))
throw new KeyNotFoundException("curve");
m_Curves[curve] = state;
}
public Selection GetSelection()
{
Keyframe? key = null;
if (m_SelectedKeyframeIndex > -1)
{
var curve = m_SelectedCurve.animationCurveValue;
if (m_SelectedKeyframeIndex >= curve.length)
m_SelectedKeyframeIndex = -1;
else
key = curve[m_SelectedKeyframeIndex];
}
return new Selection(m_SelectedCurve, m_SelectedKeyframeIndex, key);
}
public void ClearSelection()
{
m_SelectedCurve = null;
m_SelectedKeyframeIndex = -1;
}
public void SetKeyframe(SerializedProperty curve, int keyframeIndex, Keyframe keyframe)
{
var animCurve = curve.animationCurveValue;
SetKeyframe(animCurve, keyframeIndex, keyframe);
SaveCurve(curve, animCurve);
}
public void SetBounds(Rect bounds)
{
var newSettings = settings;
newSettings.bounds = bounds;
settings = newSettings;
}
public bool OnGUI(Rect rect)
{
if(Event.current.type == EventType.Repaint)
m_Dirty = false;
GUI.BeginClip(rect);
{
var area = new Rect(Vector2.zero, rect.size);
m_CurveArea = settings.padding.Remove(area);
foreach (var curve in m_Curves)
OnCurveGUI(area, curve.Key, curve.Value);
OnGeneralUI(area);
}
GUI.EndClip();
return m_Dirty;
}
#endregion
#region UI & events
void OnCurveGUI(Rect rect, SerializedProperty curve, CurveState state)
{
// Discard invisible curves
if (!state.visible)
return;
var animCurve = curve.animationCurveValue;
var keys = animCurve.keys;
var length = keys.Length;
// Curve drawing
// Slightly dim non-editable curves
var color = state.color;
if (!state.editable)
color.a *= 0.5f;
Handles.color = color;
var bounds = settings.bounds;
if (length == 0)
{
var p1 = CurveToCanvas(new Vector3(bounds.xMin, state.zeroKeyConstantValue));
var p2 = CurveToCanvas(new Vector3(bounds.xMax, state.zeroKeyConstantValue));
Handles.DrawAAPolyLine(state.width, p1, p2);
}
else if (length == 1)
{
var p1 = CurveToCanvas(new Vector3(bounds.xMin, keys[0].value));
var p2 = CurveToCanvas(new Vector3(bounds.xMax, keys[0].value));
Handles.DrawAAPolyLine(state.width, p1, p2);
}
else
{
var prevKey = keys[0];
for (int k = 1; k < length; k++)
{
var key = keys[k];
var pts = BezierSegment(prevKey, key);
if (float.IsInfinity(prevKey.outTangent) || float.IsInfinity(key.inTangent))
{
var s = HardSegment(prevKey, key);
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
}
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
prevKey = key;
}
// Curve extents & loops
if (keys[0].time > bounds.xMin)
{
if (state.loopInBounds)
{
var p1 = keys[length - 1];
p1.time -= settings.bounds.width;
var p2 = keys[0];
var pts = BezierSegment(p1, p2);
if (float.IsInfinity(p1.outTangent) || float.IsInfinity(p2.inTangent))
{
var s = HardSegment(p1, p2);
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
}
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
}
else
{
var p1 = CurveToCanvas(new Vector3(bounds.xMin, keys[0].value));
var p2 = CurveToCanvas(keys[0]);
Handles.DrawAAPolyLine(state.width, p1, p2);
}
}
if (keys[length - 1].time < bounds.xMax)
{
if (state.loopInBounds)
{
var p1 = keys[length - 1];
var p2 = keys[0];
p2.time += settings.bounds.width;
var pts = BezierSegment(p1, p2);
if (float.IsInfinity(p1.outTangent) || float.IsInfinity(p2.inTangent))
{
var s = HardSegment(p1, p2);
Handles.DrawAAPolyLine(state.width, s[0], s[1], s[2]);
}
else Handles.DrawBezier(pts[0], pts[3], pts[1], pts[2], color, null, state.width);
}
else
{
var p1 = CurveToCanvas(keys[length - 1]);
var p2 = CurveToCanvas(new Vector3(bounds.xMax, keys[length - 1].value));
Handles.DrawAAPolyLine(state.width, p1, p2);
}
}
}
// Make sure selection is correct (undo can break it)
bool isCurrentlySelectedCurve = curve == m_SelectedCurve;
if (isCurrentlySelectedCurve && m_SelectedKeyframeIndex >= length)
m_SelectedKeyframeIndex = -1;
// Handles & keys
for (int k = 0; k < length; k++)
{
bool isCurrentlySelectedKeyframe = k == m_SelectedKeyframeIndex;
var e = Event.current;
var pos = CurveToCanvas(keys[k]);
var hitRect = new Rect(pos.x - 8f, pos.y - 8f, 16f, 16f);
var offset = isCurrentlySelectedCurve
? new RectOffset(5, 5, 5, 5)
: new RectOffset(6, 6, 6, 6);
var outTangent = pos + CurveTangentToCanvas(keys[k].outTangent).normalized * 40f;
var inTangent = pos - CurveTangentToCanvas(keys[k].inTangent).normalized * 40f;
var inTangentHitRect = new Rect(inTangent.x - 7f, inTangent.y - 7f, 14f, 14f);
var outTangentHitrect = new Rect(outTangent.x - 7f, outTangent.y - 7f, 14f, 14f);
// Draw
if (state.showNonEditableHandles)
{
if (e.type == EventType.Repaint)
{
var selectedColor = (isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
? settings.selectionColor
: state.color;
// Keyframe
EditorGUI.DrawRect(offset.Remove(hitRect), selectedColor);
// Tangents
if (isCurrentlySelectedCurve && (!state.onlyShowHandlesOnSelection || (state.onlyShowHandlesOnSelection && isCurrentlySelectedKeyframe)))
{
Handles.color = selectedColor;
if (k > 0 || state.loopInBounds)
{
Handles.DrawAAPolyLine(state.handleWidth, pos, inTangent);
EditorGUI.DrawRect(offset.Remove(inTangentHitRect), selectedColor);
}
if (k < length - 1 || state.loopInBounds)
{
Handles.DrawAAPolyLine(state.handleWidth, pos, outTangent);
EditorGUI.DrawRect(offset.Remove(outTangentHitrect), selectedColor);
}
}
}
}
// Events
if (state.editable)
{
// Keyframe move
if (m_EditMode == EditMode.Moving && e.type == EventType.MouseDrag && isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
{
EditMoveKeyframe(animCurve, keys, k);
}
// Tangent editing
if (m_EditMode == EditMode.TangentEdit && e.type == EventType.MouseDrag && isCurrentlySelectedCurve && isCurrentlySelectedKeyframe)
{
bool alreadyBroken = !(Mathf.Approximately(keys[k].inTangent, keys[k].outTangent) || (float.IsInfinity(keys[k].inTangent) && float.IsInfinity(keys[k].outTangent)));
EditMoveTangent(animCurve, keys, k, m_TangentEditMode, e.shift || !(alreadyBroken || e.control));
}
// Keyframe selection & context menu
if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
{
if (hitRect.Contains(e.mousePosition))
{
if (e.button == 0)
{
SelectKeyframe(curve, k);
m_EditMode = EditMode.Moving;
e.Use();
}
else if (e.button == 1)
{
// Keyframe context menu
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Delete Key"), false, (x) =>
{
var action = (MenuAction)x;
var curveValue = action.curve.animationCurveValue;
action.curve.serializedObject.Update();
RemoveKeyframe(curveValue, action.index);
m_SelectedKeyframeIndex = -1;
SaveCurve(action.curve, curveValue);
action.curve.serializedObject.ApplyModifiedProperties();
}, new MenuAction(curve, k));
menu.ShowAsContext();
e.Use();
}
}
}
// Tangent selection & edit mode
if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
{
if (inTangentHitRect.Contains(e.mousePosition) && (k > 0 || state.loopInBounds))
{
SelectKeyframe(curve, k);
m_EditMode = EditMode.TangentEdit;
m_TangentEditMode = Tangent.In;
e.Use();
}
else if (outTangentHitrect.Contains(e.mousePosition) && (k < length - 1 || state.loopInBounds))
{
SelectKeyframe(curve, k);
m_EditMode = EditMode.TangentEdit;
m_TangentEditMode = Tangent.Out;
e.Use();
}
}
// Mouse up - clean up states
if (e.rawType == EventType.MouseUp && m_EditMode != EditMode.None)
{
m_EditMode = EditMode.None;
}
// Set cursors
{
EditorGUIUtility.AddCursorRect(hitRect, MouseCursor.MoveArrow);
if (k > 0 || state.loopInBounds)
EditorGUIUtility.AddCursorRect(inTangentHitRect, MouseCursor.RotateArrow);
if (k < length - 1 || state.loopInBounds)
EditorGUIUtility.AddCursorRect(outTangentHitrect, MouseCursor.RotateArrow);
}
}
}
Handles.color = Color.white;
SaveCurve(curve, animCurve);
}
void OnGeneralUI(Rect rect)
{
var e = Event.current;
// Selection
if (e.type == EventType.MouseDown)
{
GUI.FocusControl(null);
m_SelectedCurve = null;
m_SelectedKeyframeIndex = -1;
bool used = false;
var hit = CanvasToCurve(e.mousePosition);
float curvePickValue = CurveToCanvas(hit).y;
// Try and select a curve
foreach (var curve in m_Curves)
{
if (!curve.Value.editable || !curve.Value.visible)
continue;
var prop = curve.Key;
var state = curve.Value;
var animCurve = prop.animationCurveValue;
float hitY = animCurve.length == 0
? state.zeroKeyConstantValue
: animCurve.Evaluate(hit.x);
var curvePos = CurveToCanvas(new Vector3(hit.x, hitY));
if (Mathf.Abs(curvePos.y - curvePickValue) < settings.curvePickingDistance)
{
m_SelectedCurve = prop;
if (e.clickCount == 2 && e.button == 0)
{
// Create a keyframe on double-click on this curve
EditCreateKeyframe(animCurve, hit, true, state.zeroKeyConstantValue);
SaveCurve(prop, animCurve);
}
else if (e.button == 1)
{
// Curve context menu
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Add Key"), false, (x) =>
{
var action = (MenuAction)x;
var curveValue = action.curve.animationCurveValue;
action.curve.serializedObject.Update();
EditCreateKeyframe(curveValue, hit, true, 0f);
SaveCurve(action.curve, curveValue);
action.curve.serializedObject.ApplyModifiedProperties();
}, new MenuAction(prop, hit));
menu.ShowAsContext();
e.Use();
used = true;
}
}
}
if (e.clickCount == 2 && e.button == 0 && m_SelectedCurve == null)
{
// Create a keyframe on every curve on double-click
foreach (var curve in m_Curves)
{
if (!curve.Value.editable || !curve.Value.visible)
continue;
var prop = curve.Key;
var state = curve.Value;
var animCurve = prop.animationCurveValue;
EditCreateKeyframe(animCurve, hit, e.alt, state.zeroKeyConstantValue);
SaveCurve(prop, animCurve);
}
}
else if (!used && e.button == 1)
{
// Global context menu
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Add Key At Position"), false, () => ContextMenuAddKey(hit, false));
menu.AddItem(new GUIContent("Add Key On Curves"), false, () => ContextMenuAddKey(hit, true));
menu.ShowAsContext();
}
e.Use();
}
// Delete selected key(s)
if (e.type == EventType.KeyDown && (e.keyCode == KeyCode.Delete || e.keyCode == KeyCode.Backspace))
{
if (m_SelectedKeyframeIndex != -1 && m_SelectedCurve != null)
{
var animCurve = m_SelectedCurve.animationCurveValue;
var length = animCurve.length;
if (m_Curves[m_SelectedCurve].minPointCount < length && length >= 0)
{
EditDeleteKeyframe(animCurve, m_SelectedKeyframeIndex);
m_SelectedKeyframeIndex = -1;
SaveCurve(m_SelectedCurve, animCurve);
}
e.Use();
}
}
}
void SaveCurve(SerializedProperty prop, AnimationCurve curve)
{
prop.animationCurveValue = curve;
}
void Invalidate()
{
m_Dirty = true;
}
#endregion
#region Keyframe manipulations
void SelectKeyframe(SerializedProperty curve, int keyframeIndex)
{
m_SelectedKeyframeIndex = keyframeIndex;
m_SelectedCurve = curve;
Invalidate();
}
void ContextMenuAddKey(Vector3 hit, bool createOnCurve)
{
SerializedObject serializedObject = null;
foreach (var curve in m_Curves)
{
if (!curve.Value.editable || !curve.Value.visible)
continue;
var prop = curve.Key;
var state = curve.Value;
if (serializedObject == null)
{
serializedObject = prop.serializedObject;
serializedObject.Update();
}
var animCurve = prop.animationCurveValue;
EditCreateKeyframe(animCurve, hit, createOnCurve, state.zeroKeyConstantValue);
SaveCurve(prop, animCurve);
}
if (serializedObject != null)
serializedObject.ApplyModifiedProperties();
Invalidate();
}
void EditCreateKeyframe(AnimationCurve curve, Vector3 position, bool createOnCurve, float zeroKeyConstantValue)
{
float tangent = EvaluateTangent(curve, position.x);
if (createOnCurve)
{
position.y = curve.length == 0
? zeroKeyConstantValue
: curve.Evaluate(position.x);
}
AddKeyframe(curve, new Keyframe(position.x, position.y, tangent, tangent));
}
void EditDeleteKeyframe(AnimationCurve curve, int keyframeIndex)
{
RemoveKeyframe(curve, keyframeIndex);
}
void AddKeyframe(AnimationCurve curve, Keyframe newValue)
{
curve.AddKey(newValue);
Invalidate();
}
void RemoveKeyframe(AnimationCurve curve, int keyframeIndex)
{
curve.RemoveKey(keyframeIndex);
Invalidate();
}
void SetKeyframe(AnimationCurve curve, int keyframeIndex, Keyframe newValue)
{
var keys = curve.keys;
if (keyframeIndex > 0)
newValue.time = Mathf.Max(keys[keyframeIndex - 1].time + settings.keyTimeClampingDistance, newValue.time);
if (keyframeIndex < keys.Length - 1)
newValue.time = Mathf.Min(keys[keyframeIndex + 1].time - settings.keyTimeClampingDistance, newValue.time);
curve.MoveKey(keyframeIndex, newValue);
Invalidate();
}
void EditMoveKeyframe(AnimationCurve curve, Keyframe[] keys, int keyframeIndex)
{
var key = CanvasToCurve(Event.current.mousePosition);
float inTgt = keys[keyframeIndex].inTangent;
float outTgt = keys[keyframeIndex].outTangent;
SetKeyframe(curve, keyframeIndex, new Keyframe(key.x, key.y, inTgt, outTgt));
}
void EditMoveTangent(AnimationCurve curve, Keyframe[] keys, int keyframeIndex, Tangent targetTangent, bool linkTangents)
{
var pos = CanvasToCurve(Event.current.mousePosition);
float time = keys[keyframeIndex].time;
float value = keys[keyframeIndex].value;
pos -= new Vector3(time, value);
if (targetTangent == Tangent.In && pos.x > 0f)
pos.x = 0f;
if (targetTangent == Tangent.Out && pos.x < 0f)
pos.x = 0f;
float tangent;
if (Mathf.Approximately(pos.x, 0f))
tangent = pos.y < 0f ? float.PositiveInfinity : float.NegativeInfinity;
else
tangent = pos.y / pos.x;
float inTangent = keys[keyframeIndex].inTangent;
float outTangent = keys[keyframeIndex].outTangent;
if (targetTangent == Tangent.In || linkTangents)
inTangent = tangent;
if (targetTangent == Tangent.Out || linkTangents)
outTangent = tangent;
SetKeyframe(curve, keyframeIndex, new Keyframe(time, value, inTangent, outTangent));
}
#endregion
#region Maths utilities
Vector3 CurveToCanvas(Keyframe keyframe)
{
return CurveToCanvas(new Vector3(keyframe.time, keyframe.value));
}
Vector3 CurveToCanvas(Vector3 position)
{
var bounds = settings.bounds;
var output = new Vector3((position.x - bounds.x) / (bounds.xMax - bounds.x), (position.y - bounds.y) / (bounds.yMax - bounds.y));
output.x = output.x * (m_CurveArea.xMax - m_CurveArea.xMin) + m_CurveArea.xMin;
output.y = (1f - output.y) * (m_CurveArea.yMax - m_CurveArea.yMin) + m_CurveArea.yMin;
return output;
}
Vector3 CanvasToCurve(Vector3 position)
{
var bounds = settings.bounds;
var output = position;
output.x = (output.x - m_CurveArea.xMin) / (m_CurveArea.xMax - m_CurveArea.xMin);
output.y = (output.y - m_CurveArea.yMin) / (m_CurveArea.yMax - m_CurveArea.yMin);
output.x = Mathf.Lerp(bounds.x, bounds.xMax, output.x);
output.y = Mathf.Lerp(bounds.yMax, bounds.y, output.y);
return output;
}
Vector3 CurveTangentToCanvas(float tangent)
{
if (!float.IsInfinity(tangent))
{
var bounds = settings.bounds;
float ratio = (m_CurveArea.width / m_CurveArea.height) / ((bounds.xMax - bounds.x) / (bounds.yMax - bounds.y));
return new Vector3(1f, -tangent / ratio).normalized;
}
return float.IsPositiveInfinity(tangent) ? Vector3.up : Vector3.down;
}
Vector3[] BezierSegment(Keyframe start, Keyframe end)
{
var segment = new Vector3[4];
segment[0] = CurveToCanvas(new Vector3(start.time, start.value));
segment[3] = CurveToCanvas(new Vector3(end.time, end.value));
float middle = start.time + ((end.time - start.time) * 0.333333f);
float middle2 = start.time + ((end.time - start.time) * 0.666666f);
segment[1] = CurveToCanvas(new Vector3(middle, ProjectTangent(start.time, start.value, start.outTangent, middle)));
segment[2] = CurveToCanvas(new Vector3(middle2, ProjectTangent(end.time, end.value, end.inTangent, middle2)));
return segment;
}
Vector3[] HardSegment(Keyframe start, Keyframe end)
{
var segment = new Vector3[3];
segment[0] = CurveToCanvas(start);
segment[1] = CurveToCanvas(new Vector3(end.time, start.value));
segment[2] = CurveToCanvas(end);
return segment;
}
float ProjectTangent(float inPosition, float inValue, float inTangent, float projPosition)
{
return inValue + ((projPosition - inPosition) * inTangent);
}
float EvaluateTangent(AnimationCurve curve, float time)
{
int prev = -1, next = 0;
for (int i = 0; i < curve.keys.Length; i++)
{
if (time > curve.keys[i].time)
{
prev = i;
next = i + 1;
}
else break;
}
if (next == 0)
return 0f;
if (prev == curve.keys.Length - 1)
return 0f;
const float kD = 1e-3f;
float tp = Mathf.Max(time - kD, curve.keys[prev].time);
float tn = Mathf.Min(time + kD, curve.keys[next].time);
float vp = curve.Evaluate(tp);
float vn = curve.Evaluate(tn);
if (Mathf.Approximately(tn, tp))
return (vn - vp > 0f) ? float.PositiveInfinity : float.NegativeInfinity;
return (vn - vp) / (tn - tp);
}
#endregion
}
}

12
com.unity.vfx-toolbox/Editor/External/CurveEditor.cs.meta


fileFormatVersion: 2
guid: 09fa5806b3255d5468ab4a0e83c7aeb8
timeCreated: 1478175296
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Resources.meta


fileFormatVersion: 2
guid: 476e8e3ff454ecb4080c665b1b2f57c7
folderAsset: yes
timeCreated: 1478600131
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

34
com.unity.vfx-toolbox/Editor/Resources/MissingTexture.png

之前 之后
宽度: 256  |  高度: 256  |  大小: 8.3 KiB

76
com.unity.vfx-toolbox/Editor/Resources/MissingTexture.png.meta


fileFormatVersion: 2
guid: d8f6eb1d1e749d1449301432b2121c19
timeCreated: 1478600136
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Utility.meta


fileFormatVersion: 2
guid: 11f66135d9e709f4ab5d2de74addb620
folderAsset: yes
timeCreated: 1471966525
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

275
com.unity.vfx-toolbox/Editor/Utility/CurveDrawer.cs


using UnityEngine;
using UnityEngine.VFXToolbox;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox
{
public class CurveDrawer
{
private string m_CurveEditName;
private int m_WidgetDefaultHeight;
private bool m_WidgetShowToolbar;
private readonly RectOffset m_CurvePadding = new RectOffset(40, 16, 16, 16);
private CurveEditor m_Editor;
private Dictionary<string, SerializedProperty> m_Curves;
public delegate void CurveDrawEventDelegate(Rect renderArea, Rect curveArea);
public CurveDrawEventDelegate OnPostGUI;
private float lineBrightnessValue { get { return EditorGUIUtility.isProSkin ? 1.0f : 0.0f; } }
public CurveDrawer(string curveEditName, float minInput, float maxInput, float minOutput, float maxOutput, int height, bool showToolbar)
:this(curveEditName, minInput, maxInput, minOutput, maxOutput)
{
m_WidgetDefaultHeight = height;
m_WidgetShowToolbar = showToolbar;
}
public CurveDrawer(string curveEditName, float minInput, float maxInput, float minOutput, float maxOutput)
{
var settings = CurveEditor.Settings.defaultSettings;
settings.bounds = new Rect(minInput, minOutput, maxInput - minInput, maxOutput - minOutput);
settings.padding = m_CurvePadding;
m_Editor = new CurveEditor(settings);
m_CurveEditName = curveEditName;
m_WidgetDefaultHeight = 240;
m_WidgetShowToolbar = true;
m_Curves = new Dictionary<string, SerializedProperty>();
}
public void SetBounds(Rect bounds)
{
m_Editor.SetBounds(bounds);
}
public void ClearSelection()
{
m_Editor.ClearSelection();
}
public void AddCurve(SerializedProperty curveProperty, Color curveColor, string name, bool visible = true)
{
if (m_Curves.ContainsKey(name))
return;
var state = CurveEditor.CurveState.defaultState;
state.color = curveColor;
state.minPointCount = 2;
m_Curves.Add(name, curveProperty);
m_Editor.Add(curveProperty, state);
}
public void RemoveCurve(string name)
{
if (!m_Curves.ContainsKey(name))
return;
m_Editor.Remove(m_Curves[name]);
}
public void Clear()
{
m_Curves.Clear();
m_Editor.RemoveAll();
}
public bool OnGUI(Rect drawRect)
{
return m_Editor.OnGUI(drawRect);
}
public bool OnGUILayout()
{
return OnGUILayout(m_WidgetDefaultHeight, m_WidgetShowToolbar);
}
public bool OnGUILayout(bool showToolbar)
{
return OnGUILayout(m_WidgetDefaultHeight, showToolbar);
}
public bool OnGUILayout(float height, bool showToolbar)
{
bool dirty = false;
using (new GUILayout.VerticalScope())
{
// Header
if(m_CurveEditName != null || m_CurveEditName == "")
GUILayout.Label(m_CurveEditName);
GUILayout.Space(4.0f);
// Curve Area
if(showToolbar)
{
using (new GUILayout.HorizontalScope(EditorStyles.toolbar))
{
foreach(KeyValuePair<string,SerializedProperty> kvp in m_Curves)
{
string name = kvp.Key;
SerializedProperty curve = kvp.Value;
CurveEditor.CurveState state = m_Editor.GetCurveState(curve);
bool b = GUILayout.Toggle(state.visible, name, EditorStyles.toolbarButton);
if (b != state.visible)
{
state.visible = b;
m_Editor.SetCurveState(curve, state);
}
}
GUILayout.FlexibleSpace();
}
}
Rect lastRect = GUILayoutUtility.GetLastRect();
Rect curveArea = GUILayoutUtility.GetRect(lastRect.width, height);
// Selection
CurveEditor.Selection selection = m_Editor.GetSelection();
if(selection.curve != null && selection.keyframe != null)
{
EditorGUI.indentLevel ++;
var key = selection.keyframe.Value;
Rect range = m_Editor.settings.bounds;
float t = EditorGUILayout.Slider("Time", key.time, range.xMin, range.xMax);
float v = EditorGUILayout.Slider("Value", key.value, range.yMin, range.yMax);
float inTgt = EditorGUILayout.FloatField("In Tangent", key.inTangent);
float outTgt = EditorGUILayout.FloatField("Out Tangent", key.outTangent);
if(t != key.time || v != key.value || inTgt != key.inTangent || outTgt != key.outTangent)
{
Keyframe newkey = new Keyframe(t,v,inTgt, outTgt);
m_Editor.SetKeyframe(selection.curve, selection.keyframeIndex, newkey);
}
EditorGUI.indentLevel--;
}
// Canvas
DrawCurveCanvas(curveArea);
dirty = m_Editor.OnGUI(curveArea);
}
return dirty;
}
public void DrawCurveCanvas(Rect rect)
{
EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.25f));
if(Event.current.type == EventType.Layout)
return;
GUI.BeginClip(rect);
Rect area = new Rect(Vector2.zero, rect.size);
rect = m_CurvePadding.Remove(area);
Rect bounds = m_Editor.settings.bounds;
float minInput = bounds.xMin;
float maxInput = bounds.xMax;
float minOutput = bounds.yMin;
float maxOutput = bounds.yMax;
//////////////////////////////////////////////////////////////////////////////
// Draw Origins
//////////////////////////////////////////////////////////////////////////////
float l = lineBrightnessValue;
Handles.color = new Color(l, l, l, 0.2f);
Handles.DrawLine(new Vector2(rect.xMin, area.yMin), new Vector2(rect.xMin, area.yMax));
Handles.DrawLine(new Vector2(area.xMin, rect.yMax), new Vector2(area.xMax, rect.yMax));
Handles.DrawLine(new Vector2(rect.xMax, area.yMin), new Vector2(rect.xMax, area.yMax));
Handles.DrawLine(new Vector2(area.xMin, rect.yMin), new Vector2(area.xMax, rect.yMin));
//////////////////////////////////////////////////////////////////////////////
// Draw Zero Axis'es
//////////////////////////////////////////////////////////////////////////////
if(minInput < 0 && maxInput > 0)
{
Handles.color = new Color(l, l, l, 0.6f);
Handles.DrawLine(new Vector2(0,rect.yMin),new Vector2(0,rect.yMax));
}
if(minOutput < 0 && maxOutput > 0)
{
Handles.color = new Color(l, l, l, 0.6f);
Handles.DrawLine(new Vector2(rect.xMin,0),new Vector2(rect.xMax, 0));
}
//////////////////////////////////////////////////////////////////////////////
// Draw Grid By Step
//////////////////////////////////////////////////////////////////////////////
Handles.color = new Color(l, l, l, 0.05f);
for(int i = 1; i < 8; i++) // Verticals
{
float step = Mathf.Lerp(rect.xMin, rect.xMax,(float)i / 8);
Handles.DrawLine(new Vector2(step, area.yMin), new Vector2(step, area.yMax));
}
for(int i = 1; i < 4; i++) // Horizontals
{
float step = Mathf.Lerp(rect.yMin, rect.yMax,(float)i / 4);
Handles.DrawLine(new Vector2(area.xMin, step), new Vector2(area.xMax, step));
}
//////////////////////////////////////////////////////////////////////////////
// Texts
//////////////////////////////////////////////////////////////////////////////
Rect minInRect = new Rect(rect.xMin, rect.yMax, 40, 12);
Rect maxInRect = new Rect(rect.xMax-40, rect.yMax, 40, 12);
Rect minOutRect = new Rect(rect.xMin-40, rect.yMax-12, 40, 12);
Rect maxOutRect = new Rect(rect.xMin-40, rect.yMin, 40, 12);
GUI.Label(minInRect, minInput.ToString("F2"), styles.smallLabelLeftAlign);
GUI.Label(maxInRect, maxInput.ToString("F2"), styles.smallLabelRightAlign);
GUI.Label(minOutRect, minOutput.ToString("F2"), styles.smallLabelRightAlign);
GUI.Label(maxOutRect, maxOutput.ToString("F2"), styles.smallLabelRightAlign);
//////////////////////////////////////////////////////////////////////////////
// Text on Zero Axis'es
//////////////////////////////////////////////////////////////////////////////
if(minInput < 0 && maxInput > 0)
{
Handles.color = new Color(l, l, l, 0.6f);
Handles.DrawLine(new Vector2(0,rect.yMin), new Vector2(0,rect.yMax));
}
if(minOutput < 0 && maxOutput > 0)
{
Handles.color = new Color(l, l, l, 0.6f);
Handles.DrawLine(new Vector2(rect.xMin,0),new Vector2(rect.xMax, 0));
}
// Custom delegate
if (OnPostGUI != null)
OnPostGUI(area, rect);
GUI.EndClip();
}
#region Styles
public Styles styles { get { if (m_Styles == null) m_Styles = new Styles(); return m_Styles; } }
private Styles m_Styles;
public class Styles
{
public GUIStyle smallLabelLeftAlign;
public GUIStyle smallLabelRightAlign;
public Styles()
{
smallLabelLeftAlign = new GUIStyle(EditorStyles.miniLabel);
smallLabelLeftAlign.alignment = TextAnchor.MiddleLeft;
smallLabelRightAlign = new GUIStyle(EditorStyles.miniLabel);
smallLabelRightAlign.alignment = TextAnchor.MiddleRight;
}
}
#endregion
}
}

12
com.unity.vfx-toolbox/Editor/Utility/CurveDrawer.cs.meta


fileFormatVersion: 2
guid: e70156dc82d6e394ca81e15807862054
timeCreated: 1473239983
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

59
com.unity.vfx-toolbox/Editor/Utility/CurveToTextureUtility.cs


using UnityEngine;
namespace UnityEditor.VFXToolbox
{
public class CurveToTextureUtility
{
public static void CurveToTexture(AnimationCurve curve, ref Texture2D texture)
{
if(texture != null && curve!= null && texture.height == 1 && texture.width > 1)
{
Color[] colors = new Color[texture.width];
for (int i = 0; i < texture.width; i++)
{
float t = (float)i / (texture.width - 1);
float v = curve.Evaluate(t);
colors[i] = new Color(v, v, v, 1);
}
texture.SetPixels(colors);
texture.Apply();
}
}
public static void GradientToTexture(Gradient gradient, ref Texture2D texture, bool linear = false)
{
if(texture != null && gradient != null && texture.height == 1 && texture.width > 1)
{
Color[] colors = new Color[texture.width];
for (int i = 0; i < texture.width; i++)
{
float t = (float)i / (texture.width - 1);
if(linear)
colors[i] = gradient.Evaluate(t).linear;
else
colors[i] = gradient.Evaluate(t);
}
texture.SetPixels(colors);
texture.Apply();
}
}
public static void GradientToTexture(Gradient gradient, AnimationCurve curve, ref Texture2D texture, bool linear = false)
{
if (texture != null && gradient != null && texture.height == 1 && texture.width > 1)
{
Color[] colors = new Color[texture.width];
for (int i = 0; i < texture.width; i++)
{
float t = (float)i / (texture.width - 1);
float b = curve.Evaluate(t);
if (linear)
colors[i] = b * gradient.Evaluate(t).linear;
else
colors[i] = b * gradient.Evaluate(t);
}
texture.SetPixels(colors);
texture.Apply();
}
}
}
}

12
com.unity.vfx-toolbox/Editor/Utility/CurveToTextureUtility.cs.meta


fileFormatVersion: 2
guid: 99231acc997bec24abf2c850c97b869e
timeCreated: 1474882560
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

699
com.unity.vfx-toolbox/Editor/Utility/FilterPopupWindow.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace UnityEditor.VFXToolbox
{
public interface IProvider
{
void CreateComponentTree(List<FilterPopupWindow.Element> tree);
bool GoToChild(FilterPopupWindow.Element element, bool addIfComponent);
}
[InitializeOnLoad]
public class FilterPopupWindow : EditorWindow
{
public static readonly float DefaultWidth = 240f;
public static readonly float DefaultHeight = 300f;
#region BaseElements
public class Element : IComparable
{
public int level;
public GUIContent content;
public string name
{
get { return content.text; }
}
public int CompareTo(object o)
{
return name.CompareTo((o as Element).name);
}
}
[Serializable]
public class GroupElement : Element
{
public Vector2 scroll;
public int selectedIndex = 0;
public GroupElement(int level, string name)
{
this.level = level;
content = new GUIContent(name);
}
public bool WantsFocus { get; protected set; }
public virtual bool ShouldDisable
{
get { return false; }
}
public virtual bool HandleKeyboard(Event evt, FilterPopupWindow w, Action goToParent)
{
return false;
}
public virtual bool OnGUI(FilterPopupWindow sFilterWindow)
{
return false;
}
}
#endregion
// Styles
class Styles
{
public GUIStyle header = (GUIStyle)typeof(EditorStyles).GetProperty("inspectorBig", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null);
public GUIStyle componentButton = new GUIStyle("PR Label"); //new GUIStyle (EditorStyles.label);
public GUIStyle groupButton;
public GUIStyle background = "grey_border";
public GUIStyle previewBackground = "PopupCurveSwatchBackground";
public GUIStyle previewHeader = new GUIStyle(EditorStyles.label);
public GUIStyle previewText = new GUIStyle(EditorStyles.wordWrappedLabel);
public GUIStyle rightArrow = "AC RightArrow";
public GUIStyle leftArrow = "AC LeftArrow";
public Styles()
{
header.font = EditorStyles.boldLabel.font;
componentButton.alignment = TextAnchor.MiddleLeft;
componentButton.padding.left -= 15;
componentButton.fixedHeight = 20;
groupButton = new GUIStyle(componentButton);
groupButton.padding.left += 17;
previewText.padding.left += 3;
previewText.padding.right += 3;
previewHeader.padding.left += 3 - 2;
previewHeader.padding.right += 3;
previewHeader.padding.top += 3;
previewHeader.padding.bottom += 2;
}
}
// Constants
private const int kHeaderHeight = 30;
private const int kWindowHeight = 400 - 80;
private const int kHelpHeight = 80 * 0;
private const string kComponentSearch = "NodeSearchString";
// Static variables
private static Styles s_Styles;
private static FilterPopupWindow s_FilterWindow = null;
private static long s_LastClosedTime;
private static bool s_DirtyList = false;
// Member variables
private IProvider m_Provider;
private Element[] m_Tree;
private Element[] m_SearchResultTree;
private List<GroupElement> m_Stack = new List<GroupElement>();
private float m_Anim = 1;
private int m_AnimTarget = 1;
private long m_LastTime = 0;
private bool m_ScrollToSelected = false;
private string m_DelayedSearch = null;
private string m_Search = "";
// Properties
private bool hasSearch { get { return !string.IsNullOrEmpty(m_Search); } }
private GroupElement activeParent { get { return m_Stack[m_Stack.Count - 2 + m_AnimTarget]; } }
private Element[] activeTree { get { return hasSearch ? m_SearchResultTree : m_Tree; } }
private Element activeElement
{
get
{
if (activeTree == null)
return null;
List<Element> children = GetChildren(activeTree, activeParent);
if (children.Count == 0)
return null;
return children[activeParent.selectedIndex];
}
}
private bool isAnimating { get { return m_Anim != m_AnimTarget; } }
// Methods
static FilterPopupWindow()
{
s_DirtyList = true;
}
void OnEnable()
{
s_FilterWindow = this;
m_Search = "";
}
void OnDisable()
{
s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;
s_FilterWindow = null;
}
internal static bool ValidateAddComponentMenuItem()
{
return true;
}
internal static bool Show(Vector2 position, IProvider provider)
{
// If the window is already open, close it instead.
UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(typeof(FilterPopupWindow));
if (wins.Length > 0)
{
try
{
((EditorWindow)wins[0]).Close();
return false;
}
catch (Exception)
{
s_FilterWindow = null;
}
}
// We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time.
long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond;
bool justClosed = nowMilliSeconds < s_LastClosedTime + 50;
if (!justClosed)
{
Event.current.Use();
if (s_FilterWindow == null)
s_FilterWindow = ScriptableObject.CreateInstance<FilterPopupWindow>();
s_FilterWindow.Init(position, provider);
return true;
}
return false;
}
private static object Invoke(Type t, object inst, string method, params object[] args)
{
var mi = t.GetMethod(method, (inst == null ? BindingFlags.Static : BindingFlags.Instance) | BindingFlags.NonPublic);
return mi.Invoke(inst, args);
}
void Init(Vector2 position, IProvider provider)
{
m_Provider = provider;
// Has to be done before calling Show / ShowWithMode
Vector2 pos = GUIUtility.GUIToScreenPoint(position);
Rect buttonRect = new Rect(pos.x - 32, pos.y - 16, DefaultWidth, 1);
CreateComponentTree();
ShowAsDropDown(buttonRect, new Vector2(buttonRect.width, kWindowHeight));
Focus();
wantsMouseMove = true;
}
private void CreateComponentTree()
{
var tree = new List<Element>();
m_Provider.CreateComponentTree(tree);
m_Tree = tree.ToArray();
// Rebuild stack
if (m_Stack.Count == 0)
m_Stack.Add(m_Tree[0] as GroupElement);
else
{
// The root is always the match for level 0
GroupElement match = m_Tree[0] as GroupElement;
int level = 0;
while (true)
{
// Assign the match for the current level
GroupElement oldElement = m_Stack[level];
m_Stack[level] = match;
m_Stack[level].selectedIndex = oldElement.selectedIndex;
m_Stack[level].scroll = oldElement.scroll;
// See if we reached last element of stack
level++;
if (level == m_Stack.Count)
break;
// Try to find a child of the same name as we had before
List<Element> children = GetChildren(activeTree, match);
Element childMatch = children.FirstOrDefault(c => c.name == m_Stack[level].name);
if (childMatch != null && childMatch is GroupElement)
{
match = childMatch as GroupElement;
}
else
{
// If we couldn't find the child, remove all further elements from the stack
while (m_Stack.Count > level)
m_Stack.RemoveAt(level);
}
}
}
//Debug.Log ("Rebuilt tree - "+m_Tree.Length+" elements");
s_DirtyList = false;
RebuildSearch();
}
internal void OnGUI()
{
if (s_Styles == null)
s_Styles = new Styles();
GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background);
if (s_DirtyList)
CreateComponentTree();
// Keyboard
HandleKeyboard();
GUILayout.Space(7);
// Search
if (!(activeParent.WantsFocus))
EditorGUI.FocusTextInControl("ComponentSearch");
Rect searchRect = GUILayoutUtility.GetRect(10, 20);
searchRect.x += 8;
searchRect.width -= 16;
GUI.SetNextControlName("ComponentSearch");
using (new DisabledScope(activeParent.ShouldDisable))
{
string newSearch = (string)Invoke(typeof(EditorGUI), null, "SearchField", searchRect, m_DelayedSearch ?? m_Search);
if (newSearch != m_Search || m_DelayedSearch != null)
{
if (!isAnimating)
{
m_Search = m_DelayedSearch ?? newSearch;
EditorPrefs.SetString(kComponentSearch, m_Search);
RebuildSearch();
m_DelayedSearch = null;
}
else
{
m_DelayedSearch = newSearch;
}
}
}
// Show lists
ListGUI(activeTree, m_Anim, GetElementRelative(0), GetElementRelative(-1));
if (m_Anim < 1)
ListGUI(activeTree, m_Anim + 1, GetElementRelative(-1), GetElementRelative(-2));
// Show help area
//DrawHelpArea (new Rect (0, position.height - kHelpHeight, position.width, kHelpHeight));
// Animate
if (isAnimating && Event.current.type == EventType.Repaint)
{
long now = System.DateTime.Now.Ticks;
float deltaTime = (now - m_LastTime) / (float)System.TimeSpan.TicksPerSecond;
m_LastTime = now;
m_Anim = Mathf.MoveTowards(m_Anim, m_AnimTarget, deltaTime * 4);
if (m_AnimTarget == 0 && m_Anim == 0)
{
m_Anim = 1;
m_AnimTarget = 1;
m_Stack.RemoveAt(m_Stack.Count - 1);
}
Repaint();
}
}
private void HandleKeyboard()
{
Event evt = Event.current;
if (evt.type == EventType.KeyDown)
{
// Special handling when in new script panel
if (!activeParent.HandleKeyboard(evt, s_FilterWindow, GoToParent))
{
// Always do these
if (evt.keyCode == KeyCode.DownArrow)
{
activeParent.selectedIndex++;
activeParent.selectedIndex = Mathf.Min(activeParent.selectedIndex, GetChildren(activeTree, activeParent).Count - 1);
m_ScrollToSelected = true;
evt.Use();
}
if (evt.keyCode == KeyCode.UpArrow)
{
activeParent.selectedIndex--;
activeParent.selectedIndex = Mathf.Max(activeParent.selectedIndex, 0);
m_ScrollToSelected = true;
evt.Use();
}
if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)
{
GoToChild(activeElement, true);
evt.Use();
}
// Do these if we're not in search mode
if (!hasSearch)
{
if (evt.keyCode == KeyCode.LeftArrow || evt.keyCode == KeyCode.Backspace)
{
GoToParent();
evt.Use();
}
if (evt.keyCode == KeyCode.RightArrow)
{
GoToChild(activeElement, false);
evt.Use();
}
if (evt.keyCode == KeyCode.Escape)
{
Close();
evt.Use();
}
}
}
}
}
const string kSearchHeader = "Search";
private void RebuildSearch()
{
if (!hasSearch)
{
m_SearchResultTree = null;
if (m_Stack[m_Stack.Count - 1].name == kSearchHeader)
{
m_Stack.Clear();
m_Stack.Add(m_Tree[0] as GroupElement);
}
m_AnimTarget = 1;
m_LastTime = System.DateTime.Now.Ticks;
return;
}
// Support multiple search words separated by spaces.
string[] searchWords = m_Search.ToLower().Split(' ');
// We keep two lists. Matches that matches the start of an item always get first priority.
List<Element> matchesStart = new List<Element>();
List<Element> matchesWithin = new List<Element>();
foreach (Element e in m_Tree)
{
if ((e is GroupElement)) //TODO RF
continue;
string name = e.name.ToLower().Replace(" ", "");
bool didMatchAll = true;
bool didMatchStart = false;
// See if we match ALL the seaarch words.
for (int w = 0; w < searchWords.Length; w++)
{
string search = searchWords[w];
if (name.Contains(search))
{
// If the start of the item matches the first search word, make a note of that.
if (w == 0 && name.StartsWith(search))
didMatchStart = true;
}
else
{
// As soon as any word is not matched, we disregard this item.
didMatchAll = false;
break;
}
}
// We always need to match all search words.
// If we ALSO matched the start, this item gets priority.
if (didMatchAll)
{
if (didMatchStart)
matchesStart.Add(e);
else
matchesWithin.Add(e);
}
}
matchesStart.Sort();
matchesWithin.Sort();
// Create search tree
List<Element> tree = new List<Element>();
// Add parent
tree.Add(new GroupElement(0, kSearchHeader));
// Add search results
tree.AddRange(matchesStart);
tree.AddRange(matchesWithin);
// Add the new script element
//tree.Add(m_Tree[m_Tree.Length - 1]);
// Create search result tree
m_SearchResultTree = tree.ToArray();
m_Stack.Clear();
m_Stack.Add(m_SearchResultTree[0] as GroupElement);
// Always select the first search result when search is changed (e.g. a character was typed in or deleted),
// because it's usually the best match.
if (GetChildren(activeTree, activeParent).Count >= 1)
activeParent.selectedIndex = 0;
else
activeParent.selectedIndex = -1;
}
private GroupElement GetElementRelative(int rel)
{
int i = m_Stack.Count + rel - 1;
if (i < 0)
return null;
return m_Stack[i] as GroupElement;
}
private void GoToParent()
{
if (m_Stack.Count > 1)
{
m_AnimTarget = 0;
m_LastTime = System.DateTime.Now.Ticks;
}
}
private void ListGUI(Element[] tree, float anim, GroupElement parent, GroupElement grandParent)
{
// Smooth the fractional part of the anim value
anim = Mathf.Floor(anim) + Mathf.SmoothStep(0, 1, Mathf.Repeat(anim, 1));
// Calculate rect for animated area
Rect animRect = position;
animRect.x = position.width * (1 - anim) + 1;
animRect.y = kHeaderHeight;
animRect.height -= kHeaderHeight + kHelpHeight;
animRect.width -= 2;
// Start of animated area (the part that moves left and right)
GUILayout.BeginArea(animRect);
// Header
Rect headerRect = GUILayoutUtility.GetRect(10, 25);
string name = parent.name;
GUI.Label(headerRect, name, s_Styles.header);
// Back button
if (grandParent != null)
{
Rect arrowRect = new Rect(headerRect.x + 4, headerRect.y + 7, 13, 13);
if (Event.current.type == EventType.Repaint)
s_Styles.leftArrow.Draw(arrowRect, false, false, false, false);
if (Event.current.type == EventType.MouseDown && headerRect.Contains(Event.current.mousePosition))
{
GoToParent();
Event.current.Use();
}
}
//GUILayout.Space (10);
if (!parent.OnGUI(s_FilterWindow))
ListGUI(tree, parent);
GUILayout.EndArea();
}
private void GoToChild(Element e, bool addIfComponent)
{
if(m_Provider.GoToChild(e, addIfComponent))
Close();
else if (!hasSearch)//TODO RF || e is NewElement)
{
m_LastTime = System.DateTime.Now.Ticks;
if (m_AnimTarget == 0)
m_AnimTarget = 1;
else if (m_Anim == 1)
{
m_Anim = 0;
m_Stack.Add(e as FilterPopupWindow.GroupElement);
}
}
}
private void ListGUI(Element[] tree, GroupElement parent)
{
// Start of scroll view list
parent.scroll = GUILayout.BeginScrollView(parent.scroll);
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
List<Element> children = GetChildren(tree, parent);
Rect selectedRect = new Rect();
// Iterate through the children
for (int i = 0; i < children.Count; i++)
{
Element e = children[i];
Rect r = GUILayoutUtility.GetRect(16, 20, GUILayout.ExpandWidth(true));
// Select the element the mouse cursor is over.
// Only do it on mouse move - keyboard controls are allowed to overwrite this until the next time the mouse moves.
if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDown)
{
if (parent.selectedIndex != i && r.Contains(Event.current.mousePosition))
{
parent.selectedIndex = i;
Repaint();
}
}
bool selected = false;
// Handle selected item
if (i == parent.selectedIndex)
{
selected = true;
selectedRect = r;
}
// Draw element
if (Event.current.type == EventType.Repaint)
{
GUIStyle labelStyle = (e is GroupElement) ? s_Styles.groupButton : s_Styles.componentButton;
labelStyle.Draw(r, e.content, false, false, selected, selected);
if ((e is GroupElement))
{
Rect arrowRect = new Rect(r.x + r.width - 13, r.y + 4, 13, 13);
s_Styles.rightArrow.Draw(arrowRect, false, false, false, false);
}
}
if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition))
{
Event.current.Use();
parent.selectedIndex = i;
GoToChild(e, true);
}
}
EditorGUIUtility.SetIconSize(Vector2.zero);
GUILayout.EndScrollView();
// Scroll to show selected
if (m_ScrollToSelected && Event.current.type == EventType.Repaint)
{
m_ScrollToSelected = false;
Rect scrollRect = GUILayoutUtility.GetLastRect();
if (selectedRect.yMax - scrollRect.height > parent.scroll.y)
{
parent.scroll.y = selectedRect.yMax - scrollRect.height;
Repaint();
}
if (selectedRect.y < parent.scroll.y)
{
parent.scroll.y = selectedRect.y;
Repaint();
}
}
}
private List<Element> GetChildren(Element[] tree, Element parent)
{
List<Element> children = new List<Element>();
int level = -1;
int i = 0;
for (i = 0; i < tree.Length; i++)
{
if (tree[i] == parent)
{
level = parent.level + 1;
i++;
break;
}
}
if (level == -1)
return children;
for (; i < tree.Length; i++)
{
Element e = tree[i];
if (e.level < level)
break;
if (e.level > level && !hasSearch)
continue;
children.Add(e);
}
return children;
}
}
public struct DisabledScope : IDisposable
{
private static Stack<bool> s_EnabledStack = new Stack<bool>();
bool m_Disposed;
public DisabledScope(bool disabled)
{
m_Disposed = false;
s_EnabledStack.Push(GUI.enabled);
GUI.enabled &= !disabled;
}
public void Dispose()
{
if (m_Disposed)
return;
m_Disposed = true;
if (s_EnabledStack.Count > 0)
GUI.enabled = s_EnabledStack.Pop();
}
}
}

12
com.unity.vfx-toolbox/Editor/Utility/FilterPopupWindow.cs.meta


fileFormatVersion: 2
guid: cf782fd1355b6a14bb9f026693fe111c
timeCreated: 1485512158
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

21
com.unity.vfx-toolbox/Editor/Utility/FloatSliderPropertyDrawer.cs


using UnityEngine;
using UnityEngine.VFXToolbox;
namespace UnityEditor.VFXToolbox
{
[CustomPropertyDrawer(typeof(FloatSliderAttribute))]
public class FloatSliderPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
FloatSliderAttribute floatSliderAttribute = attribute as FloatSliderAttribute;
if(property.propertyType == SerializedPropertyType.Float)
{
EditorGUI.Slider(position, property, floatSliderAttribute.m_ValueMin, floatSliderAttribute.m_ValueMax);
}
else
EditorGUI.LabelField(position, label, "(FloatSliderProperty can only be used with float attributes)");
}
}
}

12
com.unity.vfx-toolbox/Editor/Utility/FloatSliderPropertyDrawer.cs.meta


fileFormatVersion: 2
guid: b906391f203061740a413d469a9fa304
timeCreated: 1471966526
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/Editor/Utility/Shaders.meta


fileFormatVersion: 2
guid: 175bf1ad95f5c7240b11877e3eced98b
folderAsset: yes
timeCreated: 1475654884
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

56
com.unity.vfx-toolbox/Editor/Utility/Shaders/BlitRect.shader


Shader "Hidden/VFXToolbox/BlitRect"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Rect ("Rect", Vector) = (0.0,0.0,1.0,1.0)
}
SubShader
{
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
LOD 100
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float4 _Rect;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = v.vertex;
o.vertex.xy = (v.vertex.xy / _Rect.zw) - _Rect.xy;
o.texcoord = o.vertex;
o.vertex.y = 1.0f - o.vertex.y;
o.vertex = o.vertex * 2 - 1;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.texcoord);
return col;
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/Editor/Utility/Shaders/BlitRect.shader.meta


fileFormatVersion: 2
guid: 8c674c47209b57a4ab266f4371e5501c
timeCreated: 1475655065
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

108
com.unity.vfx-toolbox/Editor/Utility/Splitter.cs


using UnityEngine;
using System;
using System.IO;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox
{
public class Splitter
{
public enum SplitLockMode
{
None = 0,
BothMinSize = 1,
LeftMinMax = 2,
RightMinMax = 3
}
public float value
{
get { return m_SplitterValue; }
set { SetSplitterValue(value); }
}
public delegate void SplitViewOnGUIDelegate(Rect drawRect);
private SplitViewOnGUIDelegate m_onDrawLeftDelegate;
private SplitViewOnGUIDelegate m_onDrawRightDelegate;
private float m_SplitterValue;
private bool m_Resize;
private SplitLockMode m_LockMode;
private Vector2 m_LockValues;
public Splitter(float initialLeftWidth, SplitViewOnGUIDelegate onDrawLeftDelegate, SplitViewOnGUIDelegate onDrawRightDelegate, SplitLockMode lockMode, Vector2 lockValues)
{
m_SplitterValue = initialLeftWidth;
m_onDrawLeftDelegate = onDrawLeftDelegate;
m_onDrawRightDelegate = onDrawRightDelegate;
m_LockMode = lockMode;
if (((int)lockMode > 1) && (lockValues.y < lockValues.x))
m_LockValues = new Vector2(lockValues.y, lockValues.x);
else
m_LockValues = lockValues;
}
public bool DoSplitter(Rect rect)
{
if(m_onDrawLeftDelegate != null)
{
m_onDrawLeftDelegate(new Rect(rect.x, rect.y, m_SplitterValue, rect.height));
}
if(m_onDrawRightDelegate != null)
{
m_onDrawRightDelegate(new Rect(rect.x + m_SplitterValue, rect.y, rect.width - m_SplitterValue, rect.height));
}
HandlePanelResize(rect);
return m_Resize;
}
private void SetSplitterValue(float Value)
{
m_SplitterValue = Value;
}
private void HandlePanelResize(Rect rect)
{
Rect resizeActiveArea = new Rect(rect.x + m_SplitterValue - 8, rect.y, 16, rect.height);
EditorGUIUtility.AddCursorRect(resizeActiveArea, MouseCursor.ResizeHorizontal);
if (Event.current.type == EventType.MouseDown && resizeActiveArea.Contains(Event.current.mousePosition))
m_Resize = true;
if (m_Resize)
{
value = Event.current.mousePosition.x;
}
switch(m_LockMode)
{
case SplitLockMode.BothMinSize:
m_SplitterValue = Mathf.Clamp(m_SplitterValue, m_LockValues.x, rect.width - m_LockValues.y);
break;
case SplitLockMode.LeftMinMax:
m_SplitterValue = Mathf.Clamp(m_SplitterValue, m_LockValues.x, m_LockValues.y);
break;
case SplitLockMode.RightMinMax:
m_SplitterValue = Mathf.Clamp(m_SplitterValue, rect.width - m_LockValues.y, rect.width - m_LockValues.x);
break;
default:
break;
}
RectOffset o = new RectOffset(7, 8, 0, 0);
EditorGUI.DrawRect(o.Remove(resizeActiveArea), new Color(0,0,0,1.0f));
if (Event.current.type == EventType.MouseUp)
m_Resize = false;
}
}
}

12
com.unity.vfx-toolbox/Editor/Utility/Splitter.cs.meta


fileFormatVersion: 2
guid: a7133f5114a741e44b47d1111f070e39
timeCreated: 1476694621
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

210
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxGUIUtility.cs


using UnityEngine;
using System;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox
{
class VFXToolboxGUIUtility
{
#region GUIContent caching
private static Dictionary<string, GUIContent> s_GUIContentCache;
public static GUIContent Get(string textAndTooltip)
{
return GetTextAndIcon(textAndTooltip, null);
}
public static GUIContent GetTextAndIcon(string textAndTooltip, string icon)
{
if (s_GUIContentCache == null)
s_GUIContentCache = new Dictionary<string, GUIContent>();
if (string.IsNullOrEmpty(textAndTooltip))
return GUIContent.none;
GUIContent content;
if (!s_GUIContentCache.TryGetValue(textAndTooltip, out content))
{
var s = textAndTooltip.Split('|');
if (!string.IsNullOrEmpty(icon))
{
var iconContent = EditorGUIUtility.IconContent(icon);
content = new GUIContent(s[0], iconContent.image);
}
else
{
content = new GUIContent(s[0]);
}
if (s.Length > 1 && !string.IsNullOrEmpty(s[1]))
content.tooltip = s[1];
s_GUIContentCache.Add(textAndTooltip, content);
}
return content;
}
public static void Clear()
{
s_GUIContentCache.Clear();
}
#endregion
#region ProgressBar Handling
private static double s_LastProgressBarTime;
/// <summary>
/// Displays a progress bar with delay and optional cancel button
/// </summary>
/// <param name="title">title of the window</param>
/// <param name="message">message</param>
/// <param name="progress">progress</param>
/// <param name="delay">minimum delay before displaying window</param>
/// <param name="cancelable">is the window cancellable?</param>
/// <returns>true if cancelled, false otherwise</returns>
public static bool DisplayProgressBar(string title, string message, float progress, float delay = 0.0f, bool cancelable = false)
{
if(s_LastProgressBarTime < 0.0)
s_LastProgressBarTime = EditorApplication.timeSinceStartup;
if (EditorApplication.timeSinceStartup - s_LastProgressBarTime > delay)
{
if(cancelable)
{
return EditorUtility.DisplayCancelableProgressBar(title, message, progress);
}
else
{
EditorUtility.DisplayProgressBar(title, message, progress);
return false;
}
}
return false;
}
/// <summary>
/// Clears the current progressbar
/// </summary>
public static void ClearProgressBar()
{
s_LastProgressBarTime = -1.0;
EditorUtility.ClearProgressBar();
}
#endregion
#region Other GUI Utils
public static void GUIRotatedLabel(Rect position, string label, float angle, GUIStyle style)
{
var matrix = GUI.matrix;
var rect = new Rect(position.x - 10f, position.y, position.width, position.height);
GUIUtility.RotateAroundPivot(angle, rect.center);
GUI.Label(rect, label, style);
GUI.matrix = matrix;
}
#endregion
#region ToggleableHeader
public static bool ToggleableHeader(bool enabled, bool bToggleable, string title)
{
Rect rect = GUILayoutUtility.GetRect(16f, 32f, VFXToolboxStyles.Header);
using (new EditorGUI.DisabledGroupScope(!enabled))
{
GUI.Box(rect, title, VFXToolboxStyles.Header);
}
if(bToggleable)
{
Rect toggleRect = new Rect(rect.x + 10f, rect.y + 6f, 13f, 13f);
if (Event.current.type == EventType.Repaint)
VFXToolboxStyles.HeaderCheckBox.Draw(toggleRect, false, false, enabled, false);
Event e = Event.current;
if (e.type == EventType.MouseDown)
{
if (toggleRect.Contains(e.mousePosition))
{
enabled = !enabled;
e.Use();
}
}
}
return enabled;
}
#endregion
#region Tabbed Buttons
public static int TabbedButtonsGUILayout(int value, string[] labels, bool[] enabled)
{
int count = labels.Length;
int selected = value;
if (labels.Length != enabled.Length)
throw new ArgumentException("Labels or enabled arrays does not match count for EnumTabbedButtons()");
int i = 0;
using (new EditorGUILayout.HorizontalScope())
{
foreach(string label in labels)
{
GUIStyle style = (i == 0) ? VFXToolboxStyles.TabButtonLeft : ((i == count - 1) ? VFXToolboxStyles.TabButtonRight : VFXToolboxStyles.TabButtonMid);
using (new EditorGUI.DisabledScope(!enabled[i]))
{
bool val = GUILayout.Toggle(selected == i, Get(label), style, GUILayout.Height(24));
if(val != (selected == i))
{
selected = i;
}
}
i++;
}
}
return selected;
}
#endregion
#region Custom Scopes
public class HeaderSectionScope : GUI.Scope
{
public HeaderSectionScope(string headerText)
{
EditorGUILayout.LabelField(Get(headerText), s_Styles.header);
EditorGUI.indentLevel += 1;
}
protected override void CloseScope()
{
EditorGUI.indentLevel -= 1;
GUILayout.Label(GUIContent.none, s_Styles.separator);
}
static Styles s_Styles = new Styles();
private class Styles
{
public GUIStyle header;
public GUIStyle separator;
public Styles()
{
header = new GUIStyle(EditorStyles.boldLabel);
header.margin = new RectOffset(0, 0, 0, 12);
separator = new GUIStyle("sv_iconselector_sep");
separator.margin = new RectOffset(0, 0, 8, 0);
}
}
}
#endregion
}
}

12
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxGUIUtility.cs.meta


fileFormatVersion: 2
guid: 46694eeb11886f24ab5b4ab6f92265e9
timeCreated: 1471966525
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

80
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxStyles.cs


using UnityEngine;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox
{
public static class VFXToolboxStyles
{
// Custom Toggleable Header (in VFXToolboxGUIUtility)
public static GUIStyle Header;
public static GUIStyle HeaderCheckBox;
// Tab Buttons
public static GUIStyle TabButtonLeft;
public static GUIStyle TabButtonSingle;
public static GUIStyle TabButtonMid;
public static GUIStyle TabButtonRight;
// Toolbar Related
public static GUIStyle toolbarButton;
public static GUIStyle toolbarTextField;
public static GUIStyle toolbarLabelLeft;
// Labels
public static GUIStyle LargeLabel;
public static GUIStyle miniLabel;
public static GUIStyle miniLabelRight;
public static GUIStyle miniLabelCenter;
// Misc
public static GUIStyle RListLabel;
static VFXToolboxStyles()
{
Header = new GUIStyle("ShurikenModuleTitle");
HeaderCheckBox = new GUIStyle("ShurikenCheckMark");
Header.font = (new GUIStyle("Label")).font;
Header.fontSize = 12;
Header.fontStyle = FontStyle.Bold;
Header.border = new RectOffset(15, 7, 4, 4);
Header.margin = new RectOffset(0, 0, 16, 0);
Header.fixedHeight = 28;
Header.contentOffset = new Vector2(32f, -2f);
TabButtonSingle = new GUIStyle(EditorStyles.miniButton);
TabButtonLeft = new GUIStyle(EditorStyles.miniButtonLeft);
TabButtonMid = new GUIStyle(EditorStyles.miniButtonMid);
TabButtonRight = new GUIStyle(EditorStyles.miniButtonRight);
TabButtonSingle.fontSize = 12;
TabButtonLeft.fontSize = 12;
TabButtonMid.fontSize = 12;
TabButtonRight.fontSize = 12;
LargeLabel = new GUIStyle(EditorStyles.largeLabel);
RListLabel = new GUIStyle(EditorStyles.label);
toolbarButton = new GUIStyle(EditorStyles.toolbarButton);
toolbarButton.padding = new RectOffset();
toolbarButton.margin = new RectOffset();
toolbarLabelLeft = new GUIStyle(EditorStyles.miniLabel);
toolbarLabelLeft.alignment = TextAnchor.MiddleLeft;
toolbarLabelLeft.contentOffset = new Vector2(-2, -4);
toolbarTextField = new GUIStyle(EditorStyles.toolbarTextField);
toolbarTextField.padding = new RectOffset(2,2,2,2);
toolbarTextField.margin = new RectOffset(2,2,2,2);
LargeLabel.alignment = TextAnchor.UpperRight;
miniLabel = new GUIStyle(EditorStyles.miniLabel);
miniLabelRight = new GUIStyle(EditorStyles.miniLabel);
miniLabelRight.alignment = TextAnchor.MiddleRight;
miniLabelCenter = new GUIStyle(EditorStyles.miniLabel);
miniLabelCenter.alignment = TextAnchor.MiddleCenter;
}
}
}

12
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxStyles.cs.meta


fileFormatVersion: 2
guid: 49a77d36083c9474e9611de5a530eb91
timeCreated: 1478251652
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

116
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxUtility.cs


using UnityEngine;
using System;
using System.IO;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox
{
public class VFXToolboxUtility
{
#region Readback utils
public static Color[] ReadBack(RenderTexture renderTexture)
{
RenderTexture backup = RenderTexture.active;
RenderTexture.active = renderTexture;
bool hdr = false;
if (renderTexture.format == RenderTextureFormat.ARGBHalf)
hdr = true;
Texture2D texture = new Texture2D(renderTexture.width, renderTexture.height, hdr ? TextureFormat.RGBAHalf : TextureFormat.RGBA32, false);
texture.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
//texture.Apply();
RenderTexture.active = backup;
return texture.GetPixels();
}
#endregion
#region Asset Utils
public static bool IsDirectory(string path)
{
if (path.Length > 0 && Directory.Exists(path))
return true;
return false;
}
public static bool IsDirectorySelected()
{
var path = "";
var obj = Selection.activeObject;
if (obj == null) path = "Assets";
else path = AssetDatabase.GetAssetPath(obj.GetInstanceID());
return IsDirectory(path);
}
public static string[] GetAllTexturesInPath(string path)
{
List<string> files = new List<string>();
string absolutePath = Application.dataPath + "/" + path.Remove(0, 7);
string [] fileEntries = Directory.GetFiles(absolutePath);
int count = fileEntries.Length;
int i = 0;
foreach(string fileName in fileEntries)
{
string fname = fileName.Replace('\\', '/');
int index = fname.LastIndexOf('/');
string localPath = path;
if (index > 0)
localPath += fname.Substring(index);
VFXToolboxGUIUtility.DisplayProgressBar("Image Sequencer", "Discovering Assets in folder...", (float)i/count);
Texture2D t = AssetDatabase.LoadAssetAtPath<Texture2D>(localPath);
if(t != null)
files.Add(localPath);
i++;
}
VFXToolboxGUIUtility.ClearProgressBar();
return files.ToArray();
}
#endregion
#region ReflectionUtils
public static IEnumerable<Type> FindConcreteSubclasses<T>()
{
List<Type> types = new List<Type>();
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type[] assemblyTypes = null;
try
{
assemblyTypes = domainAssembly.GetTypes();
}
catch(Exception)
{
Debug.LogWarning("Cannot access assembly: " + domainAssembly);
assemblyTypes = null;
}
if (assemblyTypes != null)
foreach (var assemblyType in assemblyTypes)
if (assemblyType.IsSubclassOf(typeof(T)) && !assemblyType.IsAbstract)
types.Add (assemblyType);
}
return types;
}
#endregion
#region GraphicUtils
public static void BlitRect(Rect rect, RenderTexture target, Texture texture, Material material = null)
{
RenderTexture backup = RenderTexture.active;
RenderTexture.active = target;
GL.PushMatrix();
GL.LoadPixelMatrix(0, target.width, target.height, 0);
Graphics.DrawTexture(rect, texture, material);
GL.PopMatrix();
RenderTexture.active = backup;
}
#endregion
}
}

12
com.unity.vfx-toolbox/Editor/Utility/VFXToolboxUtility.cs.meta


fileFormatVersion: 2
guid: e4d0ab18b4d169e4284296fcddc58096
timeCreated: 1471966526
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer.meta


fileFormatVersion: 2
guid: c15717f283b1d3e47a49dc05c4e1afe8
folderAsset: yes
timeCreated: 1471965337
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders.meta


fileFormatVersion: 2
guid: dbd095a2e7603c644a980b9344813b8d
folderAsset: yes
timeCreated: 1478254072
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

97
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Blur.shader


Shader "VFXToolbox/ImageSequencer/Blur"
{
Properties
{
_Radius("Radius", range(0.0,10.0)) = 3
[Enum(RGBA,0,Alpha,1,RGB,2)] _ApplyBlur("Apply Blur", Int) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
// // z, w : (unused)
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
float _Radius;
int _ApplyBlur;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
half4 blur(sampler2D s, float2 t, float2 size, float r)
{
int rad = r;
half4 col = half4(0,0,0,0);
float2 invSize = 1.0f/size;
for(float i = -rad; i <= rad; i++)
{
for(float j = -rad; j <= rad; j++)
{
col += tex2D(s,t+(invSize*float2(i,j)));
}
}
return col / (((2*rad)+1)*((2*rad)+1));
}
half4 frag (v2f input) : SV_Target
{
half4 src = tex2D(_InputFrame,input.uv);
half4 col = blur(_InputFrame, input.uv, _FrameData.xy, _Radius);
half3 dstRGB = col.rgb;
half dstA = col.a;
if(_ApplyBlur == 1) dstRGB = src.rgb;
if(_ApplyBlur == 2) dstA = src.a;
return half4(dstRGB,dstA);
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Blur.shader.meta


fileFormatVersion: 2
guid: 67cfb370fc1c4104bbf7930165bb3d4b
timeCreated: 1478611277
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

140
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/HeightToNormal.shader


Shader "VFXToolbox/ImageSequencer/HeightToNormal"
{
Properties
{
[Enum(Red,0,Green,1,Blue,2,Alpha,3)] _HeightSource("Input Channel for Height Source", Int) = 3
[Enum(Red,0,Green,1,Blue,2,Alpha,3,None,4)] _AlphaChannel("Input Channel for Alpha Output", Int) = 3
_HeightScale("Height Scale", Range(0.0,150.0)) = 25
_Radius("Radius", Range(1.0,5.0)) = 1.0
_Spherize("Spherize", Range(0.0,1.0)) = 0.0
[Enum(Low,4,Medium,8,High,16)] _NumSamples("Sample Count", Int) = 8
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
// // z, w : (unused)
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
int _HeightSource;
int _AlphaChannel;
int _NumSamples;
float _HeightScale;
float _Radius;
float _Spherize;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
half3 position(sampler2D s, float2 t)
{
half4 w = tex2D(s,t);
float h;
if(_HeightSource == 0) h = w.r;
if(_HeightSource == 1) h = w.g;
if(_HeightSource == 2) h = w.b;
if(_HeightSource == 3) h = w.a;
float x = t.x *_FrameData.x;
float y = t.y *_FrameData.y;
float z = h *_HeightScale;
// Spherize
float2 ssc = float2(t.x - 0.5f , t.y - 0.5f) * 1.414213562373095f;
z += _Spherize * (1.0f - dot(ssc, ssc)) * 200;
return float3(x, y, z);
}
half3 normal(sampler2D s, float2 t, float r)
{
float2 invSize = 1.0f/_FrameData.xy;
float3 pos = position(s,t);
float3 nrm = float3(0,0,0);
float step = UNITY_PI*2*(1.0/(_NumSamples*2));
int numRings = ceil(r);
for(int j = 1; j <= numRings ; j++)
{
float rad = r * ((float)j/numRings);
for(int i = 0; i < (_NumSamples*2); i+=2)
{
float angle = i*step;
float2 offset = float2(cos(angle),sin(angle)) * invSize * rad;
float3 sampleA = position(s, t+offset);
angle = (i+1)*step;
offset = float2(cos(angle),sin(angle)) * invSize * rad;
float3 sampleB = position(s, t+offset);
nrm += normalize(cross(sampleA-pos, sampleB-pos));
}
}
nrm = normalize(nrm);
//nrm += float3(_Spherize * pow(float2(t - 0.5f)*2.0f,5.0f),0.0f);
return nrm;
}
half4 frag (v2f input) : SV_Target
{
float alpha;
half4 col = tex2D(_InputFrame,input.uv);
if(_AlphaChannel == 0) alpha = col.r;
if(_AlphaChannel == 1) alpha = col.g;
if(_AlphaChannel == 2) alpha = col.b;
if(_AlphaChannel == 3) alpha = col.a;
if(_AlphaChannel == 4) alpha = 1.0f;
half3 nrml = normal(_InputFrame, input.uv, _Radius);
return half4((nrml * 0.5)+0.5,alpha);
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/HeightToNormal.shader.meta


fileFormatVersion: 2
guid: 68f6507ff55de254db370dcb132f5b4e
timeCreated: 1478611277
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

100
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/LightNormals.shader


Shader "VFXToolbox/ImageSequencer/LightNormals"
{
Properties
{
_Orientation("Orientation", Range(0.0,360.0)) = 0.0
_GrazingAngle("Grazing Angle", Range(0.0,90.0)) = 0.0
_BaseColor("Base Color", Color) = (1.0,1.0,1.0,1.0)
_AmbientColor("Ambient Color", Color) = (0.1,0.15,0.2,1.0)
_LightColor("Light Color", Color) = (1.0,1.0,1.0,1.0)
_LightBrightness("Light Brightness", Range(0.0,10.0)) = 1.0
_LightExponent("Light Exponent", Range(1.0, 10.0)) = 2.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
// // z, w : (unused)
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
float _Orientation;
float _GrazingAngle;
float4 _BaseColor;
float4 _LightColor;
float _LightBrightness;
float _LightExponent;
float4 _AmbientColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
half3 latLonToXYZ(float lat, float lon)
{
lat = (lat / 360) * 2 * UNITY_PI;
lon = (lon / 360) * 2 * UNITY_PI;
float x = cos(lat)*cos(lon);
float y = cos(lat)*sin(lon);
float z = sin(lat);
return half3(x,y,z);
}
half4 frag (v2f i) : SV_Target
{
half4 tex = tex2D(_InputFrame, i.uv);
half3 nrm = tex.rgb*2-1;
half3 lightdir = latLonToXYZ(_GrazingAngle, _Orientation);
half3 color = _BaseColor*((pow(saturate(dot(nrm,lightdir)*0.5+0.5),_LightExponent) * _LightColor * _LightBrightness) + _AmbientColor);
return half4(color,tex.a);
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/LightNormals.shader.meta


fileFormatVersion: 2
guid: 5be8ac80f90d85540845a26c7fafdaa9
timeCreated: 1478611277
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

68
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Negative.shader


Shader "VFXToolbox/ImageSequencer/Negative"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
// // z, w : (unused)
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
half4 frag (v2f i) : SV_Target
{
half4 col = tex2D(_InputFrame, i.uv);
half3 rgb = LinearToGammaSpace(col.rgb);
return half4(GammaToLinearSpace(1-rgb),col.a);
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Negative.shader.meta


fileFormatVersion: 2
guid: 0f56c58ead6305e4db16de20ca259856
timeCreated: 1478611277
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

89
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Rotate.shader


Shader "VFXToolbox/ImageSequencer/Rotate"
{
Properties
{
_Angle("Angle", Range(0.0,360.0)) = 0.0
_RotationCenter("Center of Rotation", Vector) = (0.5,0.5,0.0,0.0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
// ImageSequencer CustomMaterial uniforms
// ======================================
//
// sampler2D _InputFrame; // Input Frame (from previous sequence)
//
// float4 _FrameData; // Frame Data
// // x, y : width (x) and height (y) in pixels
// // z, w : sequence index (z) and length (w)
//
// float4 _FlipbookData; // Flipbook Data
// // x, y : number of columns (x) and rows (y)
// // z, w : (unused)
sampler2D _InputFrame;
float4 _FrameData;
float4 _FlipbookData;
float _Angle;
float2 _RotationCenter;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
float2 rotate2D(float2 TexCoord, float2 Center, float Angle) {
float2 AngleCoords = float2(sin(Angle%(2*UNITY_PI)),cos(Angle%(2*UNITY_PI)));
TexCoord -= Center;
return Center +
float2(
TexCoord.x*AngleCoords.y - TexCoord.y * AngleCoords.x,
TexCoord.x*AngleCoords.x + TexCoord.y * AngleCoords.y
);
}
half4 frag (v2f i) : SV_Target
{
float2 nm = floor(i.uv*_FlipbookData.xy)/_FlipbookData.xy;
float2 frameuv = frac(i.uv * _FlipbookData.xy);
frameuv = saturate(rotate2D(frameuv, _RotationCenter, (_Angle / 360) * UNITY_PI * 2));
half4 col = tex2D(_InputFrame, (frameuv/_FlipbookData.xy)+nm);
return col;
}
ENDCG
}
}
}

9
com.unity.vfx-toolbox/ImageSequencer/CustomMaterialShaders/Rotate.shader.meta


fileFormatVersion: 2
guid: 0709f816418bb514e8025d1455fdcc45
timeCreated: 1478611277
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer/Editor.meta


fileFormatVersion: 2
guid: b089fc59037435549b98ce54579918cb
folderAsset: yes
timeCreated: 1460544600
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes.meta


fileFormatVersion: 2
guid: b2170b9213417b94584e56c4a7f985d4
folderAsset: yes
timeCreated: 1485434907
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

20
com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes/ProcessorAttribute.cs


using UnityEngine;
using System;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
[AttributeUsage(AttributeTargets.Class)]
public class ProcessorAttribute : Attribute
{
public readonly string category;
public readonly string name;
public readonly Type processorType;
public ProcessorAttribute(string category, string name, Type processorType)
{
this.category = category;
this.name = name;
this.processorType = processorType;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/Attributes/ProcessorAttribute.cs.meta


fileFormatVersion: 2
guid: 1d6b5f22b3e06424e92e5aa2d216b8bf
timeCreated: 1485434907
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources.meta


fileFormatVersion: 2
guid: fc42ab04392773d40b0121c0abfac68b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

4
com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources/ImageSequence Icon.png

之前 之后
宽度: 64  |  高度: 64  |  大小: 1.8 KiB

92
com.unity.vfx-toolbox/ImageSequencer/Editor/EditorResources/ImageSequence Icon.png.meta


fileFormatVersion: 2
guid: e444a0e95c20b4442885c0a4f1468245
timeCreated: 1485447509
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters.meta


fileFormatVersion: 2
guid: 480a6ceec94297a489f2583204dc68f0
folderAsset: yes
timeCreated: 1465462056
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

477
com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniEXR.cs


using UnityEngine;
using UnityEditor.VFXToolbox;
// MiniEXR 2013 by Aras Pranckevicius / Unity Technologies.
//
// C# conversion by Ilya Suzdalnitski.
// Slightly Modified by Thomas Ich�
//
// Writes OpenEXR RGB files out of half-precision RGBA or RGB data.
//
namespace MiniEXR {
//Based on source-forge project: http://sourceforge.net/projects/csharp-half/
internal static class HalfHelper
{
private static uint[] mantissaTable = GenerateMantissaTable();
private static uint[] exponentTable = GenerateExponentTable();
private static ushort[] offsetTable = GenerateOffsetTable();
private static ushort[] baseTable = GenerateBaseTable();
private static sbyte[] shiftTable = GenerateShiftTable();
// Transforms the subnormal representation to a normalized one.
private static uint ConvertMantissa(int i)
{
uint m = (uint)(i << 13); // Zero pad mantissa bits
uint e = 0; // Zero exponent
// While not normalized
while ((m & 0x00800000) == 0)
{
e -= 0x00800000; // Decrement exponent (1<<23)
m <<= 1; // Shift mantissa
}
m &= unchecked((uint)~0x00800000); // Clear leading 1 bit
e += 0x38800000; // Adjust bias ((127-14)<<23)
return m | e; // Return combined number
}
private static uint[] GenerateMantissaTable()
{
uint[] mantissaTable = new uint[2048];
mantissaTable[0] = 0;
for (int i = 1; i < 1024; i++)
{
mantissaTable[i] = ConvertMantissa(i);
}
for (int i = 1024; i < 2048; i++)
{
mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));
}
return mantissaTable;
}
private static uint[] GenerateExponentTable()
{
uint[] exponentTable = new uint[64];
exponentTable[0] = 0;
for (int i = 1; i < 31; i++)
{
exponentTable[i] = (uint)(i << 23);
}
exponentTable[31] = 0x47800000;
exponentTable[32] = 0x80000000;
for (int i = 33; i < 63; i++)
{
exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));
}
exponentTable[63] = 0xc7800000;
return exponentTable;
}
private static ushort[] GenerateOffsetTable()
{
ushort[] offsetTable = new ushort[64];
offsetTable[0] = 0;
for (int i = 1; i < 32; i++)
{
offsetTable[i] = 1024;
}
offsetTable[32] = 0;
for (int i = 33; i < 64; i++)
{
offsetTable[i] = 1024;
}
return offsetTable;
}
private static ushort[] GenerateBaseTable()
{
ushort[] baseTable = new ushort[512];
for (int i = 0; i < 256; ++i)
{
sbyte e = (sbyte)(127 - i);
if (e > 24)
{ // Very small numbers map to zero
baseTable[i | 0x000] = 0x0000;
baseTable[i | 0x100] = 0x8000;
}
else if (e > 14)
{ // Small numbers map to denorms
baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));
baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);
}
else if (e >= -15)
{ // Normal numbers just lose precision
baseTable[i | 0x000] = (ushort)((15 - e) << 10);
baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);
}
else if (e > -128)
{ // Large numbers map to Infinity
baseTable[i | 0x000] = 0x7c00;
baseTable[i | 0x100] = 0xfc00;
}
else
{ // Infinity and NaN's stay Infinity and NaN's
baseTable[i | 0x000] = 0x7c00;
baseTable[i | 0x100] = 0xfc00;
}
}
return baseTable;
}
private static sbyte[] GenerateShiftTable()
{
sbyte[] shiftTable = new sbyte[512];
for (int i = 0; i < 256; ++i)
{
sbyte e = (sbyte)(127 - i);
if (e > 24)
{ // Very small numbers map to zero
shiftTable[i | 0x000] = 24;
shiftTable[i | 0x100] = 24;
}
else if (e > 14)
{ // Small numbers map to denorms
shiftTable[i | 0x000] = (sbyte)(e - 1);
shiftTable[i | 0x100] = (sbyte)(e - 1);
}
else if (e >= -15)
{ // Normal numbers just lose precision
shiftTable[i | 0x000] = 13;
shiftTable[i | 0x100] = 13;
}
else if (e > -128)
{ // Large numbers map to Infinity
shiftTable[i | 0x000] = 24;
shiftTable[i | 0x100] = 24;
}
else
{ // Infinity and NaN's stay Infinity and NaN's
shiftTable[i | 0x000] = 13;
shiftTable[i | 0x100] = 13;
}
}
return shiftTable;
}
public static float HalfToSingle(ushort half)
{
uint result = mantissaTable[offsetTable[half >> 10] + (half & 0x3ff)] + exponentTable[half >> 10];
return System.BitConverter.ToSingle( System.BitConverter.GetBytes( result ), 0 );
//return *((float*)&result);
}
public static ushort SingleToHalf(float single)
{
//uint value = *((uint*)&single);
uint value = System.BitConverter.ToUInt32( System.BitConverter.GetBytes( single ), 0 );
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return result;
}
}
public static class MiniEXR {
// Writes EXR into a memory buffer.
// Input:
// - (width) x (height) image,
// - channels=4: 8 bytes per pixel (R,G,B,A order, 16 bit float per channel; alpha ignored), or
// - channels=3: 6 bytes per pixel (R,G,B order, 16 bit float per channel).
// Returns memory buffer with .EXR contents and buffer size in outSize. free() the buffer when done with it.
public static void MiniEXRWrite (string _filePath, uint _width, uint _height, bool _ExportAlpha, Color[] _colorArray, bool bFlipVertical) {
byte[] bytes = MiniEXRWrite(_width, _height, _ExportAlpha, _colorArray, bFlipVertical);
System.IO.File.WriteAllBytes(_filePath, bytes );
}
public static byte[] MiniEXRWrite (uint _width, uint _height, bool _ExportAlpha, Color[] _colorArray, bool bFlipVertical = false)
{
if (bFlipVertical)
_colorArray = FlipVertical(_colorArray, _width, _height);
byte stride = (byte)(_ExportAlpha ? 4 : 3);
float[] rgbaArray = new float[ _colorArray.Length * stride ];
for (int i = 0; i < _colorArray.Length; i++)
{
rgbaArray[i * stride] = _colorArray[i].r;
rgbaArray[i * stride + 1] = _colorArray[i].g;
rgbaArray[i * stride + 2] = _colorArray[i].b;
if(_ExportAlpha)
rgbaArray[i * stride + 3] = _colorArray[i].a;
}
return MiniEXRWrite(_width, _height, stride, rgbaArray);
}
private static Color[] FlipVertical(Color[] input, uint _width, uint _height)
{
Color[] output = new Color[input.Length];
uint k = 0;
for(int j = (int)_height-1; j >= 0; j--)
{
for (int i = 0; i < _width; i++)
{
int idx = i + (j * (int)_width);
output[k] = input[idx];
k++;
}
}
return output;
}
public static byte[] MiniEXRWrite (uint _width, uint _height, uint _channels, float[] _rgbaArray)
{
//const void* rgba16f
uint ww = _width-1;
uint hh = _height-1;
byte[] kHeader;
if(_channels == 3)
{
kHeader = new byte[] {
0x76, 0x2f, 0x31, 0x01, // magic
2, 0, 0, 0, // version, scanline
// channels
(byte)'c',(byte)'h',(byte)'a',(byte)'n',(byte)'n',(byte)'e',(byte)'l',(byte)'s',0,
(byte)'c',(byte)'h',(byte)'l',(byte)'i',(byte)'s',(byte)'t',0,
55,0,0,0,
(byte)'B',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // R, half
(byte)'G',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // G, half
(byte)'R',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // B, half
0,
// compression
(byte)'c',(byte)'o',(byte)'m',(byte)'p',(byte)'r',(byte)'e',(byte)'s',(byte)'s',(byte)'i',(byte)'o',(byte)'n',0,
(byte)'c',(byte)'o',(byte)'m',(byte)'p',(byte)'r',(byte)'e',(byte)'s',(byte)'s',(byte)'i',(byte)'o',(byte)'n',0,
1,0,0,0,
0, // no compression
// dataWindow
(byte)'d',(byte)'a',(byte)'t',(byte)'a',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',0,
(byte)'b',(byte)'o',(byte)'x',(byte)'2',(byte)'i',0,
16,0,0,0,
0,0,0,0,0,0,0,0,
(byte)(ww&0xFF), (byte)((ww>>8)&0xFF), (byte)((ww>>16)&0xFF), (byte)((ww>>24)&0xFF),
(byte)(hh&0xFF), (byte)((hh>>8)&0xFF), (byte)((hh>>16)&0xFF), (byte)((hh>>24)&0xFF),
// displayWindow
(byte)'d',(byte)'i',(byte)'s',(byte)'p',(byte)'l',(byte)'a',(byte)'y',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',0,
(byte)'b',(byte)'o',(byte)'x',(byte)'2',(byte)'i',0,
16,0,0,0,
0,0,0,0,0,0,0,0,
(byte)(ww&0xFF), (byte)((ww>>8)&0xFF), (byte)((ww>>16)&0xFF), (byte)((ww>>24)&0xFF),
(byte)(hh&0xFF), (byte)((hh>>8)&0xFF), (byte)((hh>>16)&0xFF), (byte)((hh>>24)&0xFF),
// lineOrder
(byte)'l',(byte)'i',(byte)'n',(byte)'e',(byte)'O',(byte)'r',(byte)'d',(byte)'e',(byte)'r',0,
(byte)'l',(byte)'i',(byte)'n',(byte)'e',(byte)'O',(byte)'r',(byte)'d',(byte)'e',(byte)'r',0,
1,0,0,0,
0, // increasing Y
// pixelAspectRatio
(byte)'p',(byte)'i',(byte)'x',(byte)'e',(byte)'l',(byte)'A',(byte)'s',(byte)'p',(byte)'e',(byte)'c',(byte)'t',(byte)'R',(byte)'a',(byte)'t',(byte)'i',(byte)'o',0,
(byte)'f',(byte)'l',(byte)'o',(byte)'a',(byte)'t',0,
4,0,0,0,
0,0,0x80,0x3f, // 1.0f
// screenWindowCenter
(byte)'s',(byte)'c',(byte)'r',(byte)'e',(byte)'e',(byte)'n',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',(byte)'C',(byte)'e',(byte)'n',(byte)'t',(byte)'e',(byte)'r',0,
(byte)'v',(byte)'2',(byte)'f',0,
8,0,0,0,
0,0,0,0, 0,0,0,0,
// screenWindowWidth
(byte)'s',(byte)'c',(byte)'r',(byte)'e',(byte)'e',(byte)'n',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',(byte)'W',(byte)'i',(byte)'d',(byte)'t',(byte)'h',0,
(byte)'f',(byte)'l',(byte)'o',(byte)'a',(byte)'t',0,
4,0,0,0,
0,0,0x80,0x3f, // 1.0f
// end of header
0,
};
}
else
{
kHeader = new byte[] {
0x76, 0x2f, 0x31, 0x01, // magic
2, 0, 0, 0, // version, scanline
// channels
(byte)'c',(byte)'h',(byte)'a',(byte)'n',(byte)'n',(byte)'e',(byte)'l',(byte)'s',0,
(byte)'c',(byte)'h',(byte)'l',(byte)'i',(byte)'s',(byte)'t',0,
55,0,0,0,
(byte)'A',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // A, half
(byte)'B',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // R, half
(byte)'G',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // G, half
(byte)'R',0, 1,0,0,0, 0, 0,0,0,1,0,0,0,1,0,0,0, // B, half
0,
// compression
(byte)'c',(byte)'o',(byte)'m',(byte)'p',(byte)'r',(byte)'e',(byte)'s',(byte)'s',(byte)'i',(byte)'o',(byte)'n',0,
(byte)'c',(byte)'o',(byte)'m',(byte)'p',(byte)'r',(byte)'e',(byte)'s',(byte)'s',(byte)'i',(byte)'o',(byte)'n',0,
1,0,0,0,
0, // no compression
// dataWindow
(byte)'d',(byte)'a',(byte)'t',(byte)'a',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',0,
(byte)'b',(byte)'o',(byte)'x',(byte)'2',(byte)'i',0,
16,0,0,0,
0,0,0,0,0,0,0,0,
(byte)(ww&0xFF), (byte)((ww>>8)&0xFF), (byte)((ww>>16)&0xFF), (byte)((ww>>24)&0xFF),
(byte)(hh&0xFF), (byte)((hh>>8)&0xFF), (byte)((hh>>16)&0xFF), (byte)((hh>>24)&0xFF),
// displayWindow
(byte)'d',(byte)'i',(byte)'s',(byte)'p',(byte)'l',(byte)'a',(byte)'y',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',0,
(byte)'b',(byte)'o',(byte)'x',(byte)'2',(byte)'i',0,
16,0,0,0,
0,0,0,0,0,0,0,0,
(byte)(ww&0xFF), (byte)((ww>>8)&0xFF), (byte)((ww>>16)&0xFF), (byte)((ww>>24)&0xFF),
(byte)(hh&0xFF), (byte)((hh>>8)&0xFF), (byte)((hh>>16)&0xFF), (byte)((hh>>24)&0xFF),
// lineOrder
(byte)'l',(byte)'i',(byte)'n',(byte)'e',(byte)'O',(byte)'r',(byte)'d',(byte)'e',(byte)'r',0,
(byte)'l',(byte)'i',(byte)'n',(byte)'e',(byte)'O',(byte)'r',(byte)'d',(byte)'e',(byte)'r',0,
1,0,0,0,
0, // increasing Y
// pixelAspectRatio
(byte)'p',(byte)'i',(byte)'x',(byte)'e',(byte)'l',(byte)'A',(byte)'s',(byte)'p',(byte)'e',(byte)'c',(byte)'t',(byte)'R',(byte)'a',(byte)'t',(byte)'i',(byte)'o',0,
(byte)'f',(byte)'l',(byte)'o',(byte)'a',(byte)'t',0,
4,0,0,0,
0,0,0x80,0x3f, // 1.0f
// screenWindowCenter
(byte)'s',(byte)'c',(byte)'r',(byte)'e',(byte)'e',(byte)'n',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',(byte)'C',(byte)'e',(byte)'n',(byte)'t',(byte)'e',(byte)'r',0,
(byte)'v',(byte)'2',(byte)'f',0,
8,0,0,0,
0,0,0,0, 0,0,0,0,
// screenWindowWidth
(byte)'s',(byte)'c',(byte)'r',(byte)'e',(byte)'e',(byte)'n',(byte)'W',(byte)'i',(byte)'n',(byte)'d',(byte)'o',(byte)'w',(byte)'W',(byte)'i',(byte)'d',(byte)'t',(byte)'h',0,
(byte)'f',(byte)'l',(byte)'o',(byte)'a',(byte)'t',0,
4,0,0,0,
0,0,0x80,0x3f, // 1.0f
// end of header
0,
};
}
uint kHeaderSize = (uint)kHeader.Length;
uint kScanlineTableSize = 8 * _height;
uint pixelRowSize = _width * _channels * 2;
uint fullRowSize = pixelRowSize + 8;
uint bufSize = kHeaderSize + kScanlineTableSize + _height * fullRowSize;
byte[] buf = new byte[bufSize];
// copy in header
int bufI = 0;
for (int i = 0; i < kHeaderSize; i++) {
buf[ bufI ] = kHeader[i];
bufI++;
}
// line offset table
uint ofs = kHeaderSize + kScanlineTableSize;
for (int y = 0; y < _height; ++y)
{
buf[ bufI++ ] = (byte)(ofs & 0xFF);
buf[ bufI++ ] = (byte)((ofs >> 8) & 0xFF);
buf[ bufI++ ] = (byte)((ofs >> 16) & 0xFF);
buf[ bufI++ ] = (byte)((ofs >> 24) & 0xFF);
buf[ bufI++ ] = 0;
buf[ bufI++ ] = 0;
buf[ bufI++ ] = 0;
buf[ bufI++ ] = 0;
ofs += fullRowSize;
}
//Convert float to half float
ushort[] srcHalf = new ushort[_rgbaArray.Length];
for (int i = 0; i < _rgbaArray.Length; i++) {
//Gamma encode before converting : no
//_rgbaArray[i] = Mathf.Pow(_rgbaArray[i], 2.2f);
srcHalf[i] = HalfHelper.SingleToHalf( _rgbaArray[i] );
}
uint srcDataI = 0;
for (int y = 0; y < _height; y++)
{
// coordinate
buf[ bufI++ ] = (byte)(y & 0xFF);
buf[ bufI++ ] = (byte)((y >> 8) & 0xFF);
buf[ bufI++ ] = (byte)((y >> 16) & 0xFF);
buf[ bufI++ ] = (byte)((y >> 24) & 0xFF);
// data size
buf[ bufI++ ] = (byte)(pixelRowSize & 0xFF);
buf[ bufI++ ] = (byte)((pixelRowSize >> 8) & 0xFF);
buf[ bufI++ ] = (byte)((pixelRowSize >> 16) & 0xFF);
buf[ bufI++ ] = (byte)((pixelRowSize >> 24) & 0xFF);
// B, G, R
//memcpy (ptr, src, width*6); //Copy first line - 6 bits, 2 bits per channel
uint tempSrcI;
//If _channels == 4, write Alpha
if(_channels == 4)
{
tempSrcI = srcDataI;
for (int x = 0; x < _width; ++x)
{
//Blue
byte[] halfBytes = System.BitConverter.GetBytes( srcHalf[ tempSrcI + 3 ] );
buf[ bufI++ ] = halfBytes[0];
buf[ bufI++ ] = halfBytes[1];
tempSrcI += _channels;
}
}
//First copy a line of B
tempSrcI = srcDataI;
for (int x = 0; x < _width; ++x)
{
//Blue
byte[] halfBytes = System.BitConverter.GetBytes( srcHalf[ tempSrcI + 2 ] );
buf[ bufI++ ] = halfBytes[0];
buf[ bufI++ ] = halfBytes[1];
tempSrcI += _channels;
}
//Then copy a line of G
tempSrcI = srcDataI;
for (int x = 0; x < _width; ++x)
{
//Blue
byte[] halfBytes = System.BitConverter.GetBytes( srcHalf[ tempSrcI + 1 ] );
buf[ bufI++ ] = halfBytes[0];
buf[ bufI++ ] = halfBytes[1];
tempSrcI += _channels;
}
//Finally copy a line of R
tempSrcI = srcDataI;
for (int x = 0; x < _width; ++x)
{
//Blue
byte[] halfBytes = System.BitConverter.GetBytes( srcHalf[ tempSrcI ] );
buf[ bufI++ ] = halfBytes[0];
buf[ bufI++ ] = halfBytes[1];
tempSrcI += _channels;
}
srcDataI += _width * _channels;
}
return buf;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniEXR.cs.meta


fileFormatVersion: 2
guid: be9b913bdcccabf4aa59739f61686a41
timeCreated: 1465462056
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

65
com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniTGA.cs


using System;
using UnityEngine;
using UnityEditor.VFXToolbox;
namespace MiniTGA
{
public static class MiniTGA
{
// Writes TGA into a memory buffer.
// Input:
// - (width) x (height) image,
// - channels=4: RGBA 32bit
// - channels=3: RGB 24bit
// Returns memory buffer with uncompressed, unpalettized Targa contents and buffer size in outSize. free() the buffer when done with it.
public static void MiniTGAWrite (string _filePath, ushort _width, ushort _height, bool _exportalpha, Color[] _colorArray) {
byte[] bytes = MiniTGAWrite(_width, _height, _exportalpha, _colorArray);
System.IO.File.WriteAllBytes(_filePath, bytes);
}
public static byte[] MiniTGAWrite (ushort _width, ushort _height, bool _exportalpha, Color[] _colorArray)
{
byte[] kHeader = // TRUEVISION TARGA HEADER 18 bytes
{
0, // No ID Field 1
0, // No ColorMap 1
2, // Uncompressed 1
0,0,0,0,0, // Null Dummies for Color Map 5
0,0, // X Origin = 0 2
0,0, // Y Origin = 0 2
(byte)(_width % 256), (byte)(_width >> 8), // Width 2
(byte)(_height % 256), (byte)(_height >> 8), // Height 2
(byte)(_exportalpha ? 32 : 24), // Bit depth 1
0 // End Descriptor 1
};
byte stride = (byte)(_exportalpha ? 4 : 3);
int size = kHeader.Length + (_width * _height * stride);
byte[] buffer = new byte[size];
// Copy Header into buffer
Buffer.BlockCopy(kHeader, 0, buffer, 0, kHeader.Length);
// Image Positionning
int pos = kHeader.Length;
int count = _colorArray.Length;
int i = 0;
foreach(Color c in _colorArray)
{
buffer[pos] = (byte)(Mathf.Clamp01(c.b) * 255);
buffer[pos+1] = (byte)(Mathf.Clamp01(c.g) * 255);
buffer[pos+2] = (byte)(Mathf.Clamp01(c.r) * 255);
if(_exportalpha)
buffer[pos+3] = (byte)(Mathf.Clamp01(c.a) * 255);
pos += stride;
i++;
}
return buffer;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/Exporters/MiniTGA.cs.meta


fileFormatVersion: 2
guid: 335ff1d947896f2428a2587cc539d0a6
timeCreated: 1465462056
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup.meta


fileFormatVersion: 2
guid: 412b3158d6b5a3140b557976c0a4f63e
folderAsset: yes
timeCreated: 1485512158
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

121
com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup/ProcessorDataProvider.cs


using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEditor;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public class ProcessorDataProvider : IProvider
{
private Dictionary<Type, ProcessorAttribute> m_dataSource;
private FrameProcessorStack m_processorStack;
private ImageSequence m_CurrentAsset;
public class ProcessorElement : FilterPopupWindow.Element
{
public Action<ProcessorElement> m_SpawnCallback;
public ProcessorAttribute m_Desc;
public Type m_ProcessorSettingType;
public ProcessorElement(int level, KeyValuePair<Type, ProcessorAttribute> desc, Action<ProcessorElement> spawncallback)
{
this.level = level;
content = new GUIContent(EditorGUIUtility.IconContent("SceneViewFx"));
content.text = desc.Value.name;
m_Desc = desc.Value;
m_ProcessorSettingType = desc.Key;
m_SpawnCallback = spawncallback;
}
}
internal ProcessorDataProvider(FrameProcessorStack stack, ImageSequence asset)
{
m_dataSource = stack.settingsDefinitions;
m_processorStack = stack;
m_CurrentAsset = asset;
}
public void CreateComponentTree(List<FilterPopupWindow.Element> tree)
{
tree.Add(new FilterPopupWindow.GroupElement(0, "Add new Processor..."));
var processors = m_dataSource.ToList();
processors.Sort((processorA, processorB) => {
int res = processorA.Value.category.CompareTo(processorB.Value.category);
return res != 0 ? res : processorA.Value.name.CompareTo(processorB.Value.name);
});
HashSet<string> categories = new HashSet<string>();
foreach( KeyValuePair<Type, ProcessorAttribute> desc in processors)
{
int i = 0;
if(!categories.Contains(desc.Value.category) && desc.Value.category != "")
{
string[] split = desc.Value.category.Split('/');
string current = "";
while(i < split.Length)
{
current += split[i];
if(!categories.Contains(current))
tree.Add(new FilterPopupWindow.GroupElement(i+1,split[i]));
i++;
current += "/";
}
categories.Add(desc.Value.category);
}
else
{
i = desc.Value.category.Split('/').Length;
}
if (desc.Value.category != "")
i++;
tree.Add(new ProcessorElement(i, desc, AddProcessor));
}
}
public void AddProcessor(ProcessorElement element)
{
var settingType = element.m_ProcessorSettingType;
// Add Element
Undo.RecordObject(m_CurrentAsset, "Add Processor");
FrameProcessor processor = null;
// Reflection Stuff here
ProcessorAttribute attribute = m_processorStack.settingsDefinitions[settingType];
Type processorType = attribute.processorType;
var info = ProcessorInfo.CreateDefault(attribute.name, true, settingType);
processor = (FrameProcessor)Activator.CreateInstance(processorType, m_processorStack, info);
if(processor != null)
{
m_processorStack.AddProcessor(processor, m_CurrentAsset);
m_processorStack.InvalidateAll();
}
}
public bool GoToChild(FilterPopupWindow.Element element, bool addIfComponent)
{
if (element is ProcessorElement)
{
((ProcessorElement)element).m_SpawnCallback.Invoke((ProcessorElement)element);
return true;
}
return false;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/FilterPopup/ProcessorDataProvider.cs.meta


fileFormatVersion: 2
guid: ad769a5a4d1115645bd4121e6d470566
timeCreated: 1485512158
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

278
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessor.cs


using UnityEngine;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public abstract class FrameProcessor
{
public int OutputWidth
{
get {
if (Enabled)
return GetOutputWidth();
else
return
InputSequence.width;
}
}
public int OutputHeight
{
get
{
if (Enabled)
return GetOutputHeight();
else
return
InputSequence.width;
}
}
public int NumU
{
get {
if (Enabled)
return GetNumU();
else
return InputSequence.numU;
}
}
public int NumV
{
get {
if (Enabled)
return GetNumV();
else
return InputSequence.numV;
}
}
public bool GenerateMipMaps;
public bool Linear;
public bool Enabled { get{ return m_bEnabled; } set {SetEnabled(value); } }
public ProcessingFrameSequence InputSequence
{
get { return m_ProcessorStack.GetInputSequence(this); }
}
public ProcessingFrameSequence OutputSequence
{
get { if (m_bEnabled) return m_OutputSequence; else return InputSequence; }
}
public ProcessorInfo ProcessorInfo
{
get { return m_ProcessorInfo; }
}
protected FrameProcessorStack m_ProcessorStack;
protected ProcessingFrameSequence m_OutputSequence;
protected bool m_bEnabled;
protected int m_OutputWidth;
protected int m_OutputHeight;
protected ProcessorInfo m_ProcessorInfo;
public FrameProcessor(FrameProcessorStack processorStack, ProcessorInfo info)
{
m_ProcessorInfo = info;
m_ProcessorInfo.ProcessorName = GetName();
m_bEnabled = m_ProcessorInfo.Enabled;
m_ProcessorStack = processorStack;
m_OutputSequence = new ProcessingFrameSequence(this);
Linear = true;
GenerateMipMaps = true;
}
public void SetEnabled(bool value)
{
m_bEnabled = value;
var info = new SerializedObject(m_ProcessorInfo);
info.Update();
info.FindProperty("Enabled").boolValue = value;
info.ApplyModifiedProperties();
}
public virtual void Dispose()
{
m_OutputSequence.Dispose();
}
public void Refresh()
{
if(Enabled != m_ProcessorInfo.Enabled)
Enabled = m_ProcessorInfo.Enabled;
UpdateSequenceLength();
UpdateOutputSize();
}
protected virtual void UpdateOutputSize()
{
SetOutputSize(InputSequence.width, InputSequence.height);
}
protected virtual int GetOutputWidth()
{
UpdateOutputSize();
return m_OutputWidth;
}
protected virtual int GetOutputHeight()
{
UpdateOutputSize();
return m_OutputHeight;
}
public void SetOutputSize(int width, int height)
{
if(m_OutputWidth != width || m_OutputHeight != height)
{
m_OutputWidth = Mathf.Clamp(width,1,8192);
m_OutputHeight = Mathf.Clamp(height,1,8192);
}
}
protected abstract int GetNumU();
protected abstract int GetNumV();
protected bool DrawSidePanelHeader()
{
bool bHasChanged = false;
bool previousEnabled = Enabled;
Enabled = VFXToolboxGUIUtility.ToggleableHeader(Enabled, false, GetName());
if(previousEnabled != Enabled)
{
SerializedObject o = new SerializedObject(m_ProcessorInfo);
o.FindProperty("Enabled").boolValue = Enabled;
o.ApplyModifiedProperties();
m_ProcessorStack.Invalidate(this);
bHasChanged = true;
}
return bHasChanged;
}
protected abstract bool DrawSidePanelContent(bool hasChanged);
public abstract bool OnSidePanelGUI(ImageSequence asset, int ProcessorIndex);
public abstract bool OnCanvasGUI(ImageSequencerCanvas canvas);
public virtual void RequestProcessOneFrame(int currentFrame)
{
int length = OutputSequence.length;
int i = (currentFrame + 1) % length;
while (i != currentFrame)
{
bool advance = false;
if(OutputSequence.frames[i].dirty)
{
advance = OutputSequence.Process(i);
if(advance) return;
}
i = (i + 1);
i %= length;
}
}
public abstract bool Process(int frame);
public virtual int GetProcessorSequenceLength()
{
return InputSequence.length;
}
public bool Process(ProcessingFrame frame)
{
return Process(OutputSequence.frames.IndexOf(frame));
}
public void UpdateSequenceLength()
{
int currentCount = m_OutputSequence.frames.Count;
int requiredCount = GetProcessorSequenceLength();
if (currentCount == requiredCount)
return;
if(currentCount > requiredCount)
{
for(int i = requiredCount - 1; i < currentCount - 1; i++)
{
m_OutputSequence.frames[i].Dispose();
}
m_OutputSequence.frames.RemoveRange(requiredCount - 1, currentCount - requiredCount);
}
else
{
for(int i = 0; i < requiredCount - currentCount; i++)
{
m_OutputSequence.frames.Add(new ProcessingFrame(this));
}
}
}
public virtual void Invalidate()
{
UpdateSequenceLength();
SetOutputSize(GetOutputWidth(), GetOutputHeight());
m_OutputSequence.InvalidateAll();
FrameProcessor next = m_ProcessorStack.GetNextProcessor(this);
if(next != null)
next.Invalidate();
}
public abstract string GetName();
public virtual string GetLabel()
{
return GetName();
}
public override string ToString()
{
return GetLabel() + (Enabled ? "" : " (Disabled)");
}
public abstract ProcessorSettingsBase GetSettingsAbstract();
}
public abstract class FrameProcessor<T> : FrameProcessor where T : ProcessorSettingsBase
{
public T settings { get { return m_Settings; } private set { m_Settings = value; m_SerializedObject = new SerializedObject(m_Settings); } }
private T m_Settings;
protected SerializedObject m_SerializedObject;
public FrameProcessor(FrameProcessorStack stack, ProcessorInfo info) : base(stack, info)
{
m_ProcessorInfo = info;
settings = (T)m_ProcessorInfo.Settings;
}
public override bool OnSidePanelGUI(ImageSequence asset, int ProcessorIndex)
{
bool bHasChanged = DrawSidePanelHeader();
using (new EditorGUI.DisabledScope(!Enabled))
{
m_SerializedObject.Update();
bHasChanged = DrawSidePanelContent(bHasChanged);
m_SerializedObject.ApplyModifiedProperties();
}
return bHasChanged;
}
public sealed override ProcessorSettingsBase GetSettingsAbstract()
{
return settings;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessor.cs.meta


fileFormatVersion: 2
guid: 41d9351ae1420d640af2102cd1a09969
timeCreated: 1460732283
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

158
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.Serialization.cs


using UnityEngine;
using System;
using System.Reflection;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class FrameProcessorStack
{
public void AddSettingsObjectToAsset(ImageSequence asset, ScriptableObject settings)
{
AssetDatabase.AddObjectToAsset(settings,asset);
settings.hideFlags = HideFlags.HideInHierarchy;
}
public void AddProcessorInfoObjectToAsset(ImageSequence asset, ProcessorInfo info)
{
AssetDatabase.AddObjectToAsset(info,asset);
info.hideFlags = HideFlags.HideInHierarchy;
}
public void RemoveAllInputFrames(ImageSequence asset)
{
asset.inputFrameGUIDs.Clear();
m_InputSequence.frames.Clear();
EditorUtility.SetDirty(asset);
}
public void SortAllInputFrames(ImageSequence asset)
{
asset.inputFrameGUIDs.Sort((guidA,guidB) => {
return string.Compare(AssetDatabase.GUIDToAssetPath(guidA), AssetDatabase.GUIDToAssetPath(guidB));
});
EditorUtility.SetDirty(asset);
}
public void ReverseAllInputFrames(ImageSequence asset)
{
asset.inputFrameGUIDs.Reverse();
EditorUtility.SetDirty(asset);
}
public void LoadFramesFromAsset(ImageSequence asset)
{
inputSequence.frames.Clear();
if (asset.inputFrameGUIDs != null && asset.inputFrameGUIDs.Count > 0)
{
int count = asset.inputFrameGUIDs.Count;
int i = 1;
foreach (string guid in asset.inputFrameGUIDs)
{
VFXToolboxGUIUtility.DisplayProgressBar("Image Sequencer", "Loading Textures (" + i + "/" + count + ")", (float)i/count, 0.1f);
string path = AssetDatabase.GUIDToAssetPath(guid);
Texture2D t = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if (t != null)
{
inputSequence.frames.Add(new ProcessingFrame(t));
}
else
{
inputSequence.frames.Add(ProcessingFrame.Missing);
}
i++;
}
VFXToolboxGUIUtility.ClearProgressBar();
}
}
public void SyncFramesToAsset(ImageSequence asset)
{
asset.inputFrameGUIDs.Clear();
foreach(ProcessingFrame f in inputSequence.frames)
{
asset.inputFrameGUIDs.Add(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(f.texture)));
}
EditorUtility.SetDirty(asset);
}
public void AddProcessor(FrameProcessor processor, ImageSequence asset)
{
AddProcessorInfoObjectToAsset(asset, processor.ProcessorInfo);
asset.processorInfos.Add(processor.ProcessorInfo);
ProcessorSettingsBase settings = processor.GetSettingsAbstract();
if (settings != null)
{
AddSettingsObjectToAsset(asset, settings);
processor.ProcessorInfo.Settings = settings;
}
m_Processors.Add(processor);
EditorUtility.SetDirty(asset);
}
public void RemoveAllProcessors(ImageSequence asset)
{
asset.processorInfos.Clear();
m_Processors.Clear();
EditorUtility.SetDirty(asset);
}
public void RemoveProcessor(int index, ImageSequence asset)
{
asset.processorInfos.RemoveAt(index);
m_Processors.RemoveAt(index);
EditorUtility.SetDirty(asset);
}
public void ReorderProcessors(ImageSequence asset)
{
if(m_Processors.Count > 0)
{
List<FrameProcessor> old = new List<FrameProcessor>();
foreach(FrameProcessor p in m_Processors)
{
old.Add(p);
}
m_Processors.Clear();
foreach(ProcessorInfo info in asset.processorInfos)
{
foreach(FrameProcessor p in old)
{
if(p.ProcessorInfo.Equals(info))
{
m_Processors.Add(p);
break;
}
}
}
EditorUtility.SetDirty(asset);
}
}
public void LoadProcessorsFromAsset(ImageSequence asset)
{
m_Processors.Clear();
var infos = asset.processorInfos;
UpdateProcessorsFromAssembly();
// Creating Runtime
foreach(ProcessorInfo procInfo in infos)
{
Type processorType = settingsDefinitions[procInfo.Settings.GetType()].processorType;
var processor = (FrameProcessor)Activator.CreateInstance(processorType, this, procInfo);
m_Processors.Add(processor);
}
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.Serialization.cs.meta


fileFormatVersion: 2
guid: a1e35fc6527c7334baf151504ef8930a
timeCreated: 1463737821
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

143
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.cs


using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class FrameProcessorStack
{
public ProcessingFrameSequence inputSequence
{
get
{
return m_InputSequence;
}
}
public ProcessingFrameSequence outputSequence
{
get
{
if (m_Processors.Count > 0)
return m_Processors[m_Processors.Count - 1].OutputSequence;
else
return m_InputSequence;
}
}
public ImageSequencer imageSequencer
{
get { return m_ImageSequencer; }
}
public List<FrameProcessor> processors
{
get
{
return m_Processors;
}
}
private List<FrameProcessor> m_Processors;
private ProcessingFrameSequence m_InputSequence;
private ImageSequencer m_ImageSequencer;
public FrameProcessorStack(ProcessingFrameSequence inputSequence, ImageSequencer imageSequencer)
{
m_InputSequence = inputSequence;
m_Processors = new List<FrameProcessor>();
m_ImageSequencer = imageSequencer;
}
public void Dispose()
{
foreach(FrameProcessor p in m_Processors)
{
p.Dispose();
}
m_Processors.Clear();
}
public ProcessingFrameSequence GetOutputSequence()
{
if(m_Processors.Count > 0)
{
return m_Processors[m_Processors.Count - 1].OutputSequence;
}
else
{
return inputSequence;
}
}
public ProcessingFrameSequence GetInputSequence(FrameProcessor processor)
{
int index = m_Processors.IndexOf(processor);
if (index > 0)
{
return m_Processors[index - 1].OutputSequence;
}
else
return m_InputSequence;
}
public FrameProcessor GetNextProcessor(FrameProcessor processor)
{
int index = m_Processors.IndexOf(processor);
if(index < m_Processors.Count-1)
{
return m_Processors[index + 1];
}
return null;
}
public void Invalidate(FrameProcessor processor)
{
int index = m_Processors.IndexOf(processor);
if(index != -1)
m_Processors[index].Invalidate();
}
public void InvalidateAll()
{
if (m_Processors.Count > 0)
m_Processors[0].Invalidate();
}
public Dictionary<Type, ProcessorAttribute> settingsDefinitions { get; private set; }
public void UpdateProcessorsFromAssembly()
{
settingsDefinitions = new Dictionary<Type, ProcessorAttribute>();
var assembly = Assembly.GetAssembly(typeof(ProcessorSettingsBase));
var types = assembly.GetTypes();
var processorSettingsType = typeof(ProcessorSettingsBase);
var attrType = typeof(ProcessorAttribute);
var processorSettingTypes = types
.Where(t => t.IsClass
&& !t.IsAbstract
&& t.IsSubclassOf(processorSettingsType)
&& t.IsDefined(attrType, false));
foreach (var processorSettingType in processorSettingTypes)
{
var attr = (ProcessorAttribute)processorSettingType.GetCustomAttributes(attrType, false)[0];
Type processorType = attr.processorType;
if (!processorType.IsClass || !processorType.IsSubclassOf(typeof(FrameProcessor)) || processorType.IsAbstract)
throw new InvalidOperationException("Invalid RendererAttribute parameter, type must be a non-abstract class that extends GPUFrameProcessor<>");
settingsDefinitions.Add(processorSettingType, attr);
}
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/FrameProcessorStack.cs.meta


fileFormatVersion: 2
guid: 3ce623adbc8851e47b42e1381950be6d
timeCreated: 1461142428
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

54
com.unity.vfx-toolbox/ImageSequencer/Editor/GPUFrameProcessor.cs


using UnityEngine;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public abstract class GPUFrameProcessor<T> : FrameProcessor<T> where T : ProcessorSettingsBase
{
protected Shader m_Shader;
protected Material m_Material;
public GPUFrameProcessor(string shaderPath, FrameProcessorStack processorStack, ProcessorInfo info )
: this(AssetDatabase.LoadAssetAtPath<Shader>(shaderPath),processorStack, info)
{ }
public GPUFrameProcessor(Shader shader, FrameProcessorStack processorStack, ProcessorInfo info ) : base(processorStack, info)
{
m_Shader = shader;
m_Material = new Material(m_Shader) { hideFlags = HideFlags.DontSave };
m_Material.hideFlags = HideFlags.DontSave;
}
public void ExecuteShaderAndDump(int outputframe, Texture mainTex)
{
ExecuteShaderAndDump(outputframe, mainTex, m_Material);
}
public void ExecuteShaderAndDump(int outputframe, Texture mainTex, Material material)
{
RenderTexture backup = RenderTexture.active;
Graphics.Blit(mainTex, (RenderTexture)m_OutputSequence.frames[outputframe].texture, material);
RenderTexture.active = backup;
}
public override void Dispose()
{
Material.DestroyImmediate(m_Material);
base.Dispose();
}
protected override int GetNumU()
{
if (InputSequence.processor == null)
return 1;
return InputSequence.numU;
}
protected override int GetNumV()
{
if (InputSequence.processor == null)
return 1;
return InputSequence.numV;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/GPUFrameProcessor.cs.meta


fileFormatVersion: 2
guid: a00044f5e3e7b924e925a45bcb585727
timeCreated: 1461162132
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

218
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetEditor.cs


using UnityEngine;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
[CustomEditor(typeof(ImageSequence))]
public class ImageSequenceAssetEditor : Editor
{
private bool m_PreviewInput = false;
private bool m_PreviewOutput = false;
private bool m_RequireConstantRepaint = false;
public override bool RequiresConstantRepaint()
{
return m_RequireConstantRepaint;
}
protected override void OnHeaderGUI()
{
base.OnHeaderGUI();
}
public override void OnInspectorGUI()
{
serializedObject.Update();
m_RequireConstantRepaint = false;
using (new EditorGUILayout.VerticalScope())
{
if (GUILayout.Button(VFXToolboxGUIUtility.Get("Edit Sequence"), GUILayout.Height(40)))
{
ImageSequencer toolbox = EditorWindow.GetWindow<ImageSequencer>();
toolbox.LoadAsset((ImageSequence)Selection.activeObject);
}
VFXToolboxGUIUtility.ToggleableHeader(true, false, "Input Frames");
{
var inputFrames = serializedObject.FindProperty("inputFrameGUIDs");
int inputFrameCount = inputFrames.arraySize;
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label("Input sequence contains " + inputFrameCount + " frame(s).");
GUILayout.FlexibleSpace();
m_PreviewInput = GUILayout.Toggle(m_PreviewInput, VFXToolboxGUIUtility.Get("Preview"), EditorStyles.miniButton);
}
if(inputFrameCount > 0 && m_PreviewInput)
{
int index;
if(inputFrameCount > 1)
{
m_RequireConstantRepaint = true;
float time = (float)EditorApplication.timeSinceStartup;
index = (int)Mathf.Floor((time * 30) % inputFrameCount);
}
else
{
index = 0;
}
var frame = inputFrames.GetArrayElementAtIndex(index);
string guid = frame.stringValue;
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(guid));
DrawAnimatedPreviewLayout(texture, ((float)index / inputFrameCount));
}
else
{
m_PreviewInput = false;
}
}
GUILayout.Space(24);
VFXToolboxGUIUtility.ToggleableHeader(true, false, "Processors");
{
var processors = serializedObject.FindProperty("processorInfos");
int processorsCount = processors.arraySize;
EditorGUILayout.LabelField("Asset contains " + processorsCount + " Processor (s).");
EditorGUI.indentLevel++;
for(int i = 0; i < processorsCount; i++)
{
var item = processors.GetArrayElementAtIndex(i).objectReferenceValue as ProcessorInfo;
EditorGUILayout.LabelField("#"+i+" - " + item.ProcessorName + (item.Enabled?"":" (Disabled)"));
}
EditorGUI.indentLevel--;
}
GUILayout.Space(24);
VFXToolboxGUIUtility.ToggleableHeader(true, false, "Export Settings");
var exportSettings = serializedObject.FindProperty("exportSettings");
string fileName = exportSettings.FindPropertyRelative("fileName").stringValue;
var mode = (ImageSequence.ExportMode)exportSettings.FindPropertyRelative("exportMode").enumValueIndex;
var frameCount = exportSettings.FindPropertyRelative("frameCount");
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.EnumPopup(VFXToolboxGUIUtility.Get("Export Format"), mode);
EditorGUI.EndDisabledGroup();
if (fileName != "")
{
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.TextField("Exporting to ", fileName);
EditorGUI.EndDisabledGroup();
Rect r = GUILayoutUtility.GetLastRect();
r.width += EditorGUIUtility.fieldWidth;
if (Event.current.rawType == EventType.MouseDown && r.Contains(Event.current.mousePosition))
{
ImageSequencer.PingOutputTexture(fileName);
}
string dir = System.IO.Path.GetDirectoryName(fileName);
string file = System.IO.Path.GetFileNameWithoutExtension(fileName);
string[] assets;
if(!fileName.StartsWith("Assets/"))
{
EditorGUILayout.HelpBox("The output sequence has been exported outside the project, preview will be unavailable", MessageType.Warning);
return;
}
if(fileName.Contains("#"))
{
if(System.IO.Directory.Exists(dir))
{
string[] guids = AssetDatabase.FindAssets(file.Replace('#', '*'), new string[] { dir });
assets = new string[guids.Length];
for(int i = 0; i < guids.Length; i++)
{
assets[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
}
}
else
assets = new string[] { };
}
else
{
assets = new string[] { fileName };
}
int outputFrameCount;
if (frameCount.intValue == assets.Length)
outputFrameCount = frameCount.intValue;
else
outputFrameCount = 0; // Something went wrong
if(outputFrameCount > 0)
{
if(outputFrameCount > 1)
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label("Output sequence contains " + assets.Length + " frame(s).");
GUILayout.FlexibleSpace();
m_PreviewOutput = GUILayout.Toggle(m_PreviewOutput, VFXToolboxGUIUtility.Get("Preview"), EditorStyles.miniButton);
}
if(m_PreviewOutput)
{
m_RequireConstantRepaint = true;
float time = (float)EditorApplication.timeSinceStartup;
int index = (int)Mathf.Floor((time * 30) % outputFrameCount);
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assets[index]);
DrawAnimatedPreviewLayout(texture, ((float)index / outputFrameCount));
}
else
{
m_PreviewOutput = false;
}
}
else // Only one frame
{
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assets[0]);
if (texture != null)
DrawAnimatedPreviewLayout(texture, 0.0f);
else
EditorGUILayout.HelpBox("Output Texture could not be loaded, maybe the file was deleted. Please export again using the editor", MessageType.Error);
}
}
else
{
EditorGUILayout.HelpBox("The output sequence does not match the number of files on disk, you probably need to export your sequence again", MessageType.Warning);
}
}
else
{
EditorGUILayout.HelpBox("This asset has not yet been exported. Please open editor and export it to generate a sequence.",MessageType.None);
}
}
}
private void DrawAnimatedPreviewLayout(Texture2D texture, float progress)
{
float ratio = (float)texture.height / (float)texture.width;
using (new EditorGUILayout.HorizontalScope())
{
float width = EditorGUIUtility.currentViewWidth-32;
float height = 240;
GUILayout.FlexibleSpace();
Rect texture_rect;
if(ratio >= 1)
texture_rect = GUILayoutUtility.GetRect(height / ratio, height);
else
texture_rect = GUILayoutUtility.GetRect(width, width * ratio);
GUILayout.FlexibleSpace();
EditorGUI.DrawTextureTransparent(texture_rect, texture);
EditorGUI.DrawRect(new Rect(texture_rect.x, texture_rect.y, progress * 200.0f / ratio, 4.0f), new Color(0.3f, 0.5f, 1.0f));
}
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetEditor.cs.meta


fileFormatVersion: 2
guid: aff58427bba3d4a429ffc73dc97bdc6b
timeCreated: 1471965338
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

52
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetFactory.cs


using UnityEngine;
using UnityEditor.Callbacks;
using UnityEditor.ProjectWindowCallback;
using System.IO;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public class ImageSequenceAssetFactory
{
[MenuItem("Assets/Create/Visual Effects/Image Sequence", priority = 301)]
private static void MenuCreatePostProcessingProfile()
{
var icon = EditorGUIUtility.FindTexture("ImageSequence Icon");
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreateImageSequenceAsset>(), "New Image Sequence.asset", icon, null);
}
public static ImageSequence CreateImageSequenceAtPath(string path)
{
ImageSequence asset = ScriptableObject.CreateInstance<ImageSequence>();
asset.name = Path.GetFileName(path);
AssetDatabase.CreateAsset(asset, path);
return asset;
}
}
internal class DoCreateImageSequenceAsset : EndNameEditAction
{
public override void Action(int instanceId, string pathName, string resourceFile)
{
ImageSequence asset = ImageSequenceAssetFactory.CreateImageSequenceAtPath(pathName);
ProjectWindowUtil.ShowCreatedAsset(asset);
}
}
public class ImageSequenceAssetCallbackHandler
{
[OnOpenAsset(1)]
public static bool OpenImageSequenceAsset(int instanceID, int line)
{
ImageSequence asset = EditorUtility.InstanceIDToObject(instanceID) as ImageSequence;
if(asset != null) // We opened an image sequence asset, open the editor.
{
ImageSequencer.OpenEditor();
ImageSequencer window = EditorWindow.GetWindow<ImageSequencer>();
window.Focus();
return true;
}
else
return false;
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequenceAssetFactory.cs.meta


fileFormatVersion: 2
guid: a7fed52c3c7c62541a07cb519bfcbc27
timeCreated: 1471965338
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

357
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Export.cs


using UnityEngine;
using System.IO;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class ImageSequencer : EditorWindow
{
private string GetNumberedFileName(string pattern, int number, int maxFrames)
{
int numbering = (int)Mathf.Floor(Mathf.Log10(maxFrames))+1;
return pattern.Replace("#", number.ToString("D" + numbering.ToString()));
}
public string ExportToFile(bool useCurrentFileName)
{
bool bIsInsideProject = true;
string path;
if(useCurrentFileName)
{
path = m_CurrentAsset.exportSettings.fileName;
}
else
{
string title = "Save Texture, use # for frame numbering.";
string defaultFileName, extension;
int count = m_processorStack.outputSequence.frames.Count;
int numU = m_processorStack.outputSequence.numU;
int numV = m_processorStack.outputSequence.numV;
string defaultDir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(m_CurrentAsset));
defaultFileName = m_CurrentAsset.name;
if (count > 1)
defaultFileName += "_#";
if(numU * numV != 1)
defaultFileName += "_"+numU+"x"+numV;
switch (m_CurrentAsset.exportSettings.exportMode)
{
case ImageSequence.ExportMode.EXR:
defaultFileName += ".exr";
extension = "exr";
break;
case ImageSequence.ExportMode.Targa:
defaultFileName += ".tga";
extension = "tga";
break;
case ImageSequence.ExportMode.PNG:
defaultFileName += ".png";
extension = "png";
break;
default: return null;
}
path = EditorUtility.SaveFilePanel(title, defaultDir, defaultFileName, extension);
if (path == null || path == "")
return "";
if (path.Contains(Application.dataPath))
path = path.Replace(Application.dataPath, "Assets");
}
if(!path.StartsWith("Assets/"))
{
bIsInsideProject = false;
Debug.LogWarning("VFX Toolbox Warning : Saving a texture outside the project's scope. Import Settings will not be applied");
}
int frameCount = m_processorStack.outputSequence.length;
if(frameCount > 1 && !Path.GetFileNameWithoutExtension(path).Contains("#"))
{
if (!EditorUtility.DisplayDialog("VFX Toolbox", "You are currently exporting a sequence of images with no # in filename for numbering, do you want to add _# as a suffix of the filename?", "Add Postfix", "Cancel Export"))
return "";
string newpath = Path.GetDirectoryName(path) + "\\" + Path.GetFileNameWithoutExtension(path) + "_#" + Path.GetExtension(path);
path = newpath;
}
ImageSequence.ExportSettings settings = m_CurrentAsset.exportSettings;
bool bCanceled = false;
try
{
int i = 1;
foreach (ProcessingFrame frame in m_processorStack.outputSequence.frames)
{
if(VFXToolboxGUIUtility.DisplayProgressBar("Image Sequencer", "Exporting Frame #" + i + "/" + frameCount, (float)i / frameCount, 0, true))
{
bCanceled = true;
break;
}
// Export frame : first, dump data into color array
Color[] inputs;
if (frame.texture is Texture2D) // if using input frame
{
RenderTexture temp = RenderTexture.GetTemporary(frame.texture.width, frame.texture.height, 0, RenderTextureFormat.ARGBHalf);
Graphics.Blit((Texture2D)frame.texture, temp);
inputs = ReadBack(temp);
}
else // frame.texture is RenderTexture
{
frame.Process();
inputs = ReadBack((RenderTexture)frame.texture);
}
string fileName = GetNumberedFileName(path, i, frameCount);
// Dump data
byte[] bytes;
switch(m_CurrentAsset.exportSettings.exportMode)
{
case ImageSequence.ExportMode.EXR:
#if UNITY_5_6_OR_NEWER
// New Exporter
{
Texture2D texture = new Texture2D(frame.texture.width, frame.texture.height, TextureFormat.RGBAHalf, settings.generateMipMaps, !settings.sRGB);
texture.SetPixels(inputs);
texture.Apply(true);
bytes = texture.EncodeToEXR();
}
#else
// Old Exporter
{
bytes = MiniEXR.MiniEXR.MiniEXRWrite((ushort)frame.texture.width, (ushort)frame.texture.height, settings.exportAlpha, inputs, true);
}
#endif
break;
case ImageSequence.ExportMode.Targa:
{
bytes = MiniTGA.MiniTGA.MiniTGAWrite((ushort)frame.texture.width, (ushort)frame.texture.height, settings.exportAlpha, inputs);
}
break;
case ImageSequence.ExportMode.PNG:
{
Texture2D texture = new Texture2D(frame.texture.width, frame.texture.height, TextureFormat.RGBA32, settings.generateMipMaps, !settings.sRGB);
texture.SetPixels(inputs);
texture.Apply(true);
bytes = texture.EncodeToPNG();
}
break;
default:
{
bytes = new byte[0] { }; // Empty file that should not happen
}
break;
}
File.WriteAllBytes(fileName, bytes);
AssetDatabase.Refresh();
// Process Import if saved inside project
if(bIsInsideProject)
{
TextureImporter importer = (TextureImporter)TextureImporter.GetAtPath(fileName);
importer.wrapMode = m_CurrentAsset.exportSettings.wrapMode;
importer.filterMode = m_CurrentAsset.exportSettings.filterMode;
switch(m_CurrentAsset.exportSettings.dataContents)
{
case ImageSequence.DataContents.Color:
importer.textureType = TextureImporterType.Default;
break;
case ImageSequence.DataContents.NormalMap:
importer.textureType = TextureImporterType.NormalMap;
importer.convertToNormalmap = false;
break;
case ImageSequence.DataContents.NormalMapFromGrayscale:
importer.textureType = TextureImporterType.NormalMap;
importer.convertToNormalmap = true;
break;
case ImageSequence.DataContents.Sprite:
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Multiple;
importer.spritesheet = GetSpriteMetaData(frame, m_processorStack.outputSequence.numU, m_processorStack.outputSequence.numV );
break;
}
importer.mipmapEnabled = m_CurrentAsset.exportSettings.generateMipMaps;
switch(m_CurrentAsset.exportSettings.exportMode)
{
case ImageSequence.ExportMode.Targa:
importer.sRGBTexture = m_CurrentAsset.exportSettings.sRGB;
importer.alphaSource = m_CurrentAsset.exportSettings.exportAlpha ? TextureImporterAlphaSource.FromInput : TextureImporterAlphaSource.None;
importer.textureCompression = m_CurrentAsset.exportSettings.compress ? TextureImporterCompression.Compressed : TextureImporterCompression.Uncompressed;
break;
case ImageSequence.ExportMode.EXR:
importer.sRGBTexture = false;
importer.alphaSource = (m_CurrentAsset.exportSettings.exportAlpha && !m_CurrentAsset.exportSettings.compress) ? TextureImporterAlphaSource.FromInput : TextureImporterAlphaSource.None;
importer.textureCompression = m_CurrentAsset.exportSettings.compress ? TextureImporterCompression.CompressedHQ : TextureImporterCompression.Uncompressed;
break;
case ImageSequence.ExportMode.PNG:
importer.sRGBTexture = m_CurrentAsset.exportSettings.sRGB;
importer.alphaSource = m_CurrentAsset.exportSettings.exportAlpha ? TextureImporterAlphaSource.FromInput : TextureImporterAlphaSource.None;
importer.textureCompression = m_CurrentAsset.exportSettings.compress ? TextureImporterCompression.Compressed : TextureImporterCompression.Uncompressed;
break;
}
AssetDatabase.ImportAsset(fileName, ImportAssetOptions.ForceUpdate);
}
// Separate Alpha
if (m_CurrentAsset.exportSettings.exportSeparateAlpha)
{
string alphaFilename = fileName.Substring(0, fileName.Length - 4) + "_alpha.tga";
// build alpha
for(int k = 0; k < inputs.Length; k++)
{
float a = inputs[k].a;
inputs[k] = new Color(a, a, a, a);
}
MiniTGA.MiniTGA.MiniTGAWrite(alphaFilename,(ushort)frame.texture.width, (ushort)frame.texture.height, false, inputs);
AssetDatabase.Refresh();
// Process Importer for alpha if inside project
if(bIsInsideProject)
{
TextureImporter alphaImporter = (TextureImporter)TextureImporter.GetAtPath(alphaFilename);
if (m_CurrentAsset.exportSettings.dataContents == ImageSequence.DataContents.Sprite)
{
alphaImporter.textureType = TextureImporterType.Sprite;
alphaImporter.spriteImportMode = SpriteImportMode.Multiple;
alphaImporter.spritesheet = GetSpriteMetaData(frame, m_processorStack.outputSequence.numU, m_processorStack.outputSequence.numV);
alphaImporter.alphaSource = TextureImporterAlphaSource.None;
}
else
{
alphaImporter.textureType = TextureImporterType.SingleChannel;
alphaImporter.alphaSource = TextureImporterAlphaSource.FromGrayScale;
}
alphaImporter.wrapMode = m_CurrentAsset.exportSettings.wrapMode;
alphaImporter.filterMode = m_CurrentAsset.exportSettings.filterMode;
alphaImporter.sRGBTexture = false;
alphaImporter.mipmapEnabled = m_CurrentAsset.exportSettings.generateMipMaps;
alphaImporter.textureCompression = m_CurrentAsset.exportSettings.compress ? TextureImporterCompression.Compressed : TextureImporterCompression.Uncompressed;
AssetDatabase.ImportAsset(alphaFilename, ImportAssetOptions.ForceUpdate);
}
}
i++;
}
}
catch(System.Exception e)
{
VFXToolboxGUIUtility.ClearProgressBar();
Debug.LogError(e.Message);
}
VFXToolboxGUIUtility.ClearProgressBar();
if(bCanceled)
return "";
else
return path;
}
public static void PingOutputTexture(string fileName)
{
if (fileName == "")
return;
string dir = System.IO.Path.GetDirectoryName(fileName);
string file = System.IO.Path.GetFileNameWithoutExtension(fileName);
if(!fileName.StartsWith("Assets/"))
return;
if(fileName.Contains("#"))
{
if(System.IO.Directory.Exists(dir))
{
string[] guids = AssetDatabase.FindAssets(file.Replace('#', '*'), new string[] { dir });
fileName = AssetDatabase.GUIDToAssetPath(guids[0]);
}
}
bool fileFound = (fileName != "")&&(System.IO.File.Exists(fileName));
if(fileFound)
{
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(fileName);
if (texture != null) EditorGUIUtility.PingObject(texture);
}
else
{
Debug.LogWarning("Could not ping output texture, either the file was moved or removed, you probably need to export your sequence again");
}
}
private void PingCurrentAsset()
{
EditorGUIUtility.PingObject(m_CurrentAsset);
}
private void UpdateExportedAssets()
{
if (ExportToFile(true) != "")
m_CurrentAsset.exportSettings.frameCount = (ushort)m_processorStack.outputSequence.frames.Count;
else
m_CurrentAsset.exportSettings.frameCount = 0;
}
private Color[] ReadBack(RenderTexture renderTexture)
{
Color[] inputs = VFXToolboxUtility.ReadBack(renderTexture);
if(QualitySettings.activeColorSpace == ColorSpace.Linear && m_CurrentAsset.exportSettings.sRGB)
{
Color[] outputs = new Color[inputs.Length];
for (int j = 0; j < inputs.Length; j++)
{
outputs[j] = inputs[j].gamma;
}
return outputs;
}
return inputs;
}
private SpriteMetaData[] GetSpriteMetaData(ProcessingFrame frame, int numU, int numV)
{
SpriteMetaData[] result = new SpriteMetaData[numU * numV];
float width = (float)frame.texture.width / numU;
float height = (float)frame.texture.height / numV;
for(int i = 0; i < numU; i++)
for(int j = 0; j < numV; j++)
{
SpriteMetaData data = new SpriteMetaData();
data.name = "Frame_" + (i + (j * numU));
data.rect = new Rect(i * width, (numV - j - 1) * height, width, height);
result[i + (j * numU)] = data;
}
return result;
}
private static GUIContent[] GetExportModeFriendlyNames()
{
return new GUIContent[] { VFXToolboxGUIUtility.Get("Targa"), VFXToolboxGUIUtility.Get("OpenEXR (HDR)"), VFXToolboxGUIUtility.Get("PNG") };
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Export.cs.meta


fileFormatVersion: 2
guid: 3a6ece5b6c8d2084aaef5221050b8cfa
timeCreated: 1471965338
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

779
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.GUI.cs


using UnityEngine;
using UnityEditorInternal;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class ImageSequencer : EditorWindow
{
private Splitter m_Splitter;
private ReorderableList m_InputFramesReorderableList;
private ReorderableList m_ProcessorsReorderableList;
private Vector2 m_OptionsViewScroll = Vector2.zero;
private Vector2 m_MinimumSize;
private SidePanelMode m_SidePanelViewMode = 0;
private bool m_Dirty = true;
private bool m_NeedRedraw = false;
public void InitializeGUI()
{
minSize = m_MinimumSize;
if(m_Splitter == null)
{
m_Splitter = new Splitter(360, DrawEditPanelGUI, DrawCanvasGUI, Splitter.SplitLockMode.LeftMinMax, new Vector2(320.0f, 480.0f));
}
if(m_PreviewCanvas == null)
{
m_PreviewCanvas = new ImageSequencerCanvas(new Rect(0, 16, position.width - m_Splitter.value, position.height - 16),this);
}
CheckGraphicsSettings();
}
public void OnGUI()
{
titleContent = styles.title;
m_MinimumSize = new Vector2(880, 320);
InitializeGUI();
if(m_CurrentAsset == null)
{
OnNoAssetGUI();
return;
}
m_Dirty = false;
m_CurrentAssetSerializedObject.Update();
UpdateCanvasRect();
if(HandleDropData()) return;
DrawToolbar();
Rect rect = new Rect(0,18, position.width, position.height-18);
if (m_Splitter.DoSplitter(rect))
Invalidate();
// Processing Play Mode, Cooking & Autocooking
if (previewCanvas.isPlaying && previewCanvas.sequence.length > 1)
Invalidate();
else
{
if (Event.current.type == EventType.Repaint)
{
if(m_NeedRedraw)
{
previewCanvas.UpdateCanvasSequence();
Invalidate();
m_NeedRedraw = false;
}
else if((m_AutoCook && m_CurrentProcessor != null))
{
m_CurrentProcessor.RequestProcessOneFrame(previewCanvas.currentFrameIndex);
Invalidate();
}
}
}
// if Invalidated this frame, repaint.
if (m_Dirty) Repaint();
}
public void OnNoAssetGUI()
{
UpdateCanvasRect();
if(HandleDropData()) return;
using (new EditorGUILayout.VerticalScope())
{
GUILayout.FlexibleSpace();
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
EditorGUILayout.HelpBox("No Image Sequence is currently selected.\nPlease create one within your Assets then select It in the project view.", MessageType.Info);
GUILayout.FlexibleSpace();
}
GUILayout.Space(8);
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
if (GUILayout.Button("Create Image Sequence", GUILayout.Width(160)))
{
string file = EditorUtility.SaveFilePanelInProject("Create Image Sequence", "New Image Sequence", "asset", "Create Image Sequence?");
if (file != string.Empty)
{
var sequence = ImageSequenceAssetFactory.CreateImageSequenceAtPath(file);
AssetDatabase.ImportAsset(file);
LoadAsset(sequence);
}
}
GUILayout.FlexibleSpace();
}
GUILayout.FlexibleSpace();
}
}
private bool HandleDropData()
{
if(m_CurrentAsset == null)
return false;
if(sidePanelViewMode == SidePanelMode.InputFrames && DragAndDrop.paths.Length > 0)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Link;
if( Event.current.type == EventType.DragExited)
{
List<string> texturePaths = new List<string>();
foreach(string path in DragAndDrop.paths)
{
if (VFXToolboxUtility.IsDirectory(path))
texturePaths.AddRange(VFXToolboxUtility.GetAllTexturesInPath(path));
else
{
VFXToolboxGUIUtility.DisplayProgressBar("Image Sequencer", "Discovering Assets...", 0.5f);
Texture2D t = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if(t != null)
texturePaths.Add(path);
}
}
AddInputFrame(m_InputFramesReorderableList, texturePaths);
VFXToolboxGUIUtility.ClearProgressBar();
return true;
}
}
return false;
}
private void DrawToolbar()
{
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
{
EditorGUI.BeginChangeCheck();
bool prev;
bool bMaskR = m_PreviewCanvas.maskR;
bool bMaskG = m_PreviewCanvas.maskG;
bool bMaskB = m_PreviewCanvas.maskB;
bool bMaskA = m_PreviewCanvas.maskA;
bool bMaskRGB = bMaskR && bMaskG && bMaskB;
//GUILayout.Space(m_Splitter.value);
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar, GUILayout.Width(m_Splitter.value)))
{
if (GUILayout.Button(VFXToolboxGUIUtility.Get("Current Sequence: "+m_CurrentAsset.name), EditorStyles.toolbarButton))
{
PingCurrentAsset();
}
GUILayout.FlexibleSpace();
}
Rect r = GUILayoutUtility.GetRect(VFXToolboxGUIUtility.GetTextAndIcon(" ", "SceneviewFx"), EditorStyles.toolbarPopup);
if (GUI.Button(r, VFXToolboxGUIUtility.GetTextAndIcon(" ", "SceneviewFx"), EditorStyles.toolbarPopup))
{
PopupWindow.Show(r, (PopupWindowContent) new CanvasConfigPopupWindowContent(this));
}
GUILayout.Space(20);
bMaskRGB = GUILayout.Toggle(bMaskRGB, styles.iconRGB, EditorStyles.toolbarButton);
if(bMaskRGB != (bMaskR && bMaskG && bMaskB))
{
bMaskR = bMaskG = bMaskB = bMaskRGB;
m_PreviewCanvas.maskR = bMaskR;
m_PreviewCanvas.maskG = bMaskG;
m_PreviewCanvas.maskB = bMaskB;
}
prev = bMaskR;
bMaskR = GUILayout.Toggle(bMaskR, VFXToolboxGUIUtility.Get("R"),styles.MaskRToggle);
if (bMaskR != prev)
m_PreviewCanvas.maskR = bMaskR;
prev = bMaskG;
bMaskG = GUILayout.Toggle(bMaskG, VFXToolboxGUIUtility.Get("G"),styles.MaskGToggle);
if (bMaskG != prev)
m_PreviewCanvas.maskG = bMaskG;
prev = bMaskB;
bMaskB = GUILayout.Toggle(bMaskB, VFXToolboxGUIUtility.Get("B"),styles.MaskBToggle);
if (bMaskB != prev)
m_PreviewCanvas.maskB = bMaskB;
prev = bMaskA;
bMaskA = GUILayout.Toggle(bMaskA, VFXToolboxGUIUtility.Get("A"),styles.MaskAToggle);
if (bMaskA != prev)
m_PreviewCanvas.maskA = bMaskA;
if(m_PreviewCanvas.sequence != null && m_PreviewCanvas.numFrames > 0 && m_PreviewCanvas.currentFrame != null)
{
GUILayout.Space(20.0f);
if(m_PreviewCanvas.mipMapCount > 0)
{
int currentMip = m_PreviewCanvas.mipMap;
int newMip = currentMip;
{
Rect mipRect = GUILayoutUtility.GetRect(164, 24);
GUI.Box(mipRect, GUIContent.none, VFXToolboxStyles.toolbarButton);
GUI.Label(new RectOffset(0, 0, 0, 0).Remove(mipRect), styles.iconMipMapDown);
newMip = (int)Mathf.Round(GUI.HorizontalSlider(new RectOffset(24,64,0,0).Remove(mipRect), (float)newMip, 0.0f, (float)m_PreviewCanvas.mipMapCount-1));
GUI.Label(new RectOffset(100, 0, 0, 0).Remove(mipRect), styles.iconMipMapUp);
if (newMip != currentMip)
{
m_PreviewCanvas.mipMap = newMip;
}
GUI.Label(new RectOffset(124, 0, 0, 0).Remove(mipRect), (m_PreviewCanvas.mipMap+1)+"/"+m_PreviewCanvas.mipMapCount, VFXToolboxStyles.toolbarLabelLeft);
}
}
}
if(EditorGUI.EndChangeCheck())
{
m_PreviewCanvas.UpdateCanvasSequence(); // Reblit if changed the flags.
}
GUILayout.Space(20);
{
Rect brightnessRect = GUILayoutUtility.GetRect(160, 24);
GUI.Box(brightnessRect, GUIContent.none, VFXToolboxStyles.toolbarButton);
GUI.Label(new RectOffset(4, 0, 0, 0).Remove(brightnessRect), VFXToolboxGUIUtility.GetTextAndIcon("Background|Sets the Background Brightness", "CheckerFloor"), VFXToolboxStyles.toolbarLabelLeft);
float newBrightness = GUI.HorizontalSlider(new RectOffset(82, 4, 0, 0).Remove(brightnessRect), previewCanvas.BackgroundBrightness, 0.0f, 1.0f);
if (previewCanvas.BackgroundBrightness != newBrightness)
previewCanvas.BackgroundBrightness = newBrightness;
}
GUILayout.FlexibleSpace();
}
}
private void DrawCanvasGUI(Rect rect)
{
if (previewCanvas.sequence.length > 1)
previewCanvas.displayRect = new Rect(m_Splitter.value, 16, position.width - m_Splitter.value, position.height - 116);
else
previewCanvas.displayRect = new Rect(m_Splitter.value, 16, position.width - m_Splitter.value, position.height - 16);
previewCanvas.OnGUI(this);
// Draw Update Button
if(m_CurrentAsset.exportSettings.fileName != "")
{
Rect exportButtonRect = new Rect(position.width - 100, 24, 74, 24);
if (GUI.Button(exportButtonRect, VFXToolboxGUIUtility.GetTextAndIcon("Update", "SaveActive"), VFXToolboxStyles.TabButtonSingle))
{
UpdateExportedAssets();
}
}
}
private void DrawEditPanelGUI(Rect rect)
{
using (new GUILayout.AreaScope(rect))
{
m_OptionsViewScroll = EditorGUILayout.BeginScrollView(m_OptionsViewScroll, styles.scrollView, GUILayout.Width(m_Splitter.value));
using (new EditorGUILayout.VerticalScope())
{
GUILayout.Space(16);
// Three Button Tabs : Mode Selection
DrawTabbedPanelSelector();
GUILayout.Space(16);
switch (m_SidePanelViewMode)
{
case SidePanelMode.InputFrames:
// Draw Input Frames Panel
DrawInputFramesPanelContent();
break;
case SidePanelMode.Processors:
// Draw Processors Edit Panel
DrawProcessorsPanelContent();
break;
case SidePanelMode.Export:
// Draw Export Panel
DrawExportPanelContent();
break;
default:
break;
}
GUILayout.Space(32);
}
EditorGUILayout.EndScrollView();
if(QualitySettings.activeColorSpace == ColorSpace.Gamma)
{
EditorGUILayout.HelpBox("Your project is configured to use Gamma color space. While this is not a breaking setting for the ImageSequencer to work, It will produce a different and unexpected results than when used in linear color space.", MessageType.Warning);
GUILayout.Space(8);
}
}
}
private void DrawTabbedPanelSelector()
{
SidePanelMode prevMode = m_SidePanelViewMode;
bool hasInputFrames = m_processorStack.inputSequence.frames.Count > 0;
SidePanelMode newMode = (SidePanelMode)VFXToolboxGUIUtility.TabbedButtonsGUILayout(
(int)prevMode,
new string[] { "Input Frames", "Processors", "Export"},
new bool [] { true, hasInputFrames, hasInputFrames}
);
if(prevMode != newMode)
{
m_SidePanelViewMode = newMode;
switch(m_SidePanelViewMode)
{
case SidePanelMode.InputFrames:
m_PreviewCanvas.sequence = m_processorStack.inputSequence;
break;
case SidePanelMode.Processors:
if (m_LockedPreviewProcessor != null)
m_PreviewCanvas.sequence = m_LockedPreviewProcessor.OutputSequence;
else
{
if(m_CurrentProcessor != null)
m_PreviewCanvas.sequence = m_CurrentProcessor.OutputSequence;
else
{
if (m_processorStack.processors.Count > 0)
m_PreviewCanvas.sequence = m_processorStack.processors[m_processorStack.processors.Count - 1].OutputSequence;
else
m_PreviewCanvas.sequence = m_processorStack.inputSequence;
}
}
break;
case SidePanelMode.Export:
m_PreviewCanvas.sequence = m_processorStack.outputSequence;
break;
}
m_PreviewCanvas.InvalidateRenderTarget();
m_PreviewCanvas.UpdateCanvasSequence();
m_PreviewCanvas.Invalidate(true);
}
}
private void DrawInputFramesPanelContent()
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label(VFXToolboxGUIUtility.Get("Input Frames"),EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Actions"), EditorStyles.popup, GUILayout.Width(80), GUILayout.Height(20)))
{
GenericMenu menu = new GenericMenu();
menu.AddItem(VFXToolboxGUIUtility.Get("Clear"), false, MenuClearInputFrames);
menu.AddItem(VFXToolboxGUIUtility.Get("Sort All"), false, MenuSortInputFrames);
menu.AddItem(VFXToolboxGUIUtility.Get("Reverse Oder"), false, MenuReverseInputFrames);
menu.ShowAsContext();
}
}
GUILayout.Space(8);
m_InputFramesReorderableList.DoLayoutList();
if(Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete && m_processorStack.inputSequence.length > 0)
{
RemoveInputFrame(m_InputFramesReorderableList);
Event.current.Use();
}
}
private void DrawProcessorsPanelContent()
{
ImageSequence seq = (ImageSequence)EditorGUILayout.ObjectField(VFXToolboxGUIUtility.Get("Inherit processors from"), m_CurrentAsset.inheritSettingsReference, typeof(ImageSequence), false);
if (m_IgnoreInheritSettings)
EditorGUILayout.HelpBox("Warning : Dependency Loop found when inheriting these settings, ignoring...", MessageType.Warning);
if(seq != m_CurrentAsset.inheritSettingsReference && m_CurrentAsset != seq)
{
Undo.RecordObject(m_CurrentAsset, "use processor settings from other ImageSequence");
m_CurrentAsset.inheritSettingsReference = seq;
if(seq != null)
{
m_CurrentAsset.editSettings.selectedProcessor = seq.editSettings.selectedProcessor;
m_CurrentAsset.editSettings.lockedProcessor = -1;
}
EditorUtility.SetDirty(m_CurrentAsset);
LoadAsset(m_CurrentAsset);
}
GUILayout.Space(10);
using (new EditorGUI.DisabledScope(m_CurrentAsset.inheritSettingsReference != null))
{
using (new EditorGUILayout.HorizontalScope())
{
GUILayout.Label(VFXToolboxGUIUtility.Get("Frame Processor Stack"),EditorStyles.boldLabel,GUILayout.Width(180));
GUILayout.FlexibleSpace();
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Clear"), GUILayout.Width(80)))
{
// Delete everything
Undo.RecordObject(m_CurrentAsset, "Clear All Processors");
m_processorStack.RemoveAllProcessors(m_CurrentAsset);
// Update UI
m_ProcessorsReorderableList.index = -1;
m_CurrentProcessor = null;
m_LockedPreviewProcessor = null;
m_CurrentAsset.editSettings.lockedProcessor = -1;
m_CurrentAsset.editSettings.selectedProcessor = -1;
m_PreviewCanvas.sequence = m_processorStack.inputSequence;
EditorUtility.SetDirty(m_CurrentAsset);
// Request Repaint
Invalidate();
RefreshCanvas();
return;
}
}
GUILayout.Space(8);
}
m_ProcessorsReorderableList.DoLayoutList();
if(m_IgnoreInheritSettings || m_CurrentAsset.inheritSettingsReference == null)
{
GUILayout.Space(10);
// Draw inspector and Invalidates whatever needs to.
for(int i = 0; i < m_processorStack.processors.Count; i++)
{
if(m_ProcessorsReorderableList.index == i)
{
bool changed = m_processorStack.processors[i].OnSidePanelGUI(m_CurrentAsset,i);
if (changed)
{
m_processorStack.processors[i].Invalidate();
UpdateViewport();
}
m_Dirty = m_Dirty || changed;
}
}
}
else
{
EditorGUILayout.HelpBox("Settings cannot be accessed when linked from external Image Sequence", MessageType.Info);
}
// Handle final keyboard events (delete)
if(Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete && m_processorStack.processors.Count > 0)
{
MenuRemoveProcessor(m_ProcessorsReorderableList);
Event.current.Use();
}
}
private void DrawExportPanelContent()
{
int length = m_processorStack.outputSequence.length;
if(length > 0)
{
m_CurrentAssetSerializedObject.Update();
EditorGUI.BeginChangeCheck();
ImageSequence.ExportSettings prevState = m_CurrentAsset.exportSettings;
using (new VFXToolboxGUIUtility.HeaderSectionScope("File Export Options"))
{
ImageSequence.ExportMode prevMode = m_CurrentAsset.exportSettings.exportMode;
m_CurrentAsset.exportSettings.exportMode = (ImageSequence.ExportMode)EditorGUILayout.Popup(VFXToolboxGUIUtility.Get("Export Format"), (int)m_CurrentAsset.exportSettings.exportMode, GetExportModeFriendlyNames());
if (prevMode != m_CurrentAsset.exportSettings.exportMode)
{
m_CurrentAsset.exportSettings.fileName = "";
}
switch(m_CurrentAsset.exportSettings.exportMode)
{
case ImageSequence.ExportMode.EXR:
m_CurrentAsset.exportSettings.highDynamicRange = true;
m_CurrentAsset.exportSettings.sRGB = false;
break;
case ImageSequence.ExportMode.PNG:
case ImageSequence.ExportMode.Targa:
m_CurrentAsset.exportSettings.highDynamicRange = false;
break;
}
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.TextField(VFXToolboxGUIUtility.Get("File Name|File name or pattern of the export sequence, using # characters will add frame number to the file name, use multiple ### to ensure leading zeroes."), m_CurrentAsset.exportSettings.fileName);
EditorGUI.EndDisabledGroup();
Rect r = GUILayoutUtility.GetLastRect();
r.width += EditorGUIUtility.fieldWidth;
if (Event.current.rawType == EventType.MouseDown && r.Contains(Event.current.mousePosition))
{
PingOutputTexture(m_CurrentAsset.exportSettings.fileName);
}
if(!m_CurrentAsset.exportSettings.highDynamicRange)
m_CurrentAsset.exportSettings.sRGB = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("sRGB (Color Data)|Whether the texture contains color (or not), HDR Data is always non sRGB."), m_CurrentAsset.exportSettings.sRGB);
EditorGUI.BeginDisabledGroup(m_CurrentAsset.exportSettings.compress && m_CurrentAsset.exportSettings.highDynamicRange);
m_CurrentAsset.exportSettings.exportAlpha = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("Export Alpha|Whether to export the alpha channel"), m_CurrentAsset.exportSettings.exportAlpha);
EditorGUI.EndDisabledGroup();
m_CurrentAsset.exportSettings.exportSeparateAlpha = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("Separate Alpha|Export the alpha channel as a separate TGA Grayscale file with a \"_alpha\" suffix."), m_CurrentAsset.exportSettings.exportSeparateAlpha);
}
using (new VFXToolboxGUIUtility.HeaderSectionScope("Texture Import Options"))
{
m_CurrentAsset.exportSettings.dataContents = (ImageSequence.DataContents)EditorGUILayout.EnumPopup(VFXToolboxGUIUtility.Get("Import as|Sets the importer mode"), m_CurrentAsset.exportSettings.dataContents);
if(m_CurrentAsset.exportSettings.dataContents == ImageSequence.DataContents.Sprite)
{
FrameProcessor p = m_processorStack.processors[m_processorStack.processors.Count - 1];
if (((float)p.OutputWidth % p.NumU) != 0 || ((float)p.OutputHeight % p.NumV) != 0)
EditorGUILayout.HelpBox("Warning : texture size is not a multiplier of rows ("+p.NumU+") and columns ("+p.NumV+") count, this will lead to incorrect rendering of the sprite animation", MessageType.Warning);
}
switch(m_CurrentAsset.exportSettings.dataContents)
{
case ImageSequence.DataContents.NormalMapFromGrayscale:
case ImageSequence.DataContents.NormalMap:
m_CurrentAsset.exportSettings.sRGB = false;
m_CurrentAsset.exportSettings.exportAlpha = false;
break;
default: break;
}
if(!m_CurrentAsset.exportSettings.highDynamicRange)
m_CurrentAsset.exportSettings.sRGB = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("sRGB (Color Data)|Whether the texture contains color (or not), HDR Data is always non sRGB."), m_CurrentAsset.exportSettings.sRGB);
m_CurrentAsset.exportSettings.compress = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("Compress|Whether to apply texture compression (HDR Compressed Data does not support alpha channel)"), m_CurrentAsset.exportSettings.compress);
m_CurrentAsset.exportSettings.generateMipMaps = EditorGUILayout.Toggle(VFXToolboxGUIUtility.Get("Generate MipMaps|Whether generate mipmaps."), m_CurrentAsset.exportSettings.generateMipMaps);
m_CurrentAsset.exportSettings.wrapMode = (TextureWrapMode)EditorGUILayout.EnumPopup(VFXToolboxGUIUtility.Get("Wrap Mode|Texture Wrap mode"), m_CurrentAsset.exportSettings.wrapMode);
m_CurrentAsset.exportSettings.filterMode = (FilterMode)EditorGUILayout.EnumPopup(VFXToolboxGUIUtility.Get("Filter Mode|Texture Filter mode"), m_CurrentAsset.exportSettings.filterMode);
if(m_CurrentAsset.exportSettings.compress && m_CurrentAsset.exportSettings.highDynamicRange)
{
m_CurrentAsset.exportSettings.exportAlpha = false;
}
}
if(GUILayout.Button("Export as New...", GUILayout.Height(24)))
{
string fileName = "";
fileName = ExportToFile(false);
if (fileName != "")
{
m_CurrentAsset.exportSettings.fileName = fileName;
m_CurrentAsset.exportSettings.frameCount = (ushort)m_processorStack.outputSequence.frames.Count;
}
}
// Export Again
if( m_CurrentAsset.exportSettings.fileName != null &&
((m_CurrentAsset.exportSettings.fileName.EndsWith(".tga") && m_CurrentAsset.exportSettings.exportMode == ImageSequence.ExportMode.Targa)
|| (m_CurrentAsset.exportSettings.fileName.EndsWith(".exr") && m_CurrentAsset.exportSettings.exportMode == ImageSequence.ExportMode.EXR)
|| (m_CurrentAsset.exportSettings.fileName.EndsWith(".png") && m_CurrentAsset.exportSettings.exportMode == ImageSequence.ExportMode.PNG)
))
{
if(GUILayout.Button("Update Exported Assets", GUILayout.Height(24)))
{
UpdateExportedAssets();
}
}
if (m_CurrentAsset.exportSettings.dataContents == ImageSequence.DataContents.NormalMap)
EditorGUILayout.HelpBox("The selected import mode assumes that the frame data is a normal map. To generate a normal map from grayscale, use Normal Map From Grayscale instead.",MessageType.Info);
if(EditorGUI.EndChangeCheck())
{
ImageSequence.ExportSettings curState = m_CurrentAsset.exportSettings;
m_CurrentAsset.exportSettings = prevState;
Undo.RecordObject(m_CurrentAsset, "Update Export Settings");
m_CurrentAsset.exportSettings = curState;
m_CurrentAssetSerializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(m_CurrentAsset);
AssetDatabase.Refresh();
}
}
else
{
EditorGUILayout.HelpBox("You do not have any frames to export.", MessageType.Warning);
}
}
private void UpdateCanvasRect()
{
previewCanvas.displayRect = new Rect(m_Splitter.value, 16, position.width - m_Splitter.value, position.height - 16 );
}
public void Invalidate()
{
m_Dirty = true;
}
public void UpdateViewport()
{
m_NeedRedraw = true;
}
private class CanvasConfigPopupWindowContent : PopupWindowContent
{
private static Styles s_Styles;
private ImageSequencer m_Window;
public CanvasConfigPopupWindowContent(ImageSequencer window)
{
m_Window = window;
}
public override Vector2 GetWindowSize()
{
return new Vector2(200, 292);
}
public override void OnGUI(Rect rect)
{
if (s_Styles == null)
s_Styles = new Styles();
using (new GUILayout.AreaScope(rect))
{
bool needRepaint = false;
using (new GUILayout.VerticalScope())
{
EditorGUI.BeginChangeCheck();
DoHeaderLayout("Viewport Options");
m_Window.previewCanvas.showGrid = GUILayout.Toggle(m_Window.previewCanvas.showGrid, VFXToolboxGUIUtility.Get("Grid Outline"), s_Styles.menuItem );
m_Window.previewCanvas.showExtraInfo = GUILayout.Toggle(m_Window.previewCanvas.showExtraInfo, VFXToolboxGUIUtility.Get("Frame Processor Overlays"), s_Styles.menuItem );
m_Window.previewCanvas.filter = GUILayout.Toggle(m_Window.previewCanvas.filter, VFXToolboxGUIUtility.Get("Texture Filtering"), s_Styles.menuItem );
DoHeaderLayout("Center View");
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Fit to Window"),s_Styles.menuItem))
{
m_Window.previewCanvas.Recenter(true);
needRepaint = true;
}
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Reset Zoom"),s_Styles.menuItem))
{
m_Window.previewCanvas.Recenter(false);
needRepaint = true;
}
DoHeaderLayout("Background Options");
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Reset Brightness"),s_Styles.menuItem))
{
m_Window.previewCanvas.ResetBrightness();
needRepaint = true;
}
DoHeaderLayout("Processing Options");
m_Window.m_AutoCook = GUILayout.Toggle(m_Window.m_AutoCook, VFXToolboxGUIUtility.Get("AutoCook"), s_Styles.menuItem );
DoHeaderLayout("Find in Project...");
if(GUILayout.Button(VFXToolboxGUIUtility.Get("This Image Sequence"),s_Styles.menuItem))
{
m_Window.PingCurrentAsset();
}
if(m_Window.m_CurrentAsset.exportSettings.fileName != "")
{
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Exported Texture"),s_Styles.menuItem))
{
PingOutputTexture(m_Window.m_CurrentAsset.exportSettings.fileName);
}
}
else
{
using (new EditorGUI.DisabledScope(true))
{
GUILayout.Button(VFXToolboxGUIUtility.Get("Exported Texture"),s_Styles.menuItem);
}
}
/*
DoHeaderLayout("Help and Feedback");
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Documentation"),s_Styles.menuItem))
{
Application.OpenURL("https://drive.google.com/open?id=1YUwzA1mGvzWRpajDV-XF0iUd4RhW--bhMpqo-gmj9B8");
}
if(GUILayout.Button(VFXToolboxGUIUtility.Get("Forums (for Feedback)"),s_Styles.menuItem))
{
Application.OpenURL("https://forum.unity3d.com/forums/vfx-toolbox.119/");
}
*/
if(EditorGUI.EndChangeCheck())
{
needRepaint = true;
}
}
if (needRepaint)
m_Window.Repaint();
}
if (Event.current.type == EventType.MouseMove)
Event.current.Use();
if (Event.current.type != EventType.KeyDown || Event.current.keyCode != KeyCode.Escape)
return;
this.editorWindow.Close();
GUIUtility.ExitGUI();
}
private void DoHeaderLayout(string headerText)
{
GUILayout.Label(GUIContent.none, s_Styles.separator);
GUILayout.Label(VFXToolboxGUIUtility.Get(headerText), EditorStyles.boldLabel);
}
private class Styles
{
public readonly GUIStyle menuItem = (GUIStyle)"MenuItem";
public readonly GUIStyle separator = (GUIStyle)"sv_iconselector_sep";
}
}
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.GUI.cs.meta


fileFormatVersion: 2
guid: c6c1b3a301eecfe478e5fbb2575daaa2
timeCreated: 1471965339
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

192
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.InputFrames.cs


using UnityEngine;
using UnityEditorInternal;
using System.Collections.Generic;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class ImageSequencer : EditorWindow
{
private int m_InputFramesHashCode;
private void AddInputFrame(ReorderableList list, List<string> names)
{
if(names.Count> 0)
{
names.Sort();
foreach (string s in names)
{
Texture2D t = AssetDatabase.LoadAssetAtPath<Texture2D>(s);
if(t != null) m_processorStack.inputSequence.frames.Add(new ProcessingFrame(t));
}
previewCanvas.currentFrameIndex = 0;
m_processorStack.InvalidateAll();
UpdateViewport();
m_processorStack.SyncFramesToAsset(m_CurrentAsset);
UpdateInputTexturesHash();
}
}
private void AddInputFrame(ReorderableList list)
{
if (Selection.activeObject == null)
{
Debug.LogWarning("Could not add frames with no selection : please select input frames to add in the project view and click the add button. Or drag & drop directly into the Image Sequencer Editor Window");
return;
}
string[] guids;
List<string> names = new List<string>();
if(VFXToolboxUtility.IsDirectorySelected())
{
names.AddRange(VFXToolboxUtility.GetAllTexturesInPath(AssetDatabase.GetAssetPath(Selection.activeObject)));
}
else
{
guids = Selection.assetGUIDs;
foreach (string s in guids)
{
string path = AssetDatabase.GUIDToAssetPath(s);
Texture2D t = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if(t != null)
names.Add(path);
}
}
if(names.Count > 0)
{
Undo.RecordObject(m_CurrentAsset, "Add Input Frames");
AddInputFrame(list, names);
}
else
{
Debug.LogWarning("No suitable textures found in selection, make sure you selected either a directory containing textures or texture themselves in project view.");
}
}
private void ReorderInputFrame(ReorderableList list)
{
Undo.RecordObject(m_CurrentAsset, "Reorder Input Frames");
UpdateViewport();
m_processorStack.SyncFramesToAsset(m_CurrentAsset);
UpdateInputTexturesHash();
}
private void RemoveInputFrame(ReorderableList list)
{
int index = list.index;
previewCanvas.sequence.frames.RemoveAt(index);
if (list.count == 0)
previewCanvas.currentFrame = null;
else
{
if(previewCanvas.currentFrameIndex == index)
{
previewCanvas.currentFrameIndex = Mathf.Max(0, index - 1);
previewCanvas.currentFrame = previewCanvas.sequence.frames[previewCanvas.currentFrameIndex];
}
}
Undo.RecordObject(m_CurrentAsset, "Remove Input Frames");
m_processorStack.SyncFramesToAsset(m_CurrentAsset);
UpdateViewport();
UpdateInputTexturesHash();
if(m_processorStack.inputSequence.length > 0)
m_processorStack.InvalidateAll();
}
public void DrawInputFrameRListElement(Rect rect, int index, bool isActive, bool isFocused)
{
int numbering = (int)Mathf.Floor(Mathf.Log10(m_InputFramesReorderableList.list.Count))+1;
GUI.Label(rect, new GUIContent("#" + (index+1).ToString("D"+numbering.ToString())+ " - " + m_InputFramesReorderableList.list[index].ToString()));
}
public void SelectInputFrameRListElement(ReorderableList list)
{
if (list.count > 0 && list.index != -1)
{
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GUIDToAssetPath(m_CurrentAsset.inputFrameGUIDs[list.index]));
if (texture != null)
EditorGUIUtility.PingObject(texture);
m_PreviewCanvas.currentFrameIndex = list.index;
}
}
private int GetInputTexturesHashCode()
{
if(m_CurrentAsset != null)
{
var builder = new System.Text.StringBuilder();
foreach (string s in m_CurrentAsset.inputFrameGUIDs)
builder.Append(s);
return builder.ToString().GetHashCode();
}
else
return 0;
}
public void UpdateInputTexturesHash()
{
m_InputFramesHashCode = GetInputTexturesHashCode();
}
#region menu actions
private void MenuClearInputFrames()
{
Undo.RecordObject(m_CurrentAsset, "Clear All Input Frames");
// Remove frames and update hash
m_processorStack.RemoveAllInputFrames(m_CurrentAsset);
m_processorStack.SyncFramesToAsset(m_CurrentAsset);
m_InputFramesHashCode = GetInputTexturesHashCode();
// Update view
sidePanelViewMode = SidePanelMode.InputFrames;
m_CurrentProcessor = null;
m_LockedPreviewProcessor = null;
m_CurrentAsset.editSettings.lockedProcessor = -1;
m_CurrentAsset.editSettings.selectedProcessor = -1;
m_PreviewCanvas.sequence = m_processorStack.inputSequence;
// Request an update
Invalidate();
RefreshCanvas();
}
private void MenuSortInputFrames()
{
Undo.RecordObject(m_CurrentAsset, "Sort All Input Frames");
// Sort frames and update hash
m_processorStack.SortAllInputFrames(m_CurrentAsset);
m_InputFramesHashCode = GetInputTexturesHashCode();
LoadAsset(m_CurrentAsset);
// Request an update
Invalidate();
RefreshCanvas();
}
private void MenuReverseInputFrames()
{
Undo.RecordObject(m_CurrentAsset, "Reverse Input Frames Order");
// Inverse frame order and update hash
m_processorStack.ReverseAllInputFrames(m_CurrentAsset);
m_InputFramesHashCode = GetInputTexturesHashCode();
LoadAsset(m_CurrentAsset);
// Request an update
Invalidate();
RefreshCanvas();
}
#endregion
}
}

12
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.InputFrames.cs.meta


fileFormatVersion: 2
guid: 028e010e3dbf80043b38a23c11c3836f
timeCreated: 1471965338
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

185
com.unity.vfx-toolbox/ImageSequencer/Editor/ImageSequencer.Processors.cs


using UnityEngine;
using UnityEditorInternal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace UnityEditor.VFXToolbox.ImageSequencer
{
public partial class ImageSequencer : EditorWindow
{
[System.NonSerialized]
ProcessorDataProvider m_ProcessorDataProvider;
private void ShowAddProcessorMenu(ReorderableList list)
{
if(m_ProcessorDataProvider == null)
{
m_ProcessorDataProvider = new ProcessorDataProvider(m_processorStack, m_CurrentAsset);
}
FilterPopupWindow.Show(Event.current.mousePosition, m_ProcessorDataProvider);
}
private void MenuSelectProcessor(ReorderableList list)
{
if (m_CurrentAsset.editSettings.selectedProcessor == list.index)
return;
if (list.count > 0 && list.index != -1)
{
SetCurrentFrameProcessor(m_processorStack.processors[list.index], false);
}
else
SetCurrentFrameProcessor(null, false);
}
private void ReorderProcessor(ReorderableList list)
{
Undo.RecordObject(m_CurrentAsset, "Reorder Processors");
m_processorStack.ReorderProcessors(m_CurrentAsset);
m_processorStack.InvalidateAll();
UpdateViewport();
// If locked processor is present, update its index
if(m_LockedPreviewProcessor != null)
{
m_CurrentAsset.editSettings.lockedProcessor = m_processorStack.processors.IndexOf(m_LockedPreviewProcessor);
EditorUtility.SetDirty(m_CurrentAsset);
}
}
private void MenuRemoveProcessor(ReorderableList list)
{
int idx = list.index;
Undo.RecordObject(m_CurrentAsset, "Remove Processor : " + m_processorStack.processors[idx].GetName());
m_processorStack.RemoveProcessor(idx,m_CurrentAsset);
// If was locked, unlock beforehand
if (idx == m_CurrentAsset.editSettings.lockedProcessor)
SetCurrentFrameProcessor(null, true);
else if (idx < m_CurrentAsset.editSettings.lockedProcessor)
m_CurrentAsset.editSettings.lockedProcessor--;
if(m_processorStack.processors.Count > 0)
{
int newIdx = Mathf.Clamp(idx - 1, 0, m_processorStack.processors.Count - 1);
SetCurrentFrameProcessor(m_processorStack.processors[newIdx], false);
list.index = newIdx;
}
else
{
SetCurrentFrameProcessor(null, false);
list.index = -1;
}
previewCanvas.currentFrameIndex = 0;
m_processorStack.InvalidateAll();
UpdateViewport();
}
public void RefreshCanvas()
{
if(m_CurrentProcessor != null)
previewCanvas.sequence = m_CurrentProcessor.OutputSequence;
else
previewCanvas.sequence = m_processorStack.inputSequence;
previewCanvas.currentFrameIndex = Mathf.Clamp(previewCanvas.currentFrameIndex, 0, previewCanvas.sequence.length - 1);
UpdateViewport();
Invalidate();
}
public void SetCurrentFrameProcessor(FrameProcessor processor, bool wantLock)
{
if(wantLock)
{
m_LockedPreviewProcessor = processor;
if(processor != null)
{
Undo.RecordObject(m_CurrentAsset, "Lock Processor");
m_CurrentProcessor = processor;
m_CurrentAsset.editSettings.lockedProcessor = m_processorStack.processors.IndexOf(processor);
}
else
{
Undo.RecordObject(m_CurrentAsset, "Unlock Processor");
if(m_ProcessorsReorderableList.index != -1)
m_CurrentProcessor = m_processorStack.processors[Mathf.Min(m_ProcessorsReorderableList.index, m_processorStack.processors.Count-1)];
m_CurrentAsset.editSettings.lockedProcessor = -1;
}
}
else
{
bool needChange = (m_CurrentProcessor != processor);
if(needChange)
Undo.RecordObject(m_CurrentAsset, "Select Processor");
if(m_LockedPreviewProcessor == null)
m_CurrentProcessor = processor;
else
m_CurrentProcessor = m_LockedPreviewProcessor;
}
m_CurrentAsset.editSettings.selectedProcessor = m_processorStack.processors.IndexOf(processor);
RefreshCanvas();
EditorUtility.SetDirty(m_CurrentAsset);
}
public void DrawRListPreviewProcessorElement(Rect rect, int index, bool isActive, bool isFocused)
{
Rect toggle_rect = new Rect(rect.x + 4, rect.y, 16, rect.height);
Rect label_rect = new Rect(rect.x + 24, rect.y, rect.width - 24, rect.height);
using (new EditorGUI.DisabledScope(true))
{
GUI.Toggle(toggle_rect, m_processorStack.processors[index].Enabled, "");
}
GUI.Label( label_rect, string.Format("#{0} - {1} ",index+1, m_processorStack.processors[index].ToString()), VFXToolboxStyles.RListLabel);
}
public void DrawRListProcessorElement(Rect rect, int index, bool isActive, bool isFocused)
{
Rect toggle_rect = new Rect(rect.x + 4, rect.y, 16, rect.height);
Rect label_rect = new Rect(rect.x + 24, rect.y, rect.width - 24, rect.height);
Rect view_rect = new Rect(rect.x + rect.width - 37, rect.y, 19, 18);
Rect lock_rect = new Rect(rect.x + rect.width - 16, rect.y+1, 16, 14);
bool enabled = GUI.Toggle(toggle_rect, m_processorStack.processors[index].Enabled,"");
if(enabled != m_processorStack.processors[index].Enabled)
{
m_processorStack.processors[index].Enabled = enabled;
m_processorStack.processors[index].Invalidate();
RefreshCanvas();
}
GUI.Label( label_rect, string.Format("#{0} - {1} ",index+1, m_processorStack.processors[index].ToString()), VFXToolboxStyles.RListLabel);
if((m_LockedPreviewProcessor == null && isActive) || m_processorStack.processors.IndexOf(m_LockedPreviewProcessor) == index)
GUI.DrawTexture(view_rect, (Texture2D)EditorGUIUtility.LoadRequired("ViewToolOrbit On.png"));
bool locked = (m_LockedPreviewProcessor != null) && index == m_processorStack.processors.IndexOf(m_LockedPreviewProcessor);
if(isActive || locked)
{
bool b = GUI.Toggle(lock_rect, locked,"", styles.LockToggle);
if(b != locked)
{
if(b)
SetCurrentFrameProcessor(m_processorStack.processors[index],true);
else
SetCurrentFrameProcessor(null, true);
}
}
}
}
}

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存